ukui-panel/0000755000175000017500000000000013640356061011554 5ustar fengfengukui-panel/man/0000755000175000017500000000000013633070712012325 5ustar fengfengukui-panel/man/ukui-flash-disk.10000644000175000017500000000112213633070712015403 0ustar fengfeng.TH ukui "1" "2020-01-01" "UKUI 0.10.0" "UKUI Desktop Environment" .SH NAME ukui-flash-disk \- The Tray Application for the UKUI Desktop Environment .SH SYNOPSIS .B ukui-flash-disk .br .SH DESCRIPTION This is tray application for ukui-panel .SH BEHAVIOR Ukui-flash-disk tray application can detect whether there is external storage medium mounted Click to open the content of the storage medium .P Ukui-flash-disk can according to the detected signal to determine whether to display in the tray bar .SH "REPORTING BUGS" Report bugs to https://github.com/ukui/ukui-panel/issues .SH "SEE ALSO" ukui-panel/man/ukui-panel.10000644000175000017500000000216513632320722014463 0ustar fengfeng.TH ukui "1" "2019-08-01" "UKUI 0.10.0" "UKUI Desktop Panel Module" .SH NAME ukui-panel \- The Panel for the UKUI Desktop Environment .SH SYNOPSIS .B ukui-panel .br .SH DESCRIPTION This module adds a panel, with optional plugins, to the desktop. .SH BEHAVIOR The panel can be run independently of \fBUKUI\fR, autostarted at logon, and have multiple instances. A horizontal bottom panel shows by default on the desktop, but the size, autohide, and other attributes .P The panel is comprised of plugins which provide a visual widget; like the startmenu, taskbar, or quicklaunch. They can be added or removed in the panel Widget settings. .P Several plugins are loaded by default; the desktop menu and windows workspaces are also managed here. .SH CONFIGURATIONS Right-click over any plugin to reach the panel Configure settings option, or that of each respective plugin. .SH "REPORTING BUGS" Report bugs to https://github.com/ukui/ukui-panel/issues .SH "SEE ALSO" .SS Ukui Panel documentation can be found under "Help" by right-clicking on \fBukui-panel\fR. Further information may also be available at: http://wiki.ukui-desktop.org/docs .P ukui-panel/CHANGELOG0000644000175000017500000000005613632320722012763 0ustar fengfengUse 'git log' for a detailed list of changes. ukui-panel/cmake/0000755000175000017500000000000013633432261012633 5ustar fengfengukui-panel/cmake/BuildPlugin.cmake0000644000175000017500000000761313633432261016062 0ustar fengfeng# - Try to find the UDev library # Once done this will define # # UDEV_FOUND - system has UDev # UDEV_INCLUDE_DIR - the libudev include directory # UDEV_LIBS - The libudev libraries # Copyright (c) 2010, Rafael Fernández López, # Copyright (c) 2016, Luís Pereira, # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. MACRO (BUILD_UKUI_PLUGIN NAME) set(PROGRAM "ukui-panel") project(${PROGRAM}_${NAME}) set(PROG_SHARE_DIR ${CMAKE_INSTALL_FULL_DATAROOTDIR}/ukui/${PROGRAM}) set(PLUGIN_SHARE_DIR ${PROG_SHARE_DIR}/${NAME}) # Translations ********************************** # ukui_translate_ts(${PROJECT_NAME}_QM_FILES # UPDATE_TRANSLATIONS ${UPDATE_TRANSLATIONS} # SOURCES # ${HEADERS} # ${SOURCES} # ${MOCS} # ${UIS} # TEMPLATE # ${NAME} # INSTALL_DIR # ${UKUI_TRANSLATIONS_DIR}/${PROGRAM}/${NAME} # ) file (GLOB ${PROJECT_NAME}_DESKTOP_FILES_IN resources/*.desktop.in) ukui_translate_desktop(DESKTOP_FILES SOURCES ${${PROJECT_NAME}_DESKTOP_FILES_IN} ) ukui_plugin_translation_loader(QM_LOADER ${NAME} "ukui-panel") #************************************************ file (GLOB CONFIG_FILES resources/*.conf) if (NOT DEFINED PLUGIN_DIR) set (PLUGIN_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/${PROGRAM}) endif (NOT DEFINED PLUGIN_DIR) set(QTX_LIBRARIES Qt5::Widgets) if(QT_USE_QTXML) set(QTX_LIBRARIES ${QTX_LIBRARIES} Qt5::Xml) endif() if(QT_USE_QTDBUS) set(QTX_LIBRARIES ${QTX_LIBRARIES} Qt5::DBus) endif() list(FIND STATIC_PLUGINS ${NAME} IS_STATIC) set(SRC ${HEADERS} ${SOURCES} ${QM_LOADER} ${MOC_SOURCES} ${${PROJECT_NAME}_QM_FILES} ${RESOURCES} ${UIS} ${DESKTOP_FILES}) if (${IS_STATIC} EQUAL -1) # not static add_library(${NAME} MODULE ${SRC}) # build dynamically loadable modules install(TARGETS ${NAME} DESTINATION ${PLUGIN_DIR}) # install the *.so file else() # static add_library(${NAME} STATIC ${SRC}) # build statically linked lib endif() #target_link_libraries(${NAME} ${QTX_LIBRARIES} ${LIBRARIES} KF5::WindowSystem) target_link_libraries(${NAME} ${QTX_LIBRARIES} ${LIBRARIES} KF5::WindowSystem) install(FILES ${CONFIG_FILES} DESTINATION ${PLUGIN_SHARE_DIR}) install(FILES ${DESKTOP_FILES} DESTINATION ${PROG_SHARE_DIR}) ENDMACRO(BUILD_UKUI_PLUGIN) ukui-panel/cmake/ukui-build-tools/0000755000175000017500000000000013633432261016043 5ustar fengfengukui-panel/cmake/ukui-build-tools/ukui-build-tools-config-version.cmake0000644000175000017500000000402713633432261025206 0ustar fengfeng# UDEV_FOUND - system has UDev # UDEV_INCLUDE_DIR - the libudev include directory # UDEV_LIBS - The libudev libraries # Copyright (c) 2010, Rafael Fernández López, # Copyright (c) 2016, Luís Pereira, # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. set(PACKAGE_VERSION "0.6.0") if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) set(PACKAGE_VERSION_COMPATIBLE FALSE) else() set(PACKAGE_VERSION_COMPATIBLE TRUE) if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) set(PACKAGE_VERSION_EXACT TRUE) endif() endif() ukui-panel/cmake/ukui-build-tools/ukui-build-tools-config.cmake0000644000175000017500000000564013633432261023525 0ustar fengfeng# UDEV_FOUND - system has UDev # UDEV_INCLUDE_DIR - the libudev include directory # UDEV_LIBS - The libudev libraries # Copyright (c) 2010, Rafael Fernández López, # Copyright (c) 2016, Luís Pereira, # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. ####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() ####### ####### Any changes to this file will be overwritten by the next CMake run #### ####### The input file was ukui-build-tools-config.cmake.in ######## get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE) macro(set_and_check _var _file) set(${_var} "${_file}") if(NOT EXISTS "${_file}") message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") endif() endmacro() macro(check_required_components _NAME) foreach(comp ${${_NAME}_FIND_COMPONENTS}) if(NOT ${_NAME}_${comp}_FOUND) if(${_NAME}_FIND_REQUIRED_${comp}) set(${_NAME}_FOUND FALSE) endif() endif() endforeach() endmacro() #################################################################################### set(UKUI_CMAKE_MODULES_DIR "${PACKAGE_PREFIX_DIR}/share/cmake/ukui-build-tools/modules/") set(UKUI_CMAKE_FIND_MODULES_DIR "${PACKAGE_PREFIX_DIR}/share/cmake/ukui-build-tools/find-modules/") list(APPEND CMAKE_MODULE_PATH "${UKUI_CMAKE_MODULES_DIR}" "${UKUI_CMAKE_FIND_MODULES_DIR}" ) ukui-panel/cmake/ukui-build-tools/modules/0000755000175000017500000000000013633432261017513 5ustar fengfengukui-panel/cmake/ukui-build-tools/modules/Qt5PatchedLinguistToolsMacros.cmake0000644000175000017500000001130013633432261026357 0ustar fengfeng#============================================================================= # Copyright 2005-2011 Kitware, Inc. # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of Kitware, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= include(CMakeParseArguments) function(QT5_PATCHED_CREATE_TRANSLATION _qm_files) set(options) set(oneValueArgs) set(multiValueArgs OPTIONS) cmake_parse_arguments(_LUPDATE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) set(_lupdate_files ${_LUPDATE_UNPARSED_ARGUMENTS}) set(_lupdate_options ${_LUPDATE_OPTIONS}) set(_my_sources) set(_my_tsfiles) foreach(_file ${_lupdate_files}) get_filename_component(_ext ${_file} EXT) get_filename_component(_abs_FILE ${_file} ABSOLUTE) if(_ext MATCHES "ts") list(APPEND _my_tsfiles ${_abs_FILE}) else() list(APPEND _my_sources ${_abs_FILE}) endif() endforeach() foreach(_ts_file ${_my_tsfiles}) if(_my_sources) # make a list file to call lupdate on, so we don't make our commands too # long for some systems # get_filename_component(_ts_name ${_ts_file} NAME_WE) get_filename_component(_name ${_ts_file} NAME) string(REGEX REPLACE "^(.+)(\\.[^.]+)$" "\\1" _ts_name ${_name}) set(_ts_lst_file "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_ts_name}_lst_file") set(_lst_file_srcs) foreach(_lst_file_src ${_my_sources}) set(_lst_file_srcs "${_lst_file_src}\n${_lst_file_srcs}") endforeach() get_directory_property(_inc_DIRS INCLUDE_DIRECTORIES) foreach(_pro_include ${_inc_DIRS}) get_filename_component(_abs_include "${_pro_include}" ABSOLUTE) set(_lst_file_srcs "-I${_pro_include}\n${_lst_file_srcs}") endforeach() file(WRITE ${_ts_lst_file} "${_lst_file_srcs}") endif() add_custom_command(OUTPUT ${_ts_file} COMMAND ${Qt5_LUPDATE_EXECUTABLE} ARGS ${_lupdate_options} "@${_ts_lst_file}" -ts ${_ts_file} DEPENDS ${_my_sources} ${_ts_lst_file} VERBATIM) endforeach() qt5_patched_add_translation(${_qm_files} ${_my_tsfiles}) set(${_qm_files} ${${_qm_files}} PARENT_SCOPE) endfunction() function(QT5_PATCHED_ADD_TRANSLATION _qm_files) foreach(_current_FILE ${ARGN}) get_filename_component(_abs_FILE ${_current_FILE} ABSOLUTE) # get_filename_component(qm ${_abs_FILE} NAME_WE) get_filename_component(_name ${_abs_FILE} NAME) string(REGEX REPLACE "^(.+)(\\.[^.]+)$" "\\1" qm ${_name}) get_source_file_property(output_location ${_abs_FILE} OUTPUT_LOCATION) if(output_location) file(MAKE_DIRECTORY "${output_location}") set(qm "${output_location}/${qm}.qm") else() set(qm "${CMAKE_CURRENT_BINARY_DIR}/${qm}.qm") endif() add_custom_command(OUTPUT ${qm} COMMAND ${Qt5_LRELEASE_EXECUTABLE} ARGS ${_abs_FILE} -qm ${qm} DEPENDS ${_abs_FILE} VERBATIM ) list(APPEND ${_qm_files} ${qm}) endforeach() set(${_qm_files} ${${_qm_files}} PARENT_SCOPE) endfunction() ukui-panel/cmake/ukui-build-tools/modules/UKUiTranslateDesktop.cmake0000644000175000017500000000753113632320722024545 0ustar fengfeng#============================================================================= # The ukui_translate_desktop() function was copied from the # UKUi UKUiTranslate.cmake # # Original Author: Alexander Sokolov # # funtion ukui_translate_desktop(_RESULT # SOURCES # [TRANSLATION_DIR] translation_directory # ) # Output: # _RESULT The generated .desktop (.desktop) files # # Input: # # SOURCES List of input desktop files (.destktop.in) to be translated # (merged), relative to the CMakeList.txt. # # TRANSLATION_DIR Optional path to the directory with the .ts files, # relative to the CMakeList.txt. Defaults to # "translations". # #============================================================================= function(ukui_translate_desktop _RESULT) # Parse arguments *************************************** set(oneValueArgs TRANSLATION_DIR) set(multiValueArgs SOURCES) cmake_parse_arguments(_ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) # check for unknown arguments set(_UNPARSED_ARGS ${_ARGS_UNPARSED_ARGUMENTS}) if (NOT ${_UNPARSED_ARGS} STREQUAL "") MESSAGE(FATAL_ERROR "Unknown arguments '${_UNPARSED_ARGS}'.\n" "See ukui_translate_desktop() documentation for more information.\n" ) endif() if (NOT DEFINED _ARGS_SOURCES) set(${_RESULT} "" PARENT_SCOPE) return() else() set(_sources ${_ARGS_SOURCES}) endif() if (NOT DEFINED _ARGS_TRANSLATION_DIR) set(_translationDir "translations") else() set(_translationDir ${_ARGS_TRANSLATION_DIR}) endif() get_filename_component (_translationDir ${_translationDir} ABSOLUTE) foreach (_inFile ${_sources}) get_filename_component(_inFile ${_inFile} ABSOLUTE) get_filename_component(_fileName ${_inFile} NAME_WE) #Extract the real extension ............ get_filename_component(_fileExt ${_inFile} EXT) string(REPLACE ".in" "" _fileExt ${_fileExt}) #....................................... set(_outFile "${CMAKE_CURRENT_BINARY_DIR}/${_fileName}${_fileExt}") file(GLOB _translations ${_translationDir}/${_fileName}_*${_fileExt} ) set(_pattern "'\\[.*]\\s*='") if (_translations) list(SORT _translations) add_custom_command(OUTPUT ${_outFile} COMMAND grep -v -a "'#TRANSLATIONS_DIR='" ${_inFile} > ${_outFile} COMMAND grep -h -a ${_pattern} ${_translations} >> ${_outFile} COMMENT "Generating ${_fileName}${_fileExt}" ) else() add_custom_command(OUTPUT ${_outFile} COMMAND grep -v -a "'#TRANSLATIONS_DIR='" ${_inFile} > ${_outFile} COMMENT "Generating ${_fileName}${_fileExt}" ) endif() set(__result ${__result} ${_outFile}) # TX file *********************************************** set(_txFile "${CMAKE_BINARY_DIR}/tx/${_fileName}${_fileExt}.tx.sh") string(REPLACE "${CMAKE_SOURCE_DIR}/" "" _tx_translationDir ${_translationDir}) string(REPLACE "${CMAKE_SOURCE_DIR}/" "" _tx_inFile ${_inFile}) string(REPLACE "." "" _fileType ${_fileExt}) file(WRITE ${_txFile} "[ -f ${_inFile} ] || exit 0\n" "echo '[ukui.${_fileName}_${_fileType}]'\n" "echo 'type = DESKTOP'\n" "echo 'source_lang = en'\n" "echo 'source_file = ${_tx_inFile}'\n" "echo 'file_filter = ${_tx_translationDir}/${_fileName}_${_fileExt}'\n" "echo ''\n" ) endforeach() set(${_RESULT} ${__result} PARENT_SCOPE) endfunction(ukui_translate_desktop) ukui-panel/cmake/ukui-build-tools/modules/UKUiTranslateTs.cmake0000644000175000017500000001320513633432261023520 0ustar fengfeng#============================================================================= # Copyright 2014 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= # # funtion ukui_translate_ts(qmFiles # [USE_QT5 [Yes | No]] # [UPDATE_TRANSLATIONS [Yes | No]] # SOURCES # [UPDATE_OPTIONS] update_options # [TEMPLATE] translation_template # [TRANSLATION_DIR] translation_directory # [INSTALL_DIR] install_directory # [COMPONENT] component # ) # Output: # qmFiles The generated compiled translations (.qm) files # # Input: # USE_QT5 Optional flag to choose between Qt4 and Qt5. Defaults to Qt5 # # UPDATE_TRANSLATIONS Optional flag. Setting it to Yes, extracts and # compiles the translations. Setting it No, only # compiles them. # # UPDATE_OPTIONS Optional options to lupdate when UPDATE_TRANSLATIONS # is True. # # TEMPLATE Optional translations files base name. Defaults to # ${PROJECT_NAME}. An .ts extensions is added. # # TRANSLATION_DIR Optional path to the directory with the .ts files, # relative to the CMakeList.txt. Defaults to # "translations". # # INSTALL_DIR Optional destination of the file compiled files (qmFiles). # If not present no installation is performed # # COMPONENT Optional install component. Only effective if INSTALL_DIR # present. Defaults to "Runtime". # # We use our patched version to round a annoying bug. include(Qt5PatchedLinguistToolsMacros) function(ukui_translate_ts qmFiles) set(oneValueArgs USE_QT5 UPDATE_TRANSLATIONS TEMPLATE TRANSLATION_DIR INSTALL_DIR COMPONENT ) set(multiValueArgs SOURCES UPDATE_OPTIONS) cmake_parse_arguments(TR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if (NOT DEFINED TR_UPDATE_TRANSLATIONS) set(TR_UPDATE_TRANSLATIONS "No") endif() if (NOT DEFINED TR_UPDATE_OPTIONS) set(TR_UPDATE_OPTIONS "") endif() if (NOT DEFINED TR_USE_QT5) set(TR_USE_QT5 "Yes") endif() if(NOT DEFINED TR_TEMPLATE) set(TR_TEMPLATE "${PROJECT_NAME}") endif() if (NOT DEFINED TR_TRANSLATION_DIR) set(TR_TRANSLATION_DIR "translations") endif() get_filename_component(TR_TRANSLATION_DIR "${TR_TRANSLATION_DIR}" ABSOLUTE) if (EXISTS "${TR_TRANSLATION_DIR}") file(GLOB tsFiles "${TR_TRANSLATION_DIR}/${TR_TEMPLATE}_*.ts") set(templateFile "${TR_TRANSLATION_DIR}/${TR_TEMPLATE}.ts") endif () if(TR_USE_QT5) # Qt5 if (TR_UPDATE_TRANSLATIONS) qt5_patched_create_translation(QMS ${TR_SOURCES} ${templateFile} OPTIONS ${TR_UPDATE_OPTIONS} ) qt5_patched_create_translation(QM ${TR_SOURCES} ${tsFiles} OPTIONS ${TR_UPDATE_OPTIONS} ) else() qt5_patched_add_translation(QM ${tsFiles}) endif() else() # Qt4 if(TR_UPDATE_TRANSLATIONS) qt4_create_translation(QMS ${TR_SOURCES} ${templateFile} OPTIONS ${TR_UPDATE_OPTIONS} ) qt4_create_translation(QM ${TR_SOURCES} ${tsFiles} OPTIONS ${TR_UPDATE_OPTIONS} ) else() qt4_add_translation(QM ${tsFiles}) endif() endif() if(TR_UPDATE_TRANSLATIONS) add_custom_target("update_${TR_TEMPLATE}_ts" ALL DEPENDS ${QMS}) endif() if(DEFINED TR_INSTALL_DIR) if(NOT DEFINED TR_COMPONENT) set(TR_COMPONENT "Runtime") endif() install(FILES ${QM} DESTINATION "${TR_INSTALL_DIR}" COMPONENT "${TR_COMPONENT}" ) endif() set(${qmFiles} ${QM} PARENT_SCOPE) endfunction() ukui-panel/cmake/ukui-build-tools/modules/UKUiLibTranslationLoader.cpp.in0000644000175000017500000000060513632320722025434 0ustar fengfeng/* This file has been generated by the CMake ukui_app_translation_loader(). * It loads UKUi libraries translations. * * Attention: All changes will be overwritten!!! */ #include #include static void loadLibTranslation() { UKUi::Translator::translateLibrary(QStringLiteral("@catalog_name@")); } Q_COREAPP_STARTUP_FUNCTION(loadLibTranslation) ukui-panel/cmake/ukui-build-tools/modules/UKUiCompilerSettings.cmake0000644000175000017500000001771113633432261024555 0ustar fengfeng#============================================================================= # Copyright 2015 Luís Pereira # Copyright 2015 Palo Kisa # Copyright 2013 Hong Jen Yee (PCMan) # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= #----------------------------------------------------------------------------- # Build with release mode by default (turn on compiler optimizations) #----------------------------------------------------------------------------- if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() #----------------------------------------------------------------------------- # Honor visibility properties for all target types. # # The ``_VISIBILITY_PRESET`` and # ``VISIBILITY_INLINES_HIDDEN`` target properties affect visibility # of symbols during dynamic linking. When first introduced these properties # affected compilation of sources only in shared libraries, module libraries, # and executables with the ``ENABLE_EXPORTS`` property set. This # was sufficient for the basic use cases of shared libraries and executables # with plugins. However, some sources may be compiled as part of static # libraries or object libraries and then linked into a shared library later. # CMake 3.3 and above prefer to honor these properties for sources compiled # in all target types. This policy preserves compatibility for projects # expecting the properties to work only for some target types. # # The ``OLD`` behavior for this policy is to ignore the visibility properties # for static libraries, object libraries, and executables without exports. # The ``NEW`` behavior for this policy is to honor the visibility properties # for all target types. # # This policy was introduced in CMake version 3.3. CMake version # 3.3.0 warns when the policy is not set and uses ``OLD`` behavior. Use # the ``cmake_policy()`` command to set it to ``OLD`` or ``NEW`` # explicitly. #----------------------------------------------------------------------------- if(COMMAND CMAKE_POLICY) if (POLICY CMP0063) cmake_policy(SET CMP0063 NEW) endif() endif() include(CheckCXXCompilerFlag) #----------------------------------------------------------------------------- # Global definitions #----------------------------------------------------------------------------- add_definitions( -DQT_USE_QSTRINGBUILDER -DQT_NO_FOREACH ) if (CMAKE_BUILD_TYPE MATCHES "Debug") add_definitions(-DQT_STRICT_ITERATORS) endif() #----------------------------------------------------------------------------- # Detect Clang compiler #----------------------------------------------------------------------------- if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(UKUI_COMPILER_IS_CLANGCXX 1) endif() #----------------------------------------------------------------------------- # Set visibility to hidden to hide symbols, unless they're exported manually # in the code #----------------------------------------------------------------------------- set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) #----------------------------------------------------------------------------- # Disable exceptions #----------------------------------------------------------------------------- if (CMAKE_COMPILER_IS_GNUCXX OR UKUI_COMPILER_IS_CLANGCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") endif() #----------------------------------------------------------------------------- # Common warning flags #----------------------------------------------------------------------------- set(__UKUI_COMMON_WARNING_FLAGS "-Wall -Wextra -Wchar-subscripts -Wno-long-long -Wpointer-arith -Wundef -Wformat-security") #----------------------------------------------------------------------------- # Warning flags #----------------------------------------------------------------------------- if (CMAKE_COMPILER_IS_GNUCXX OR UKUI_COMPILER_IS_CLANGCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${__UKUI_COMMON_WARNING_FLAGS} -Wnon-virtual-dtor -Woverloaded-virtual -Wpedantic") endif() if (UKUI_COMPILER_IS_CLANGCXX) # qCDebug(), qCWarning, etc trigger a very verbose warning, about.... nothing. Disable it. # Found when building ukui-session. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-gnu-zero-variadic-macro-arguments") endif() #----------------------------------------------------------------------------- # Linker flags # Do not allow undefined symbols #----------------------------------------------------------------------------- if (CMAKE_COMPILER_IS_GNUCXX OR UKUI_COMPILER_IS_CLANGCXX) # -Bsymbolic-functions: replace dynamic symbols used internally in # shared libs with direct addresses. set(SYMBOLIC_FLAGS "-Wl,-Bsymbolic-functions -Wl,-Bsymbolic" ) set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined ${SYMBOLIC_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) set(CMAKE_MODULE_LINKER_FLAGS "-Wl,--no-undefined ${SYMBOLIC_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) set(CMAKE_EXE_LINKER_FLAGS "${SYMBOLIC_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) endif() #----------------------------------------------------------------------------- # CXX14 requirements - no checks, we just set it #----------------------------------------------------------------------------- set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD 14 CACHE STRING "C++ ISO Standard") #----------------------------------------------------------------------------- # Enable colored diagnostics for the CLang/Ninja combination #----------------------------------------------------------------------------- if (CMAKE_GENERATOR STREQUAL "Ninja" AND # Rationale: https://public.kitware.com/Bug/view.php?id=15502 ((CMAKE_COMPILER_IS_GNUCXX AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR (UKUI_COMPILER_IS_CLANGCXX AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5))) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=always") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always") endif() #----------------------------------------------------------------------------- # Enable exceptions for an target # # ukui_enable_target_exceptions( # # ) # #----------------------------------------------------------------------------- function(ukui_enable_target_exceptions target mode) target_compile_options(${target} ${mode} "$<$,$>:-fexceptions>" ) endfunction() ukui-panel/cmake/ukui-build-tools/modules/Qt5TranslationLoader.cpp.in0000644000175000017500000000213113632320722024635 0ustar fengfeng/* This file has been generated by the CMake qt_translation_loader(). * It loads Qt application translations. * * Attention: All changes will be overwritten!!! */ #include #include #include #include #include static void loadQtTranslation() { QString locale = QLocale::system().name(); QTranslator *qtTranslator = new QTranslator(qApp); if (qtTranslator->load(QLatin1String("qt_") + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { qApp->installTranslator(qtTranslator); } else { delete qtTranslator; } QTranslator *appTranslator = new QTranslator(qApp); if (appTranslator->load(QString::fromLocal8Bit("@translations_dir@/@catalog_name@_%1.qm").arg(locale))) { QCoreApplication::installTranslator(appTranslator); } else if (locale == QLatin1String("C") || locale.startsWith(QLatin1String("en"))) { // English is the default. It's translated anyway. delete appTranslator; } } Q_COREAPP_STARTUP_FUNCTION(loadQtTranslation) ukui-panel/cmake/ukui-build-tools/modules/UKUiTranslationLoader.cmake0000644000175000017500000000763413633432261024712 0ustar fengfeng#============================================================================= # Copyright 2014 Luís Pereira # Copyright 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= # # These functions enables "automatic" translation loading in UKUi Qt5 apps # and libs. They generate a .cpp file that takes care of everything. The # user doesn't have to do anything in the source code. # # Typical use: # include(UKUiTranslationLoader) # ukui_app_translation_loader(ukui-app_QM_LOADER ${PROJECT_NAME}) # add_executable(${PROJECT_NAME} # ${ukui-app_QM_LOADER} # ... # ) # ukui_app_translation_loader( ) # The generated .cpp file is added to # Translations catalog to be loaded function(ukui_app_translation_loader source_files catalog_name) configure_file( #${UKUI_CMAKE_MODULES_DIR}/UKUiAppTranslationLoader.cpp.in ../cmake/ukui-build-tools/modules/UKUiAppTranslationLoader.cpp.in UKUiAppTranslationLoader.cpp @ONLY ) set(${source_files} ${${source_files}} ${CMAKE_CURRENT_BINARY_DIR}/UKUiAppTranslationLoader.cpp PARENT_SCOPE) endfunction() # ukui_lib_translation_loader( ) # The generated .cpp file is added to # Translations catalog to be loaded function(ukui_lib_translation_loader source_files catalog_name) configure_file( #${UKUI_CMAKE_MODULES_DIR}/UKUiLibTranslationLoader.cpp.in ../cmake/ukui-build-tools/modules/UKUiLibTranslationLoader.cpp.in UKUiLibTranslationLoader.cpp @ONLY ) set(${source_files} ${${source_files}} ${CMAKE_CURRENT_BINARY_DIR}/UKUiLibTranslationLoader.cpp PARENT_SCOPE) endfunction() # ukui_plugin_translation_loader( ) # The generated .cpp file is added to # Translations catalog to be loaded # Plugin type. Example: ukui-panel function(ukui_plugin_translation_loader source_files catalog_name plugin_type) configure_file( #${UKUI_CMAKE_MODULES_DIR}/UKUiPluginTranslationLoader.cpp.in #/usr/share/cmake/ukui-build-tools/modules/UKUiPluginTranslationLoader.cpp.in ../cmake/ukui-build-tools/modules/UKUiPluginTranslationLoader.cpp.in UKUiPluginTranslationLoader.cpp @ONLY ) set(${source_files} ${${source_files}} ${CMAKE_CURRENT_BINARY_DIR}/UKUiPluginTranslationLoader.cpp PARENT_SCOPE) endfunction() ukui-panel/cmake/ukui-build-tools/modules/UKUiCreatePkgConfigFile.cmake0000644000175000017500000002077613633432261025062 0ustar fengfeng#============================================================================= # Copyright 2015 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #=============================================================================# # ukui_create_pkgconfig_file(PACKAGE_NAME # VERSION # [PREFIX ] # [EXEC_PREFIX ] # [INCLUDEDIR_PREFIX ] # [INCLUDEDIRS ... ] # [LIBDIR_PREFIX ] # [DESCRIPTIVE_NAME ] # [DESCRIPTION ] # [URL ] # [REQUIRES ... ] # [REQUIRES_PRIVATE ... ] # [LIB_INSTALLDIR ] # [CFLAGS ] # [PATH ] # [INSTALL] # [COMPONENT] component) # # # PACKAGE_NAME and VERSION are mandatory. Everything else is optional include(CMakeParseArguments) include(GNUInstallDirs) function(ukui_create_pkgconfig_file) set(options INSTALL) set(oneValueArgs PACKAGE_NAME PREFIX EXEC_PREFIX INCLUDEDIR_PREFIX LIBDIR_PREFIX DESCRIPTIVE_NAME DESCRIPTION URL VERSION PATH COMPONENT ) set(multiValueArgs INCLUDEDIRS REQUIRES REQUIRES_PRIVATE CONFLICTS CFLAGS LIBS LIBS_PRIVATE ) cmake_parse_arguments(USER "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if (USER_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unknown keywords given to create_pkgconfig_file(): \"${USER_UNPARSED_ARGUMENTS}\"") endif() # Check for mandatory args. Abort if not set if (NOT DEFINED USER_PACKAGE_NAME) message(FATAL_ERROR "Required argument PACKAGE_NAME missing in generate_pkgconfig_file() call") else() set(_PKGCONFIG_PACKAGE_NAME "${USER_PACKAGE_NAME}") endif() if (NOT DEFINED USER_VERSION) message(FATAL_ERROR "Required argument VERSION missing in generate_pkgconfig_file() call") else() set(_PKGCONFIG_VERSION "${USER_VERSION}") endif() # Optional args if (NOT DEFINED USER_PREFIX) set(_PKGCONFIG_PREFIX "${CMAKE_INSTALL_PREFIX}") endif() if (NOT DEFINED USER_EXEC_PREFIX) set(_PKGCONFIG_EXEC_PREFIX "\${prefix}") endif() if (NOT DEFINED USER_INCLUDEDIR_PREFIX) set(_PKGCONFIG_INCLUDEDIR_PREFIX "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") endif() if (NOT DEFINED USER_LIBDIR_PREFIX) set(_PKGCONFIG_LIBDIR_PREFIX "\${prefix}/${CMAKE_INSTALL_LIBDIR}") endif() if (NOT DEFINED USER_DESCRIPTIVE_NAME) set(_PKGCONFIG_DESCRIPTIVE_NAME "") else() set(_PKGCONFIG_DESCRIPTIVE_NAME "${USER_DESCRIPTIVE_NAME}") endif() if (DEFINED USER_INCLUDEDIRS) set(tmp "") foreach(dir ${USER_INCLUDEDIRS}) if (NOT IS_ABSOLUTE "${dir}") list(APPEND tmp "-I\${includedir}/${dir}") endif() endforeach() string(REPLACE ";" " " _INCLUDEDIRS "${tmp}") endif() if (DEFINED USER_REQUIRES) string(REPLACE ";" ", " _PKGCONFIG_REQUIRES "${USER_REQUIRES}") endif() if (DEFINED USER_REQUIRES_PRIVATE) string(REPLACE ";" ", " _PKGCONFIG_REQUIRES_PRIVATE "${USER_REQUIRES_PRIVATE}") else() set(_PKGCONFIG_REQUIRES_PRIVATE "") endif() if (NOT DEFINED USER_CFLAGS) set(_PKGCONFIG_CFLAGS "-I\${includedir} ${_INCLUDEDIRS}") endif() if (NOT DEFINED USER_LIBS) set(_PKGCONFIG_LIBS "-L\${libdir}") else() set(tmp "-L\${libdir}") set(_libs "${USER_LIBS}") foreach(lib ${_libs}) list(APPEND tmp "-l${lib}") endforeach() string(REPLACE ";" " " _PKGCONFIG_LIBS "${tmp}") endif() if (NOT DEFINED USER_LIBS_PRIVATE) set(PKGCONFIG_LIBS "-L\${libdir}") else() set(tmp "") set(_libs "${USER_LIBS_PRIVATE}") foreach(lib ${_libs}) list(APPEND tmp "-l${lib}") endforeach() string(REPLACE ";" " " _PKGCONFIG_LIBS_PRIVATE "${tmp}") endif() if (DEFINED USER_DESCRIPTION) set(_PKGCONFIG_DESCRIPTION "${USER_DESCRIPTION}") else() set(_PKGCONFIG_DESCRIPTION "") endif() if (DEFINED USER_URL) set(_PKFCONFIG_URL "${USER_URL}") else() set(_PKGCONFIG_URL "") endif() if (NOT DEFINED USER_PATH) set(_PKGCONFIG_FILE "${PROJECT_BINARY_DIR}/${_PKGCONFIG_PACKAGE_NAME}.pc") else() if (IS_ABSOLUTE "${USER_PATH}") set(_PKGCONFIG_FILE "${USER_PATH}/${_PKGCONFIG_PACKAGE_NAME}.pc") else() set(_PKGCONFIG_FILE "${PROJECT_BINARY_DIR}/${USER_PATH}/${_PKGCONFIG_PACKAGE_NAME}.pc") endif() endif() # Write the .pc file FILE(WRITE "${_PKGCONFIG_FILE}" "# file generated by create_pkgconfig_file()\n" "prefix=${_PKGCONFIG_PREFIX}\n" "exec_prefix=${_PKGCONFIG_EXEC_PREFIX}\n" "libdir=${_PKGCONFIG_LIBDIR_PREFIX}\n" "includedir=${_PKGCONFIG_INCLUDEDIR_PREFIX}\n" "\n" "Name: ${_PKGCONFIG_DESCRIPTIVE_NAME}\n" ) if (NOT "${_PKGCONFIG_DESCRIPTION}" STREQUAL "") FILE(APPEND ${_PKGCONFIG_FILE} "Description: ${_PKGCONFIG_DESCRIPTION}\n" ) endif() if (NOT "${_PKGCONFIG_URL}" STREQUAL "") FILE(APPEND ${_PKGCONFIG_FILE} "URL: ${_PKGCONFIG_URL}\n") endif() FILE(APPEND ${_PKGCONFIG_FILE} "Version: ${_PKGCONFIG_VERSION}\n") if (NOT "${_PKGCONFIG_REQUIRES}" STREQUAL "") FILE(APPEND ${_PKGCONFIG_FILE} "Requires: ${_PKGCONFIG_REQUIRES}\n") endif() if (NOT "${_PKGCONFIG_REQUIRES_PRIVATE}" STREQUAL "") FILE(APPEND ${_PKGCONFIG_FILE} "Requires.private: ${_PKGCONFIG_REQUIRES_PRIVATE}\n" ) endif() FILE(APPEND ${_PKGCONFIG_FILE} "Cflags: ${_PKGCONFIG_CFLAGS}\n" "Libs: ${_PKGCONFIG_LIBS}\n" ) if (NOT "${_PKGCONFIG_LIBS_PRIVATE}" STREQUAL "") FILE(APPEND ${_PKGCONFIG_FILE} "Libs.private: ${_PKGCONFIG_REQUIRES_PRIVATE}\n" ) endif() if (DEFINED USER_INSTALL) # FreeBSD loves to install files to different locations # https://www.freebsd.org/doc/handbook/dirstructure.html if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") set(_PKGCONFIG_INSTALL_DESTINATION "libdata/pkgconfig") else() set(_PKGCONFIG_INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") endif() if (DEFINED USER_COMPONENT) set(_COMPONENT "${USER_COMPONENT}") else() set(_COMPONENT "Devel") endif() install(FILES "${_PKGCONFIG_FILE}" DESTINATION "${_PKGCONFIG_INSTALL_DESTINATION}" COMPONENT "${_COMPONENT}") endif() endfunction() ukui-panel/cmake/ukui-build-tools/modules/Qt5TranslationLoader.cmake0000644000175000017500000000464613633432261024546 0ustar fengfeng#============================================================================= # Copyright 2014 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= # # These functions enables "automatic" translation loading in Qt5 apps # and libs. They generate a .cpp file that takes care of everything. The # user doesn't have to do anything in the source code. # # qt5_translation_loader( ) # # Output: # Appends the generated file to this variable. # # Input: # Full path name to the translations dir. # Translation catalog to be loaded. function(qt5_translation_loader source_files translations_dir catalog_name) configure_file( ${UKUI_CMAKE_MODULES_DIR}/Qt5TranslationLoader.cpp.in Qt5TranslationLoader.cpp @ONLY ) set(${source_files} ${${source_files}} ${CMAKE_CURRENT_BINARY_DIR}/Qt5TranslationLoader.cpp PARENT_SCOPE) endfunction() ukui-panel/cmake/ukui-build-tools/modules/UKUiConfigVars.cmake0000644000175000017500000000343513632320722023316 0ustar fengfeng# The module defines the following variables # # UKUI_SHARE_DIR - This allows to install and read the configs from non-standard locations # # UKUI_TRANSLATIONS_DIR - The default translations directory # # UKUI_ETC_XDG_DIR - XDG standards expects system-wide configuration files in the # /etc/xdg/ukui location. Unfortunately QSettings we are using internally # can be overriden in the Qt compilation time to use different path for # system-wide configs. (for example configure ... -sysconfdir /etc/settings ...) # This path can be found calling Qt's qmake: # qmake -query QT_INSTALL_CONFIGURATION # # UKUI_DATA_DIR - UKUi base directory relative to which data files should # be searched.Defaults to CMAKE_INSTALL_FULL_DATADIR. It's # added to XDG_DATA_DIRS by the startukui script. set(UKUI_LIBRARY_NAME "ukui") set(UKUI_RELATIVE_SHARE_DIR "ukui") set(UKUI_SHARE_DIR "/usr/share/ukui") set(UKUI_RELATIVE_TRANSLATIONS_DIR "ukui/translations") set(UKUI_TRANSLATIONS_DIR "/usr/share/ukui/translations") set(UKUI_GRAPHICS_DIR "/usr/share/ukui/graphics") set(UKUI_ETC_XDG_DIR "/etc/xdg") set(UKUI_DATA_DIR "/usr/share") add_definitions("-DUKUI_RELATIVE_SHARE_DIR=\"${UKUI_RELATIVE_SHARE_DIR}\"") add_definitions("-DUKUI_SHARE_DIR=\"${UKUI_SHARE_DIR}\"") add_definitions("-DUKUI_RELATIVE_SHARE_TRANSLATIONS_DIR=\"${UKUI_RELATIVE_TRANSLATIONS_DIR}\"") add_definitions("-DUKUI_SHARE_TRANSLATIONS_DIR=\"${UKUI_TRANSLATIONS_DIR}\"") add_definitions("-DUKUI_GRAPHICS_DIR=\"${UKUI_GRAPHICS_DIR}\"") add_definitions("-DUKUI_ETC_XDG_DIR=\"${UKUI_ETC_XDG_DIR}\"") add_definitions("-DUKUI_DATA_DIR=\"${UKUI_DATA_DIR}\"") ukui-panel/cmake/ukui-build-tools/modules/UKUiTranslate.cmake0000644000175000017500000000366113633432261023216 0ustar fengfeng#============================================================================= # Copyright 2014 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= # # An convenience module that loads all the UKUi translations modules at once. include(/usr/share/cmake/ukui-build-tools/modules/UKUiTranslateTs.cmake) include(/usr/share/cmake/ukui-build-tools/modules/UKUiTranslateDesktop.cmake) include(/usr/share/cmake/ukui-build-tools/modules/UKUiTranslationLoader.cmake) ukui-panel/cmake/ukui-build-tools/modules/ECMFindModuleHelpers.cmake0000644000175000017500000003237013633432261024420 0ustar fengfeng#.rst: # ECMFindModuleHelpers # -------------------- # # Helper macros for find modules: ecm_find_package_version_check(), # ecm_find_package_parse_components() and # ecm_find_package_handle_library_components(). # # :: # # ecm_find_package_version_check() # # Prints warnings if the CMake version or the project's required CMake version # is older than that required by extra-cmake-modules. # # :: # # ecm_find_package_parse_components( # RESULT_VAR # KNOWN_COMPONENTS [ [...]] # [SKIP_DEPENDENCY_HANDLING]) # # This macro will populate with a list of components found in # _FIND_COMPONENTS, after checking that all those components are in the # list of KNOWN_COMPONENTS; if there are any unknown components, it will print # an error or warning (depending on the value of _FIND_REQUIRED) and call # return(). # # The order of components in is guaranteed to match the order they # are listed in the KNOWN_COMPONENTS argument. # # If SKIP_DEPENDENCY_HANDLING is not set, for each component the variable # __component_deps will be checked for dependent components. # If is listed in _FIND_COMPONENTS, then all its (transitive) # dependencies will also be added to . # # :: # # ecm_find_package_handle_library_components( # COMPONENTS [ [...]] # [SKIP_DEPENDENCY_HANDLING]) # [SKIP_PKG_CONFIG]) # # Creates an imported library target for each component. The operation of this # macro depends on the presence of a number of CMake variables. # # The __lib variable should contain the name of this library, # and __header variable should contain the name of a header # file associated with it (whatever relative path is normally passed to # '#include'). __header_subdir variable can be used to specify # which subdirectory of the include path the headers will be found in. # ecm_find_package_components() will then search for the library # and include directory (creating appropriate cache variables) and create an # imported library target named ::. # # Additional variables can be used to provide additional information: # # If SKIP_PKG_CONFIG, the __pkg_config variable is set, and # pkg-config is found, the pkg-config module given by # __pkg_config will be searched for and used to help locate the # library and header file. It will also be used to set # __VERSION. # # Note that if version information is found via pkg-config, # __FIND_VERSION can be set to require a particular version # for each component. # # If SKIP_DEPENDENCY_HANDLING is not set, the INTERFACE_LINK_LIBRARIES property # of the imported target for will be set to contain the imported # targets for the components listed in __component_deps. # _FOUND will also be set to false if any of the compoments in # __component_deps are not found. This requires the components # in __component_deps to be listed before in the # COMPONENTS argument. # # The following variables will be set: # # ``_TARGETS`` # the imported targets # ``_LIBRARIES`` # the found libraries # ``_INCLUDE_DIRS`` # the combined required include directories for the components # ``_DEFINITIONS`` # the "other" CFLAGS provided by pkg-config, if any # ``_VERSION`` # the value of ``__VERSION`` for the first component that # has this variable set (note that components are searched for in the order # they are passed to the macro), although if it is already set, it will not # be altered # # Note that these variables are never cleared, so if # ecm_find_package_handle_library_components() is called multiple times with # different components (typically because of multiple find_package() calls) then # ``_TARGETS``, for example, will contain all the targets found in any # call (although no duplicates). # # Since pre-1.0.0. #============================================================================= # Copyright 2014 Alex Merry # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include(CMakeParseArguments) macro(ecm_find_package_version_check module_name) if(CMAKE_VERSION VERSION_LESS 3.1.0) message(FATAL_ERROR "CMake 3.1.0 is required by ukui-build-tools!") endif() if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 3.1.0) message(AUTHOR_WARNING "Your project should require at least CMake 3.1.0!") endif() endmacro() macro(ecm_find_package_parse_components module_name) set(ecm_fppc_options SKIP_DEPENDENCY_HANDLING) set(ecm_fppc_oneValueArgs RESULT_VAR) set(ecm_fppc_multiValueArgs KNOWN_COMPONENTS DEFAULT_COMPONENTS) cmake_parse_arguments(ECM_FPPC "${ecm_fppc_options}" "${ecm_fppc_oneValueArgs}" "${ecm_fppc_multiValueArgs}" ${ARGN}) if(ECM_FPPC_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unexpected arguments to ecm_find_package_parse_components: ${ECM_FPPC_UNPARSED_ARGUMENTS}") endif() if(NOT ECM_FPPC_RESULT_VAR) message(FATAL_ERROR "Missing RESULT_VAR argument to ecm_find_package_parse_components") endif() if(NOT ECM_FPPC_KNOWN_COMPONENTS) message(FATAL_ERROR "Missing KNOWN_COMPONENTS argument to ecm_find_package_parse_components") endif() if(NOT ECM_FPPC_DEFAULT_COMPONENTS) set(ECM_FPPC_DEFAULT_COMPONENTS ${ECM_FPPC_KNOWN_COMPONENTS}) endif() if(${module_name}_FIND_COMPONENTS) set(ecm_fppc_requestedComps ${${module_name}_FIND_COMPONENTS}) if(NOT ECM_FPPC_SKIP_DEPENDENCY_HANDLING) # Make sure deps are included foreach(ecm_fppc_comp ${ecm_fppc_requestedComps}) foreach(ecm_fppc_dep_comp ${${module_name}_${ecm_fppc_comp}_component_deps}) list(FIND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}" ecm_fppc_index) if("${ecm_fppc_index}" STREQUAL "-1") if(NOT ${module_name}_FIND_QUIETLY) message(STATUS "${module_name}: ${ecm_fppc_comp} requires ${${module_name}_${ecm_fppc_comp}_component_deps}") endif() list(APPEND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}") endif() endforeach() endforeach() else() message(STATUS "Skipping dependency handling for ${module_name}") endif() list(REMOVE_DUPLICATES ecm_fppc_requestedComps) # This makes sure components are listed in the same order as # KNOWN_COMPONENTS (potentially important for inter-dependencies) set(${ECM_FPPC_RESULT_VAR}) foreach(ecm_fppc_comp ${ECM_FPPC_KNOWN_COMPONENTS}) list(FIND ecm_fppc_requestedComps "${ecm_fppc_comp}" ecm_fppc_index) if(NOT "${ecm_fppc_index}" STREQUAL "-1") list(APPEND ${ECM_FPPC_RESULT_VAR} "${ecm_fppc_comp}") list(REMOVE_AT ecm_fppc_requestedComps ${ecm_fppc_index}) endif() endforeach() # if there are any left, they are unknown components if(ecm_fppc_requestedComps) set(ecm_fppc_msgType STATUS) if(${module_name}_FIND_REQUIRED) set(ecm_fppc_msgType FATAL_ERROR) endif() if(NOT ${module_name}_FIND_QUIETLY) message(${ecm_fppc_msgType} "${module_name}: requested unknown components ${ecm_fppc_requestedComps}") endif() return() endif() else() set(${ECM_FPPC_RESULT_VAR} ${ECM_FPPC_DEFAULT_COMPONENTS}) endif() endmacro() macro(ecm_find_package_handle_library_components module_name) set(ecm_fpwc_options SKIP_PKG_CONFIG SKIP_DEPENDENCY_HANDLING) set(ecm_fpwc_oneValueArgs) set(ecm_fpwc_multiValueArgs COMPONENTS) cmake_parse_arguments(ECM_FPWC "${ecm_fpwc_options}" "${ecm_fpwc_oneValueArgs}" "${ecm_fpwc_multiValueArgs}" ${ARGN}) if(ECM_FPWC_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unexpected arguments to ecm_find_package_handle_components: ${ECM_FPWC_UNPARSED_ARGUMENTS}") endif() if(NOT ECM_FPWC_COMPONENTS) message(FATAL_ERROR "Missing COMPONENTS argument to ecm_find_package_handle_components") endif() include(FindPackageHandleStandardArgs) find_package(PkgConfig) foreach(ecm_fpwc_comp ${ECM_FPWC_COMPONENTS}) set(ecm_fpwc_dep_vars) set(ecm_fpwc_dep_targets) if(NOT SKIP_DEPENDENCY_HANDLING) foreach(ecm_fpwc_dep ${${module_name}_${ecm_fpwc_comp}_component_deps}) list(APPEND ecm_fpwc_dep_vars "${module_name}_${ecm_fpwc_dep}_FOUND") list(APPEND ecm_fpwc_dep_targets "${module_name}::${ecm_fpwc_dep}") endforeach() endif() if(NOT ECM_FPWC_SKIP_PKG_CONFIG AND ${module_name}_${ecm_fpwc_comp}_pkg_config) pkg_check_modules(PKG_${module_name}_${ecm_fpwc_comp} ${${module_name}_${ecm_fpwc_comp}_pkg_config}) endif() find_path(${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR NAMES ${${module_name}_${ecm_fpwc_comp}_header} HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_INCLUDE_DIRS} PATH_SUFFIXES ${${module_name}_${ecm_fpwc_comp}_header_subdir} ) find_library(${module_name}_${ecm_fpwc_comp}_LIBRARY NAMES ${${module_name}_${ecm_fpwc_comp}_lib} HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_LIBRARY_DIRS} ) set(${module_name}_${ecm_fpwc_comp}_VERSION "${PKG_${module_name}_${ecm_fpwc_comp}_VERSION}") if(NOT ${module_name}_VERSION) set(${module_name}_VERSION ${${module_name}_${ecm_fpwc_comp}_VERSION}) endif() find_package_handle_standard_args(${module_name}_${ecm_fpwc_comp} FOUND_VAR ${module_name}_${ecm_fpwc_comp}_FOUND REQUIRED_VARS ${module_name}_${ecm_fpwc_comp}_LIBRARY ${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR ${ecm_fpwc_dep_vars} VERSION_VAR ${module_name}_${ecm_fpwc_comp}_VERSION ) mark_as_advanced( ${module_name}_${ecm_fpwc_comp}_LIBRARY ${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR ) if(${module_name}_${ecm_fpwc_comp}_FOUND) list(APPEND ${module_name}_LIBRARIES "${${module_name}_${ecm_fpwc_comp}_LIBRARY}") list(APPEND ${module_name}_INCLUDE_DIRS "${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}") set(${module_name}_DEFINITIONS ${${module_name}_DEFINITIONS} ${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS}) if(NOT TARGET ${module_name}::${ecm_fpwc_comp}) add_library(${module_name}::${ecm_fpwc_comp} UNKNOWN IMPORTED) set_target_properties(${module_name}::${ecm_fpwc_comp} PROPERTIES IMPORTED_LOCATION "${${module_name}_${ecm_fpwc_comp}_LIBRARY}" INTERFACE_COMPILE_OPTIONS "${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS}" INTERFACE_INCLUDE_DIRECTORIES "${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}" INTERFACE_LINK_LIBRARIES "${ecm_fpwc_dep_targets}" ) endif() list(APPEND ${module_name}_TARGETS "${module_name}::${ecm_fpwc_comp}") endif() endforeach() if(${module_name}_LIBRARIES) list(REMOVE_DUPLICATES ${module_name}_LIBRARIES) endif() if(${module_name}_INCLUDE_DIRS) list(REMOVE_DUPLICATES ${module_name}_INCLUDE_DIRS) endif() if(${module_name}_DEFINITIONS) list(REMOVE_DUPLICATES ${module_name}_DEFINITIONS) endif() if(${module_name}_TARGETS) list(REMOVE_DUPLICATES ${module_name}_TARGETS) endif() endmacro() ukui-panel/cmake/ukui-build-tools/modules/UKUiPluginTranslationLoader.cpp.in0000644000175000017500000000175213632320722026170 0ustar fengfeng/* This file has been generated by the CMake ukui_plugin_translation_loader(). * It loads UKUi plugin translations. * * Attention: All changes will be overwritten!!! */ #include #include #include "../panel/common/ukuitranslator.h" /* Dummy helper symbol for referencing. * In case plugin is linked as static (lib*.a) unreferenced objects are stripped in linking time * => we need to reference some symbol from this file to be not stripped as a whole. */ void * loadPluginTranslation_@catalog_name@_helper = nullptr; static void loadPluginTranslation() { //XXX: we don't use the QStringLiteral here because it causes SEGFAULT in static finalization time // (the string is stored in static QHash and it's destructor can reference already deleted static QString (generated by QStringLiteral)) UKUi::Translator::translatePlugin(QLatin1String("@catalog_name@"), QLatin1String("@plugin_type@")); } Q_COREAPP_STARTUP_FUNCTION(loadPluginTranslation) ukui-panel/cmake/ukui-build-tools/modules/UKUiAppTranslationLoader.cpp.in0000644000175000017500000000063413632320722025450 0ustar fengfeng/* This file has been generated by the CMake ukui_app_translation_loader(). * It loads UKUi application translations. * * Attention: All changes will be overwritten!!! */ #include #include "../panel/common/ukuitranslator.h" static void loadAppTranslation() { UKUi::Translator::translateApplication(QStringLiteral("@catalog_name@")); } Q_COREAPP_STARTUP_FUNCTION(loadAppTranslation) ukui-panel/cmake/ukui-build-tools/modules/UKUiCreatePortableHeaders.cmake0000644000175000017500000001037413633432261025450 0ustar fengfeng#============================================================================= # Copyright 2015 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= # ukui_create_portable_headers( # HEADER_NAMES [ [...]] # [OUTPUT_DIR ] # ) # # Creates portable headers; e.g.: # Creates XdgAction from xdgaction.h # XdgAction contents: # #include "xdgaction.h" # # Output: # portable_headers File locations of the created headers # # Input: # HEADER_NAMES Header CamelCaseNames. An CamelCaseName header will be created # that includes camelcasename.h file # # OUTPUT_DIR Specifies where the files will be created. Defaults to # ``${CMAKE_CURRENT_BINARY_DIR}``. If the value is an relative path, it # will be appended to ``${CMAKE_CURRENT_BINARY_DIR}``. # # Use: # set(PUBLIC_CLASSES MyClass YourClass) # ukui_create_portable_headers(PORTABLE_HEADERS ${PUBLIC_CLASSES}) # PORTABLE_HEADER is an return value that contains the full name of the # generated headers. function(ukui_create_portable_headers outfiles) set(options) set(oneValueArgs OUTPUT_DIR PATH_PREFIX NAME_PREFIX) set(multiValueArgs HEADER_NAMES) cmake_parse_arguments(USER "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if (USER_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unknown keywords given to ukui_create_portable_headers(): \"${USER_UNPARSED_ARGUMENTS}\"") endif() if (NOT DEFINED USER_HEADER_NAMES) message(FATAL_ERROR "Required argument HEADER_NAMES missing in ukui_create_portable_headers() call") else() set(_HEADER_NAMES "${USER_HEADER_NAMES}") endif() if (NOT DEFINED USER_OUTPUT_DIR) set(_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") else() if (IS_ABSOLUTE "${USER_OUTPUT_DIR}") set(_OUTPUT_DIR "${USER_OUTPUT_DIR}") else() set(_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/${USER_OUTPUT_DIR}") endif() endif() if (NOT DEFINED USER_PATH_PREFIX) set(_PATH_PREFIX "") else() set(_PATH_PREFIX "${USER_PATH_PREFIX}") endif() if (NOT DEFINED USER_NAME_PREFIX) set(_NAME_PREFIX "") else() set(_NAME_PREFIX "${USER_NAME_PREFIX}") endif() set(class_list ${_HEADER_NAMES}) foreach(f ${class_list}) string(TOLOWER "${f}.h" _filename) if ("${_PATH_PREFIX}" STREQUAL "") file(WRITE "${_OUTPUT_DIR}/${f}" "#include \"${_NAME_PREFIX}${_filename}\"") else() file(WRITE "${_OUTPUT_DIR}/${f}" "#include \"${_PATH_PREFIX}${_NAME_PREFIX}/${_filename}\"") endif() list(APPEND ${outfiles} "${_OUTPUT_DIR}/${f}") endforeach() set(${outfiles} ${${outfiles}} PARENT_SCOPE) endfunction() ukui-panel/cmake/ukui-build-tools/modules/UKUiPreventInSourceBuilds.cmake0000644000175000017500000000627413633432261025522 0ustar fengfeng#============================================================================= # Copyright (c) 2018 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= function(ukui_prevent_in_source_builds) # Handle smarties with symlinks get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH) get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH) if("${srcdir}" STREQUAL "${bindir}") # We are in a in source build message("##############################################################") message("# In Source Build detected.") message("# UKUi does not support in source builds.") message("# Out of source build is required.") message("#") message("# The general approach to out of source builds is:") message("# mkdir build") message("# cd build") message("# cmake ") message("# make") message("#") message("# An in source build was attemped. Some files were created.") message("# Use 'git status' to check them. Remove them with:") message("# cd ") message("#") message("# # Don’t actually remove anything, just show what would be done") message("# git clean -n -d") message("#") message("# # Actually remove the files") message("# git clean -f -d") message("#") message("# checkout files out of the index") message("# git checkout --") message("##############################################################") message(FATAL_ERROR "Aborting configuration") endif() endfunction() ukui_prevent_in_source_builds() ukui-panel/cmake/ukui-build-tools/find-modules/0000755000175000017500000000000013633432261020431 5ustar fengfengukui-panel/cmake/ukui-build-tools/find-modules/FindUDev.cmake0000644000175000017500000000527313633432261023106 0ustar fengfeng# - Try to find the UDev library # Once done this will define # # UDEV_FOUND - system has UDev # UDEV_INCLUDE_DIR - the libudev include directory # UDEV_LIBS - The libudev libraries # Copyright (c) 2010, Rafael Fernández López, # Copyright (c) 2016, Luís Pereira, # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. find_package(PkgConfig) pkg_check_modules(PC_UDEV libudev) find_path(UDEV_INCLUDE_DIR libudev.h HINTS ${PC_UDEV_INCLUDEDIR} ${PC_UDEV_INCLUDE_DIRS}) find_library(UDEV_LIBS udev HINTS ${PC_UDEV_LIBDIR} ${PC_UDEV_LIBRARY_DIRS}) if(UDEV_INCLUDE_DIR AND UDEV_LIBS) include(CheckFunctionExists) include(CMakePushCheckState) cmake_push_check_state() set(CMAKE_REQUIRED_LIBRARIES ${UDEV_LIBS} ) cmake_pop_check_state() endif() set(UDEV_VERSION_STRING ${PC_UDEV_VERSION}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(UDev REQUIRED_VARS UDEV_INCLUDE_DIR UDEV_LIBS VERSION_VAR ${UDEV_VERSION_STRING}) mark_as_advanced(UDEV_INCLUDE_DIR UDEV_LIBS) include(FeatureSummary) set_package_properties(UDev PROPERTIES URL "https://www.kernel.org/pub/linux/utils/kernel/hotplug/udev/udev.html" DESCRIPTION "Linux dynamic device management") ukui-panel/cmake/ukui-build-tools/find-modules/FindXKBCommon.cmake0000644000175000017500000001022313633432261024027 0ustar fengfeng#.rst: # FindXKBCommon # ----------- # # Try to find XKBCommon. # # This is a component-based find module, which makes use of the COMPONENTS # and OPTIONAL_COMPONENTS arguments to find_module. The following components # are available:: # # XKBCommon X11 # # If no components are specified, this module will act as though all components # were passed to OPTIONAL_COMPONENTS. # # This module will define the following variables, independently of the # components searched for or found: # # ``XKBCommon_FOUND`` # TRUE if (the requested version of) XKBCommon is available # ``XKBCommon_VERSION`` # Found XKBCommon version # ``XKBCommon_TARGETS`` # A list of all targets imported by this module (note that there may be more # than the components that were requested) # ``XKBCommon_LIBRARIES`` # This can be passed to target_link_libraries() instead of the imported # targets # ``XKBCommon_INCLUDE_DIRS`` # This should be passed to target_include_directories() if the targets are # not used for linking # ``XKBCommon_DEFINITIONS`` # This should be passed to target_compile_options() if the targets are not # used for linking # # For each searched-for components, ``XKBCommon__FOUND`` will be set to # TRUE if the corresponding XKBCommon library was found, and FALSE otherwise. If # ``XKBCommon__FOUND`` is TRUE, the imported target # ``XKBCommon::`` will be defined. #============================================================================= # Copyright 2017 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Documentation adapted from the KF5 FindWayland module. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= include(ECMFindModuleHelpers) ecm_find_package_version_check(XKBCommon) set(XKBCommon_known_components XKBCommon X11) unset(XKBCommon_XKBCommon_component_deps) set(XKBCommon_XKBCommon_pkg_config "xkbcommon") set(XKBCommon_XKBCommon_lib "xkbcommon") set(XKBCommon_XKBCommon_header "xkbcommon/xkbcommon.h") set(XKBCommon_X11_component_deps XKBCommon) set(XKBCommon_X11_pkg_config "xkbcommon-x11") set(XKBCommon_X11_lib "xkbcommon-x11") set(XKBCommon_X11_header "xkbcommon/xkbcommon-x11.h") ecm_find_package_parse_components(XKBCommon RESULT_VAR XKBCommon_components KNOWN_COMPONENTS ${XKBCommon_known_components} ) ecm_find_package_handle_library_components(XKBCommon COMPONENTS ${XKBCommon_components} ) find_package_handle_standard_args(XKBCommon FOUND_VAR XKBCommon_FOUND REQUIRED_VARS XKBCommon_LIBRARIES XKBCommon_INCLUDE_DIRS VERSION_VAR XKBCommon_VERSION HANDLE_COMPONENTS ) include(FeatureSummary) set_package_properties(XKBCommon PROPERTIES URL "https://xkbcommon.org" DESCRIPTION "A library to handle keyboard descriptions" ) ukui-panel/cmake/ukui-build-tools/find-modules/FindGLIB.cmake0000644000175000017500000001304113633432261022750 0ustar fengfeng# - Try to find Glib and its components (gio, gobject etc) # Once done, this will define # # GLIB_FOUND - system has Glib # GLIB_INCLUDE_DIRS - the Glib include directories # GLIB_LIBRARIES - link these to use Glib # # Optionally, the COMPONENTS keyword can be passed to find_package() # and Glib components can be looked for. Currently, the following # components can be used, and they define the following variables if # found: # # gio: GLIB_GIO_LIBRARIES # gobject: GLIB_GOBJECT_LIBRARIES # gmodule: GLIB_GMODULE_LIBRARIES # gthread: GLIB_GTHREAD_LIBRARIES # # Note that the respective _INCLUDE_DIR variables are not set, since # all headers are in the same directory as GLIB_INCLUDE_DIRS. # # Copyright (C) 2012 Raphael Kubo da Costa # Copyright (C) 2016 Luís Pereira # Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS # IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. find_package(PkgConfig) pkg_check_modules(PC_GLIB glib-2.0) find_library(GLIB_LIBRARIES NAMES glib-2.0 HINTS ${PC_GLIB_LIBDIR} ${PC_GLIB_LIBRARY_DIRS} ) # Files in glib's main include path may include glibconfig.h, which, # for some odd reason, is normally in $LIBDIR/glib-2.0/include. get_filename_component(_GLIB_LIBRARY_DIR ${GLIB_LIBRARIES} PATH) find_path(GLIBCONFIG_INCLUDE_DIR NAMES glibconfig.h HINTS ${PC_LIBDIR} ${PC_LIBRARY_DIRS} ${_GLIB_LIBRARY_DIR} ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0/include ) find_path(GLIB_INCLUDE_DIR NAMES glib.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0 ) set(GLIB_INCLUDE_DIRS ${GLIB_INCLUDE_DIR} ${GLIBCONFIG_INCLUDE_DIR}) # Version detection if (EXISTS "${GLIBCONFIG_INCLUDE_DIR}/glibconfig.h") file(READ "${GLIBCONFIG_INCLUDE_DIR}/glibconfig.h" GLIBCONFIG_H_CONTENTS) string(REGEX MATCH "#define GLIB_MAJOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") set(GLIB_VERSION_MAJOR "${CMAKE_MATCH_1}") string(REGEX MATCH "#define GLIB_MINOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") set(GLIB_VERSION_MINOR "${CMAKE_MATCH_1}") string(REGEX MATCH "#define GLIB_MICRO_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") set(GLIB_VERSION_MICRO "${CMAKE_MATCH_1}") set(GLIB_VERSION "${GLIB_VERSION_MAJOR}.${GLIB_VERSION_MINOR}.${GLIB_VERSION_MICRO}") endif () # Additional Glib components. We only look for libraries, as not all of them # have corresponding headers and all headers are installed alongside the main # glib ones. foreach (_component ${GLIB_FIND_COMPONENTS}) if (${_component} STREQUAL "gio") find_library(GLIB_GIO_LIBRARIES NAMES gio-2.0 HINTS ${_GLIB_LIBRARY_DIR}) set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GIO_LIBRARIES) elseif (${_component} STREQUAL "gobject") find_library(GLIB_GOBJECT_LIBRARIES NAMES gobject-2.0 HINTS ${_GLIB_LIBRARY_DIR}) set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GOBJECT_LIBRARIES) elseif (${_component} STREQUAL "gmodule") find_library(GLIB_GMODULE_LIBRARIES NAMES gmodule-2.0 HINTS ${_GLIB_LIBRARY_DIR}) set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GMODULE_LIBRARIES) elseif (${_component} STREQUAL "gthread") find_library(GLIB_GTHREAD_LIBRARIES NAMES gthread-2.0 HINTS ${_GLIB_LIBRARY_DIR}) set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GTHREAD_LIBRARIES) elseif (${_component} STREQUAL "gio-unix") pkg_check_modules(GIO_UNIX gio-unix-2.0) find_path(GLIB_GIO_UNIX_INCLUDE_DIR NAMES gio/gunixconnection.h HINTS ${GIO_UNIX_INCLUDEDIR} PATH_SUFFIXES gio-unix-2.0) set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GIO_UNIX_INCLUDE_DIR) endif () endforeach () include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLIB REQUIRED_VARS GLIB_INCLUDE_DIRS GLIB_LIBRARIES ${ADDITIONAL_REQUIRED_VARS} VERSION_VAR GLIB_VERSION) mark_as_advanced( GLIBCONFIG_INCLUDE_DIR GLIB_GIO_LIBRARIES GLIB_GIO_UNIX_INCLUDE_DIR GLIB_GMODULE_LIBRARIES GLIB_GOBJECT_LIBRARIES GLIB_GTHREAD_LIBRARIES GLIB_INCLUDE_DIR GLIB_INCLUDE_DIRS GLIB_LIBRARIES ) ukui-panel/cmake/ukui-build-tools/find-modules/FindXdgUserDirs.cmake0000644000175000017500000000456413633432261024450 0ustar fengfeng#============================================================================= # Copyright 2015 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= # FindXdgUserDirs # # Try to find xdg-user-dirs-update. # # If the xdg-user-dirs-update executable is not in your PATH, you can provide # an alternative name or full path location with the # `XdgUserDirsUpdate_EXECUTABLE` variable. # # This will define the following variables: # # `XdgUserDirs_FOUND` # True if xdg-user-dirs-update is available. # # `XdgUserDirsUpdate_EXECUTABLE` # The xdg-user-dirs-update executable. # # Find xdg-user-dirs-update find_program(XdgUserDirsUpdate_EXECUTABLE NAMES xdg-user-dirs-update) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(XdgUserDirs FOUND_VAR XdgUserDirs_FOUND REQUIRED_VARS XdgUserDirsUpdate_EXECUTABLE ) mark_as_advanced(XdgUserDirsUpdate_EXECUTABLE) ukui-panel/cmake/ukui-build-tools/find-modules/FindExif.cmake0000644000175000017500000000722313633432261023133 0ustar fengfeng# Copyright (c) 2010, Rafael Fernández López, # Copyright (c) 2016, Luís Pereira, # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. #.rst: # FindExif # ----------- # # Try to find the Exif library # # Once done this will define # # :: # # EXIF_FOUND - System has the Exif library # EXIF_INCLUDE_DIR - The Exif library include directory # EXIF_INCLUDE_DIRS - Location of the headers needed to use the Exif library # EXIF_LIBRARIES - The libraries needed to use the Exif library # EXIF_DEFINITIONS - Compiler switches required for using the Exif library # EXIF_VERSION_STRING - the version of the Exif library found # use pkg-config to get the directories and then use these values # in the find_path() and find_library() calls find_package(PkgConfig) pkg_check_modules(PC_EXIF libexif) set(EXIF_DEFINITIONS ${PC_EXIF_CFLAGS_OTHER}) find_path(EXIF_INCLUDE_DIR NAMES libexif/exif-data.h HINTS ${PC_EXIF_INCLUDEDIR} ${PC_EXIF_INCLUDE_DIRS} PATH_SUFFIXES libexif ) find_library(EXIF_LIBRARIES NAMES exif libexif HINTS ${PC_EXIF_LIBDIR} ${PC_EXIF_LIBRARY_DIRS} ) # iterate over all dependencies unset(FD_LIBRARIES) foreach(depend ${PC_EXIF_LIBRARIES}) find_library(_DEPEND_LIBRARIES NAMES ${depend} HINTS ${PC_EXIF_LIBDIR} ${PC_EXIF_LIBRARY_DIRS} ) if (_DEPEND_LIBRARIES) list(APPEND FD_LIBRARIES ${_DEPEND_LIBRARIES}) endif() unset(_DEPEND_LIBRARIES CACHE) endforeach() set(EXIF_VERSION_STRING ${PC_EXIF_VERSION}) set(EXIF_INCLUDE_DIR ${PC_EXIF_INCLUDEDIR}) list(APPEND EXIF_INCLUDE_DIRS ${EXIF_INCLUDE_DIR} ${PC_EXIF_INCLUDE_DIRS} ) list(REMOVE_DUPLICATES EXIF_INCLUDE_DIRS) list(APPEND EXIF_LIBRARIES ${FD_LIBRARIES} ) list(REMOVE_DUPLICATES EXIF_LIBRARIES) # handle the QUIETLY and REQUIRED arguments and set EXIF_FOUND to TRUE if # all listed variables are TRUE include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Exif REQUIRED_VARS EXIF_LIBRARIES EXIF_INCLUDE_DIR EXIF_INCLUDE_DIRS VERSION_VAR EXIF_VERSION_STRING) mark_as_advanced(EXIF_INCLUDE_DIR EXIF_LIBRARIES) ukui-panel/cmake/ukui-build-tools/find-modules/FindMenuCache.cmake0000644000175000017500000000772213633432261024074 0ustar fengfeng# Copyright (c) 2010, Rafael Fernández López, # Copyright (c) 2016, Luís Pereira, # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. #.rst: # FindMenuCache # ----------- # # Try to find the MenuCache library # # Once done this will define # # :: # # MENUCACHE_FOUND - System has the MenuCache library # MENUCACHE_INCLUDE_DIR - The MenuCache library include directory # MENUCACHE_INCLUDE_DIRS - Location of the headers needed to use the MenuCache library # MENUCACHE_LIBRARIES - The libraries needed to the MenuCache library # MENUCACHE_DEFINITIONS - Compiler switches required for using the MenuCache library # MENUCACHE_VERSION_STRING - the version of MenuCache library found # use pkg-config to get the directories and then use these values # in the find_path() and find_library() calls find_package(PkgConfig) pkg_check_modules(PC_MENUCACHE libmenu-cache) set(MENUCACHE_DEFINITIONS ${PC_MENUCACHE_CFLAGS_OTHER}) find_path(MENUCACHE_INCLUDE_DIRS NAMES menu-cache.h menu-cache/menu-cache.h HINTS ${PC_MENUCACHE_INCLUDEDIR} ${PC_MENUCACHE_INCLUDE_DIRS} PATH_SUFFIXES libmenu-cache ) find_library(MENUCACHE_LIBRARIES NAMES menu-cache libmenu-cache HINTS ${PC_MENUCACHE_LIBDIR} ${PC_MENUCACHE_LIBRARY_DIRS} ) # iterate over all dependencies unset(FD_LIBRARIES) foreach(depend ${PC_MENUCACHE_LIBRARIES}) find_library(_DEPEND_LIBRARIES NAMES ${depend} HINTS ${PC_MENUCACHE_LIBDIR} ${PC_MENUCACHE_LIBRARY_DIRS} ) if (_DEPEND_LIBRARIES) list(APPEND FD_LIBRARIES ${_DEPEND_LIBRARIES}) endif() unset(_DEPEND_LIBRARIES CACHE) endforeach() set(MENUCACHE_VERSION_STRING ${PC_MENUCACHE_VERSION}) set(MENUCACHE_INCLUDE_DIR ${PC_MENUCACHE_INCLUDEDIR}) list(APPEND MENUCACHE_INCLUDE_DIRS ${MENUCACHE_INCLUDE_DIR} ${PC_MENUCACHE_INCLUDE_DIRS} ) list(REMOVE_DUPLICATES MENUCACHE_INCLUDE_DIRS) list(APPEND MENUCACHE_LIBRARIES ${FD_LIBRARIES} ) list(REMOVE_DUPLICATES MENUCACHE_LIBRARIES) # handle the QUIETLY and REQUIRED arguments and set MENUCACHE_FOUND to TRUE if # all listed variables are TRUE include(FindPackageHandleStandardArgs) find_package_handle_standard_args(MenuCache REQUIRED_VARS MENUCACHE_LIBRARIES MENUCACHE_INCLUDE_DIR MENUCACHE_INCLUDE_DIRS VERSION_VAR MENUCACHE_VERSION_STRING) mark_as_advanced(MENUCACHE_INCLUDE_DIR MENUCACHE_LIBRARIES) ukui-panel/cmake/ukui-build-tools/find-modules/FindXCB.cmake0000644000175000017500000000366513633432261022662 0ustar fengfeng#.rst: # FindXCB # ------- # # Find XCB libraries # # Tries to find xcb libraries on unix systems. # # - Be sure to set the COMPONENTS to the components you want to link to # - The XCB_LIBRARIES variable is set ONLY to your COMPONENTS list # - To use only a specific component check the XCB_LIBRARIES_${COMPONENT} variable # # The following values are defined # # :: # # XCB_FOUND - True if xcb is available # XCB_INCLUDE_DIRS - Include directories for xcb # XCB_LIBRARIES - List of libraries for xcb # XCB_DEFINITIONS - List of definitions for xcb # #============================================================================= # Copyright (c) 2015 Jari Vetoniemi # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Distributed under the OSI-approved BSD License (the "License"); # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= include(FeatureSummary) set_package_properties(XCB PROPERTIES URL "https://xcb.freedesktop.org/" DESCRIPTION "X protocol C-language Binding") find_package(PkgConfig) pkg_check_modules(PC_XCB xcb ${XCB_FIND_COMPONENTS}) find_library(XCB_LIBRARIES xcb HINTS ${PC_XCB_LIBRARY_DIRS}) find_path(XCB_INCLUDE_DIRS xcb/xcb.h PATH_SUFFIXES xcb HINTS ${PC_XCB_INCLUDE_DIRS}) foreach(COMPONENT ${XCB_FIND_COMPONENTS}) find_library(XCB_LIBRARIES_${COMPONENT} ${COMPONENT} HINTS ${PC_XCB_LIBRARY_DIRS}) list(APPEND XCB_LIBRARIES ${XCB_LIBRARIES_${COMPONENT}}) mark_as_advanced(XCB_LIBRARIES_${COMPONENT}) endforeach(COMPONENT ${XCB_FIND_COMPONENTS}) set(XCB_DEFINITIONS ${PC_XCB_CFLAGS_OTHER}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(XCB DEFAULT_MSG XCB_LIBRARIES XCB_INCLUDE_DIRS) mark_as_advanced(XCB_INCLUDE_DIRS XCB_LIBRARIES XCB_DEFINITIONS) ukui-panel/plugin-nightmode/0000755000175000017500000000000013643566146015040 5ustar fengfengukui-panel/plugin-nightmode/nightmode.cpp0000644000175000017500000000654513643566146017534 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include "../panel/customstyle.h" #define NIGHT_MODE_LIGHT "light" #define NIGHE_MODE_NIGHT "night" #define NIGHT_MODE_KEY "nightmode" #define NIGHT_MODE_CONTROL "org.ukui.control-center.panel.plugins" NightMode::NightMode(const IUKUIPanelPluginStartupInfo &startupInfo) : QObject(), IUKUIPanelPlugin(startupInfo) { mButton=new NightModeButton; mButton->setStyle(new CustomStyle()); // mButton->paintTooltipStyle(); mButton->setToolTip(tr("nightmode")); realign(); } NightMode::~NightMode(){ } void NightMode::realign() { mButton->setFixedSize(32,32); mButton->setIconSize(QSize(24,24)); } NightModeButton::NightModeButton(){ this->setIcon(QIcon("/usr/share/ukui-panel/panel/img/nightmode-night.svg")); const QByteArray id(NIGHT_MODE_CONTROL); if(QGSettings::isSchemaInstalled(id)) { gsettings = new QGSettings(id); connect(gsettings, &QGSettings::changed, this, [=] (const QString &key) { if (key == "nightmode") { bool mode=gsettings->get(NIGHT_MODE_KEY).toBool(); if(mode==true){ this->setIcon(QIcon("/usr/share/ukui-panel/panel/img/nightmode-light.svg")); this->setToolTip(tr("nightmode open")); } else{ this->setIcon(QIcon("/usr/share/ukui-panel/panel/img/nightmode-night.svg")); this->setToolTip(tr("nightmode close")); } } }); } this->setIcon(QIcon("/usr/share/ukui-panel/panel/img/nightmode-light.svg")); } NightModeButton::~NightModeButton(){ delete gsettings; } void NightModeButton::mousePressEvent(QMouseEvent* event) { const Qt::MouseButton b = event->button(); if (Qt::LeftButton == b){ bool mode=true; if(gsettings->keys().contains("nightmode")){ mode=gsettings->get("nightmode").toBool(); } if(mode==true){ gsettings->set("nightmode", false); system("killall redshift"); } else{ gsettings->set("nightmode", true); // system("redshift -t 5700:3600 -g 0.8 -m randr -v"); if(QFileInfo::exists(QString("/usr/bin/redshift"))) { QProcess *process =new QProcess(this); process->startDetached("redshift -t 5700:3600 -g 0.8 -m randr -v"); } else{ QMessageBox::information(this,"Error",tr("please install redshift first")); } } } QWidget::mousePressEvent(event); } ukui-panel/plugin-nightmode/nightmode.h0000644000175000017500000000420413640356061017155 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include #include "../panel/plugin.h" #include "../panel/ukuipanel.h" #include "../panel/ukuicontrolstyle.h" class NightModeButton:public UkuiToolButton { Q_OBJECT public: NightModeButton(); ~NightModeButton(); protected: void mousePressEvent(QMouseEvent* event); QGSettings *gsettings; }; class NightMode : public QObject, public IUKUIPanelPlugin { Q_OBJECT public: NightMode(const IUKUIPanelPluginStartupInfo &startupInfo); ~NightMode(); virtual QWidget *widget() { return mButton; } virtual QString themeId() const { return QStringLiteral("startmenu"); } void realign(); virtual IUKUIPanelPlugin::Flags flags() const { return PreferRightAlignment | HaveConfigDialog ; } private: NightModeButton *mButton; }; class NightModeLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "lxqt.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new NightMode(startupInfo); } }; #endif ukui-panel/plugin-nightmode/resources/0000755000175000017500000000000013633070712017036 5ustar fengfengukui-panel/plugin-nightmode/resources/nightmode.desktop.in0000644000175000017500000000030113633070712023006 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=NightMode Comment=NightMode Icon=nightmode #TRANSLATIONS_DIR=../translations Name=夜间模式 Comment=夜间模式切换按键 ukui-panel/plugin-nightmode/CMakeLists.txt0000644000175000017500000000046013633070712017564 0ustar fengfengset(PLUGIN "nightmode") set(HEADERS nightmode.h ) set(SOURCES nightmode.cpp ) set(UIS ) find_package(PkgConfig) pkg_check_modules(Gsetting REQUIRED gsettings-qt) include_directories(${Gsetting_INCLUDE_DIRS}) set(LIBRARIES Qt5Xdg ${Gsetting_LIBRARIES} ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel/plugin-taskbar/0000755000175000017500000000000013642614010014470 5ustar fengfengukui-panel/plugin-taskbar/ukuitaskbarconfiguration.cpp0000644000175000017500000001424013633355350022323 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuitaskbarconfiguration.h" #include "ui_ukuitaskbarconfiguration.h" #include UKUITaskbarConfiguration::UKUITaskbarConfiguration(PluginSettings *settings, QWidget *parent): UKUIPanelPluginConfigDialog(settings, parent), ui(new Ui::UKUITaskbarConfiguration) { setAttribute(Qt::WA_DeleteOnClose); setObjectName("TaskbarConfigurationWindow"); ui->setupUi(this); connect(ui->buttons, SIGNAL(clicked(QAbstractButton*)), this, SLOT(dialogButtonsAction(QAbstractButton*))); ui->buttonStyleCB->addItem(tr("Icon and text"), "IconText"); ui->buttonStyleCB->addItem(tr("Only icon"), "Icon"); ui->buttonStyleCB->addItem(tr("Only text"), "Text"); ui->showDesktopNumCB->addItem(tr("Current"), 0); //Note: in KWindowSystem desktops are numbered from 1..N const int desk_cnt = KWindowSystem::numberOfDesktops(); for (int i = 1; desk_cnt >= i; ++i) ui->showDesktopNumCB->addItem(QString("%1 - %2").arg(i).arg(KWindowSystem::desktopName(i)), i); loadSettings(); /* We use clicked() and activated(int) because these signals aren't emitting after programmaticaly change of state */ connect(ui->limitByDesktopCB, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(ui->limitByDesktopCB, &QCheckBox::stateChanged, ui->showDesktopNumCB, &QWidget::setEnabled); connect(ui->showDesktopNumCB, SIGNAL(activated(int)), this, SLOT(saveSettings())); connect(ui->limitByScreenCB, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(ui->limitByMinimizedCB, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(ui->raiseOnCurrentDesktopCB, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(ui->buttonStyleCB, SIGNAL(activated(int)), this, SLOT(saveSettings())); // connect(ui->buttonWidthSB, SIGNAL(valueChanged(int)), this, SLOT(saveSettings())); connect(ui->buttonHeightSB, SIGNAL(valueChanged(int)), this, SLOT(saveSettings())); connect(ui->autoRotateCB, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(ui->middleClickCB, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(ui->groupingGB, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(ui->showGroupOnHoverCB, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(ui->iconByClassCB, &QCheckBox::clicked, this, &UKUITaskbarConfiguration::saveSettings); connect(ui->cycleOnWheelScroll, &QCheckBox::clicked, this, &UKUITaskbarConfiguration::saveSettings); } UKUITaskbarConfiguration::~UKUITaskbarConfiguration() { delete ui; } void UKUITaskbarConfiguration::loadSettings() { const bool showOnlyOneDesktopTasks = settings().value("showOnlyOneDesktopTasks", false).toBool(); ui->limitByDesktopCB->setChecked(showOnlyOneDesktopTasks); ui->showDesktopNumCB->setCurrentIndex(ui->showDesktopNumCB->findData(settings().value("showDesktopNum", 0).toInt())); ui->showDesktopNumCB->setEnabled(showOnlyOneDesktopTasks); ui->limitByScreenCB->setChecked(settings().value("showOnlyCurrentScreenTasks", false).toBool()); ui->limitByMinimizedCB->setChecked(settings().value("showOnlyMinimizedTasks", false).toBool()); ui->autoRotateCB->setChecked(settings().value("autoRotate", true).toBool()); ui->middleClickCB->setChecked(settings().value("closeOnMiddleClick", true).toBool()); ui->raiseOnCurrentDesktopCB->setChecked(settings().value("raiseOnCurrentDesktop", false).toBool()); ui->buttonStyleCB->setCurrentIndex(ui->buttonStyleCB->findData(settings().value("buttonStyle", "IconText"))); // ui->buttonWidthSB->setValue(100); ui->buttonHeightSB->setValue(settings().value("buttonHeight", 100).toInt()); ui->groupingGB->setChecked(settings().value("groupingEnabled",true).toBool()); ui->showGroupOnHoverCB->setChecked(settings().value("showGroupOnHover",true).toBool()); ui->iconByClassCB->setChecked(settings().value("iconByClass", false).toBool()); ui->cycleOnWheelScroll->setChecked(settings().value("cycleOnWheelScroll", true).toBool()); } void UKUITaskbarConfiguration::saveSettings() { settings().setValue("showOnlyOneDesktopTasks", ui->limitByDesktopCB->isChecked()); settings().setValue("showDesktopNum", ui->showDesktopNumCB->itemData(ui->showDesktopNumCB->currentIndex())); settings().setValue("showOnlyCurrentScreenTasks", ui->limitByScreenCB->isChecked()); settings().setValue("showOnlyMinimizedTasks", ui->limitByMinimizedCB->isChecked()); settings().setValue("buttonStyle", ui->buttonStyleCB->itemData(ui->buttonStyleCB->currentIndex())); settings().setValue("buttonWidth", 50); settings().setValue("buttonHeight", ui->buttonHeightSB->value()); settings().setValue("autoRotate", ui->autoRotateCB->isChecked()); settings().setValue("closeOnMiddleClick", ui->middleClickCB->isChecked()); settings().setValue("raiseOnCurrentDesktop", ui->raiseOnCurrentDesktopCB->isChecked()); settings().setValue("groupingEnabled",ui->groupingGB->isChecked()); settings().setValue("showGroupOnHover",ui->showGroupOnHoverCB->isChecked()); settings().setValue("iconByClass",ui->iconByClassCB->isChecked()); settings().setValue("cycleOnWheelScroll",ui->cycleOnWheelScroll->isChecked()); } ukui-panel/plugin-taskbar/ukuitaskbutton.cpp0000644000175000017500000006207013640356061020304 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuitaskbutton.h" #include "ukuitaskgroup.h" #include "ukuitaskbar.h" //#include #include "../panel/common/ukuisettings.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ukuitaskgroup.h" #include "ukuitaskbar.h" #include // Necessary for closeApplication() #include #include bool UKUITaskButton::sDraggging = false; /************************************************ ************************************************/ void LeftAlignedTextStyle::drawItemText(QPainter * painter, const QRect & rect, int flags , const QPalette & pal, bool enabled, const QString & text , QPalette::ColorRole textRole) const { QString txt = QFontMetrics(painter->font()).elidedText(text, Qt::ElideRight, rect.width()); return QProxyStyle::drawItemText(painter, rect, (flags & ~Qt::AlignHCenter) | Qt::AlignLeft, pal, enabled, txt, textRole); } /************************************************ ************************************************/ UKUITaskButton::UKUITaskButton(const WId window, UKUITaskBar * taskbar, QWidget *parent) : QToolButton(parent), mWindow(window), mUrgencyHint(false), mOrigin(Qt::TopLeftCorner), mDrawPixmap(false), mParentTaskBar(taskbar), mPlugin(mParentTaskBar->plugin()), mDNDTimer(new QTimer(this)) { Q_ASSERT(taskbar); taskbuttonstatus=NORMAL; setCheckable(true); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setMinimumWidth(1); setMinimumHeight(1); setToolButtonStyle(Qt::ToolButtonTextBesideIcon); setAcceptDrops(true); updateText(); updateIcon(); mDNDTimer->setSingleShot(true); mDNDTimer->setInterval(700); connect(mDNDTimer, SIGNAL(timeout()), this, SLOT(activateWithDraggable())); connect(UKUi::Settings::globalSettings(), SIGNAL(iconThemeChanged()), this, SLOT(updateIcon())); connect(mParentTaskBar, &UKUITaskBar::iconByClassChanged, this, &UKUITaskButton::updateIcon); mParentTaskBar->setStyleSheet( //正常状态样式 "QFrame{" "border-width:2px;" //边框宽度像素 "}" ); this->setStyleSheet( //正常状态样式 "QToolButton{" "background-color:rgba(190,216,239,8%);" "border-style:outset;" //边框样式(inset/outset) "border-color:rgba(190,216,239,0%);" //边框颜色 "qproperty-iconSize: 28px 28px;" "border-width:4px;" //边框宽度像素 "border-radius:6px;" //边框圆角半径像素 "padding:0px;" "}" //鼠标悬停样式 "QToolButton:hover{" "background-color:rgba(190,216,239,12%);" "}" //鼠标按下样式 "QToolButton:pressed{" "background-color:rgba(190,216,239,6%);" "}" ); } /************************************************ ************************************************/ UKUITaskButton::~UKUITaskButton() { } /************************************************ ************************************************/ void UKUITaskButton::updateText() { KWindowInfo info(mWindow, NET::WMVisibleName | NET::WMName); QString title = info.visibleName().isEmpty() ? info.name() : info.visibleName(); setText(title.replace("&", "&&")); setToolTip(title); } /************************************************ ************************************************/ void UKUITaskButton::updateIcon() { QIcon ico; if (mParentTaskBar->isIconByClass()) { ico = XdgIcon::fromTheme(QString::fromUtf8(KWindowInfo{mWindow, 0, NET::WM2WindowClass}.windowClassClass()).toLower()); } if (ico.isNull()) { ico = KWindowSystem::icon(mWindow); // ico = XdgIcon::fromTheme(QString::fromUtf8(KWindowInfo{mWindow, 0, NET::WM2WindowClass}.windowClassClass()).toLower()); } setIcon(ico.isNull() ? XdgIcon::defaultApplicationIcon() : ico); } /************************************************ ************************************************/ void UKUITaskButton::refreshIconGeometry(QRect const & geom) { NETWinInfo info(QX11Info::connection(), windowId(), (WId) QX11Info::appRootWindow(), NET::WMIconGeometry, 0); NETRect const curr = info.iconGeometry(); if (curr.pos.x != geom.x() || curr.pos.y != geom.y() || curr.size.width != geom.width() || curr.size.height != geom.height()) { NETRect nrect; nrect.pos.x = geom.x(); nrect.pos.y = geom.y(); nrect.size.height = geom.height(); nrect.size.width = geom.width(); info.setIconGeometry(nrect); } } /************************************************ ************************************************/ void UKUITaskButton::dragEnterEvent(QDragEnterEvent *event) { // It must be here otherwise dragLeaveEvent and dragMoveEvent won't be called // on the other hand drop and dragmove events of parent widget won't be called event->acceptProposedAction(); if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dragging(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } else { mDNDTimer->start(); } QToolButton::dragEnterEvent(event); } void UKUITaskButton::dragMoveEvent(QDragMoveEvent * event) { if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dragging(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } } void UKUITaskButton::dragLeaveEvent(QDragLeaveEvent *event) { mDNDTimer->stop(); QToolButton::dragLeaveEvent(event); } void UKUITaskButton::dropEvent(QDropEvent *event) { mDNDTimer->stop(); if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dropped(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } QToolButton::dropEvent(event); } /************************************************ ************************************************/ void UKUITaskButton::mousePressEvent(QMouseEvent* event) { const Qt::MouseButton b = event->button(); if (Qt::LeftButton == b) mDragStartPosition = event->pos(); else if (Qt::MidButton == b && parentTaskBar()->closeOnMiddleClick()) closeApplication(); QToolButton::mousePressEvent(event); } /************************************************ ************************************************/ void UKUITaskButton::mouseReleaseEvent(QMouseEvent* event) { // if (event->button() == Qt::LeftButton) // { // if (isChecked()) // minimizeApplication(); // else // { // raiseApplication(); // } // } QToolButton::mouseReleaseEvent(event); } /************************************************ ************************************************/ QMimeData * UKUITaskButton::mimeData() { QMimeData *mimedata = new QMimeData; QByteArray ba; QDataStream stream(&ba,QIODevice::WriteOnly); stream << (qlonglong)(mWindow); mimedata->setData(mimeDataFormat(), ba); return mimedata; } /************************************************ ************************************************/ void UKUITaskButton::mouseMoveEvent(QMouseEvent* event) { if (!(event->buttons() & Qt::LeftButton)) return; if ((event->pos() - mDragStartPosition).manhattanLength() < QApplication::startDragDistance()) return; QDrag *drag = new QDrag(this); drag->setMimeData(mimeData()); QIcon ico = icon(); QPixmap img = ico.pixmap(ico.actualSize({32, 32})); drag->setPixmap(img); switch (parentTaskBar()->panel()->position()) { case IUKUIPanel::PositionLeft: case IUKUIPanel::PositionTop: drag->setHotSpot({0, 0}); break; case IUKUIPanel::PositionRight: case IUKUIPanel::PositionBottom: drag->setHotSpot(img.rect().bottomRight()); break; } sDraggging = true; drag->exec(); // if button is dropped out of panel (e.g. on desktop) // it is not deleted automatically by Qt drag->deleteLater(); sDraggging = false; QAbstractButton::mouseMoveEvent(event); } /************************************************ ************************************************/ bool UKUITaskButton::isApplicationHidden() const { KWindowInfo info(mWindow, NET::WMState); return (info.state() & NET::Hidden); } /************************************************ ************************************************/ bool UKUITaskButton::isApplicationActive() const { return KWindowSystem::activeWindow() == mWindow; } /************************************************ ************************************************/ void UKUITaskButton::activateWithDraggable() { // raise app in any time when there is a drag // in progress to allow drop it into an app raiseApplication(); KWindowSystem::forceActiveWindow(mWindow); } /************************************************ ************************************************/ void UKUITaskButton::raiseApplication() { KWindowInfo info(mWindow, NET::WMDesktop | NET::WMState | NET::XAWMState); if (parentTaskBar()->raiseOnCurrentDesktop() && info.isMinimized()) { KWindowSystem::setOnDesktop(mWindow, KWindowSystem::currentDesktop()); } else { int winDesktop = info.desktop(); if (KWindowSystem::currentDesktop() != winDesktop) KWindowSystem::setCurrentDesktop(winDesktop); } KWindowSystem::activateWindow(mWindow); setUrgencyHint(false); } /************************************************ ************************************************/ void UKUITaskButton::minimizeApplication() { KWindowSystem::minimizeWindow(mWindow); } /************************************************ ************************************************/ void UKUITaskButton::maximizeApplication() { QAction* act = qobject_cast(sender()); if (!act) return; int state = act->data().toInt(); switch (state) { case NET::MaxHoriz: KWindowSystem::setState(mWindow, NET::MaxHoriz); break; case NET::MaxVert: KWindowSystem::setState(mWindow, NET::MaxVert); break; default: KWindowSystem::setState(mWindow, NET::Max); break; } if (!isApplicationActive()) raiseApplication(); } /************************************************ ************************************************/ void UKUITaskButton::deMaximizeApplication() { KWindowSystem::clearState(mWindow, NET::Max); if (!isApplicationActive()) raiseApplication(); } /************************************************ ************************************************/ void UKUITaskButton::shadeApplication() { KWindowSystem::setState(mWindow, NET::Shaded); } /************************************************ ************************************************/ void UKUITaskButton::unShadeApplication() { KWindowSystem::clearState(mWindow, NET::Shaded); } /************************************************ ************************************************/ void UKUITaskButton::closeApplication() { // FIXME: Why there is no such thing in KWindowSystem?? NETRootInfo(QX11Info::connection(), NET::CloseWindow).closeWindowRequest(mWindow); } /************************************************ ************************************************/ void UKUITaskButton::setApplicationLayer() { QAction* act = qobject_cast(sender()); if (!act) return; int layer = act->data().toInt(); switch(layer) { case NET::KeepAbove: KWindowSystem::clearState(mWindow, NET::KeepBelow); KWindowSystem::setState(mWindow, NET::KeepAbove); break; case NET::KeepBelow: KWindowSystem::clearState(mWindow, NET::KeepAbove); KWindowSystem::setState(mWindow, NET::KeepBelow); break; default: KWindowSystem::clearState(mWindow, NET::KeepBelow); KWindowSystem::clearState(mWindow, NET::KeepAbove); break; } } /************************************************ ************************************************/ void UKUITaskButton::moveApplicationToDesktop() { QAction* act = qobject_cast(sender()); if (!act) return; bool ok; int desk = act->data().toInt(&ok); if (!ok) return; KWindowSystem::setOnDesktop(mWindow, desk); } /************************************************ ************************************************/ void UKUITaskButton::moveApplication() { KWindowInfo info(mWindow, NET::WMDesktop); if (!info.isOnCurrentDesktop()) KWindowSystem::setCurrentDesktop(info.desktop()); if (isMinimized()) KWindowSystem::unminimizeWindow(mWindow); KWindowSystem::forceActiveWindow(mWindow); const QRect& g = KWindowInfo(mWindow, NET::WMGeometry).geometry(); int X = g.center().x(); int Y = g.center().y(); QCursor::setPos(X, Y); NETRootInfo(QX11Info::connection(), NET::WMMoveResize).moveResizeRequest(mWindow, X, Y, NET::Move); } /************************************************ ************************************************/ void UKUITaskButton::resizeApplication() { KWindowInfo info(mWindow, NET::WMDesktop); if (!info.isOnCurrentDesktop()) KWindowSystem::setCurrentDesktop(info.desktop()); if (isMinimized()) KWindowSystem::unminimizeWindow(mWindow); KWindowSystem::forceActiveWindow(mWindow); const QRect& g = KWindowInfo(mWindow, NET::WMGeometry).geometry(); int X = g.bottomRight().x(); int Y = g.bottomRight().y(); QCursor::setPos(X, Y); NETRootInfo(QX11Info::connection(), NET::WMMoveResize).moveResizeRequest(mWindow, X, Y, NET::BottomRight); } /************************************************ ************************************************/ void UKUITaskButton::contextMenuEvent(QContextMenuEvent* event) { if (event->modifiers().testFlag(Qt::ControlModifier)) { event->ignore(); return; } KWindowInfo info(mWindow, 0, NET::WM2AllowedActions); unsigned long state = KWindowInfo(mWindow, NET::WMState).state(); QMenu * menu = new QMenu(tr("Application")); menu->setAttribute(Qt::WA_DeleteOnClose); QAction* a; /* KDE menu ******* + To &Desktop > + &All Desktops + --- + &1 Desktop 1 + &2 Desktop 2 + &To Current Desktop &Move Re&size + Mi&nimize + Ma&ximize + &Shade Ad&vanced > Keep &Above Others Keep &Below Others Fill screen &Layer > Always on &top &Normal Always on &bottom --- + &Close */ /********** Desktop menu **********/ int deskNum = KWindowSystem::numberOfDesktops(); if (deskNum > 1) { int winDesk = KWindowInfo(mWindow, NET::WMDesktop).desktop(); QMenu* deskMenu = menu->addMenu(tr("To &Desktop")); a = deskMenu->addAction(tr("&All Desktops")); a->setData(NET::OnAllDesktops); a->setEnabled(winDesk != NET::OnAllDesktops); connect(a, SIGNAL(triggered(bool)), this, SLOT(moveApplicationToDesktop())); deskMenu->addSeparator(); for (int i = 0; i < deskNum; ++i) { a = deskMenu->addAction(tr("Desktop &%1").arg(i + 1)); a->setData(i + 1); a->setEnabled(i + 1 != winDesk); connect(a, SIGNAL(triggered(bool)), this, SLOT(moveApplicationToDesktop())); } int curDesk = KWindowSystem::currentDesktop(); a = menu->addAction(tr("&To Current Desktop")); a->setData(curDesk); a->setEnabled(curDesk != winDesk); connect(a, SIGNAL(triggered(bool)), this, SLOT(moveApplicationToDesktop())); } /********** Move/Resize **********/ menu->addSeparator(); a = menu->addAction(tr("&Move")); a->setEnabled(info.actionSupported(NET::ActionMove) && !(state & NET::Max) && !(state & NET::FullScreen)); connect(a, &QAction::triggered, this, &UKUITaskButton::moveApplication); a = menu->addAction(tr("Resi&ze")); a->setEnabled(info.actionSupported(NET::ActionResize) && !(state & NET::Max) && !(state & NET::FullScreen)); connect(a, &QAction::triggered, this, &UKUITaskButton::resizeApplication); /********** State menu **********/ menu->addSeparator(); a = menu->addAction(tr("Ma&ximize")); a->setEnabled(info.actionSupported(NET::ActionMax) && (!(state & NET::Max) || (state & NET::Hidden))); a->setData(NET::Max); connect(a, SIGNAL(triggered(bool)), this, SLOT(maximizeApplication())); if (event->modifiers() & Qt::ShiftModifier) { a = menu->addAction(tr("Maximize vertically")); a->setEnabled(info.actionSupported(NET::ActionMaxVert) && !((state & NET::MaxVert) || (state & NET::Hidden))); a->setData(NET::MaxVert); connect(a, SIGNAL(triggered(bool)), this, SLOT(maximizeApplication())); a = menu->addAction(tr("Maximize horizontally")); a->setEnabled(info.actionSupported(NET::ActionMaxHoriz) && !((state & NET::MaxHoriz) || (state & NET::Hidden))); a->setData(NET::MaxHoriz); connect(a, SIGNAL(triggered(bool)), this, SLOT(maximizeApplication())); } a = menu->addAction(tr("&Restore")); a->setEnabled((state & NET::Hidden) || (state & NET::Max) || (state & NET::MaxHoriz) || (state & NET::MaxVert)); connect(a, SIGNAL(triggered(bool)), this, SLOT(deMaximizeApplication())); a = menu->addAction(tr("Mi&nimize")); a->setEnabled(info.actionSupported(NET::ActionMinimize) && !(state & NET::Hidden)); connect(a, SIGNAL(triggered(bool)), this, SLOT(minimizeApplication())); if (state & NET::Shaded) { a = menu->addAction(tr("Roll down")); a->setEnabled(info.actionSupported(NET::ActionShade) && !(state & NET::Hidden)); connect(a, SIGNAL(triggered(bool)), this, SLOT(unShadeApplication())); } else { a = menu->addAction(tr("Roll up")); a->setEnabled(info.actionSupported(NET::ActionShade) && !(state & NET::Hidden)); connect(a, SIGNAL(triggered(bool)), this, SLOT(shadeApplication())); } /********** Layer menu **********/ menu->addSeparator(); QMenu* layerMenu = menu->addMenu(tr("&Layer")); a = layerMenu->addAction(tr("Always on &top")); // FIXME: There is no info.actionSupported(NET::ActionKeepAbove) a->setEnabled(!(state & NET::KeepAbove)); a->setData(NET::KeepAbove); connect(a, SIGNAL(triggered(bool)), this, SLOT(setApplicationLayer())); a = layerMenu->addAction(tr("&Normal")); a->setEnabled((state & NET::KeepAbove) || (state & NET::KeepBelow)); // FIXME: There is no NET::KeepNormal, so passing 0 a->setData(0); connect(a, SIGNAL(triggered(bool)), this, SLOT(setApplicationLayer())); a = layerMenu->addAction(tr("Always on &bottom")); // FIXME: There is no info.actionSupported(NET::ActionKeepBelow) a->setEnabled(!(state & NET::KeepBelow)); a->setData(NET::KeepBelow); connect(a, SIGNAL(triggered(bool)), this, SLOT(setApplicationLayer())); /********** Kill menu **********/ menu->addSeparator(); a = menu->addAction(XdgIcon::fromTheme("process-stop"), tr("&Close")); connect(a, SIGNAL(triggered(bool)), this, SLOT(closeApplication())); menu->setGeometry(mParentTaskBar->panel()->calculatePopupWindowPos(mapToGlobal(event->pos()), menu->sizeHint())); mPlugin->willShowWindow(menu); menu->show(); } /************************************************ ************************************************/ void UKUITaskButton::setUrgencyHint(bool set) { if (mUrgencyHint == set) return; if (!set) KWindowSystem::demandAttention(mWindow, false); mUrgencyHint = set; setProperty("urgent", set); style()->unpolish(this); style()->polish(this); update(); } /************************************************ ************************************************/ bool UKUITaskButton::isOnDesktop(int desktop) const { return KWindowInfo(mWindow, NET::WMDesktop).isOnDesktop(desktop); } bool UKUITaskButton::isOnCurrentScreen() const { return QApplication::desktop()->screenGeometry(parentTaskBar()).intersects(KWindowInfo(mWindow, NET::WMFrameExtents).frameGeometry()); } bool UKUITaskButton::isMinimized() const { return KWindowInfo(mWindow,NET::WMState | NET::XAWMState).isMinimized(); } Qt::Corner UKUITaskButton::origin() const { return mOrigin; } void UKUITaskButton::setOrigin(Qt::Corner newOrigin) { if (mOrigin != newOrigin) { mOrigin = newOrigin; update(); } } void UKUITaskButton::setAutoRotation(bool value, IUKUIPanel::Position position) { if (value) { switch (position) { case IUKUIPanel::PositionTop: case IUKUIPanel::PositionBottom: setOrigin(Qt::TopLeftCorner); break; case IUKUIPanel::PositionLeft: setOrigin(Qt::BottomLeftCorner); break; case IUKUIPanel::PositionRight: setOrigin(Qt::TopRightCorner); break; } } else setOrigin(Qt::TopLeftCorner); } void UKUITaskButton::enterEvent(QEvent *) { taskbuttonstatus=HOVER; update(); } void UKUITaskButton::leaveEvent(QEvent *) { taskbuttonstatus=NORMAL; update(); } void UKUITaskButton::paintEvent(QPaintEvent *event) { // if (mOrigin == Qt::TopLeftCorner) // { // QToolButton::paintEvent(event); // return; // } QSize sz = size(); QSize adjSz (mPlugin->panel()->panelSize(),mPlugin->panel()->panelSize()); QTransform transform; QPoint originPoint; // switch (mOrigin) // { // case Qt::TopLeftCorner: // transform.rotate(0.0); // originPoint = QPoint(0.0, 0.0); // break; // case Qt::TopRightCorner: // transform.rotate(90.0); // originPoint = QPoint(0.0, -sz.width()); // adjSz.transpose(); // break; // case Qt::BottomRightCorner: // transform.rotate(180.0); // originPoint = QPoint(-sz.width(), -sz.height()); // break; // case Qt::BottomLeftCorner: // transform.rotate(270.0); // originPoint = QPoint(-sz.height(), 0.0); // adjSz.transpose(); // break; // } bool drawPixmapNextTime = false; if (!mDrawPixmap) { mPixmap = QPixmap(adjSz); mPixmap.fill(QColor(255, 0, 0, 0)); if (adjSz != sz) resize(adjSz); // this causes paint event to be repeated - next time we'll paint the pixmap to the widget surface. // copied from QToolButton::paintEvent { QStylePainter painter(&mPixmap, this); QStyleOptionToolButton opt; initStyleOption(&opt); painter.setBrush(QBrush(QColor(0xFF,0xFF,0xFF,0x19))); painter.drawComplexControl(QStyle::CC_ToolButton, opt); // } if (adjSz != sz) { resize(sz); drawPixmapNextTime = true; } else mDrawPixmap = true; // transfer the pixmap to the widget now! } if (mDrawPixmap) { QPainter painter(this); painter.setTransform(transform); painter.drawPixmap(originPoint, mPixmap); drawPixmapNextTime = false; } mDrawPixmap = drawPixmapNextTime; } bool UKUITaskButton::hasDragAndDropHover() const { return mDNDTimer->isActive(); } ukui-panel/plugin-taskbar/ukuitaskbar.h0000644000175000017500000001211113633355350017173 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKBAR_H #define UKUITASKBAR_H #include "../panel/iukuipanel.h" #include "../panel/iukuipanelplugin.h" #include "ukuitaskbarconfiguration.h" #include "ukuitaskgroup.h" #include "ukuitaskbutton.h" #include #include #include //#include #include "../panel/iukuipanel.h" #include #include #include #include #include class QSignalMapper; class UKUITaskButton; class ElidedButtonStyle; namespace UKUi { class GridLayout; } class UKUITaskBar : public QFrame { Q_OBJECT public: explicit UKUITaskBar(IUKUIPanelPlugin *plugin, QWidget* parent = 0); virtual ~UKUITaskBar(); void realign(); Qt::ToolButtonStyle buttonStyle() const { return mButtonStyle; } int buttonWidth() const { return mButtonWidth; } bool closeOnMiddleClick() const { return mCloseOnMiddleClick; } bool raiseOnCurrentDesktop() const { return mRaiseOnCurrentDesktop; } bool isShowOnlyOneDesktopTasks() const { return mShowOnlyOneDesktopTasks; } int showDesktopNum() const { return mShowDesktopNum; } bool isShowOnlyCurrentScreenTasks() const { return mShowOnlyCurrentScreenTasks; } bool isShowOnlyMinimizedTasks() const { return mShowOnlyMinimizedTasks; } bool isAutoRotate() const { return mAutoRotate; } bool isGroupingEnabled() const { return mGroupingEnabled; } bool isShowGroupOnHover() const { return mShowGroupOnHover; } bool isIconByClass() const { return mIconByClass; } void setShowGroupOnHover(bool bFlag); inline IUKUIPanel * panel() const { return mPlugin->panel(); } inline IUKUIPanelPlugin * plugin() const { return mPlugin; } public slots: void settingsChanged(); signals: void buttonRotationRefreshed(bool autoRotate, IUKUIPanel::Position position); void buttonStyleRefreshed(Qt::ToolButtonStyle buttonStyle); void refreshIconGeometry(); void showOnlySettingChanged(); void iconByClassChanged(); void popupShown(UKUITaskGroup* sender); protected: virtual void dragEnterEvent(QDragEnterEvent * event); virtual void dragMoveEvent(QDragMoveEvent * event); void enterEvent(QEvent *); void leaveEvent(QEvent *); void paintEvent(QPaintEvent *); private slots: void refreshTaskList(); void refreshButtonRotation(); void refreshPlaceholderVisibility(); void groupBecomeEmptySlot(); void onWindowChanged(WId window, NET::Properties prop, NET::Properties2 prop2); void onWindowAdded(WId window); void onWindowRemoved(WId window); void registerShortcuts(); void shortcutRegistered(); void activateTask(int pos); private: typedef QMap windowMap_t; private: void addWindow(WId window); windowMap_t::iterator removeWindow(windowMap_t::iterator pos); void buttonMove(UKUITaskGroup * dst, UKUITaskGroup * src, QPoint const & pos); enum TaskStatus{NORMAL, HOVER, PRESS}; TaskStatus taskstatus; private: QMap mKnownWindows; //!< Ids of known windows (mapping to buttons/groups) UKUi::GridLayout *mLayout; // QList mKeys; QSignalMapper *mSignalMapper; // Settings Qt::ToolButtonStyle mButtonStyle; int mButtonWidth; int mButtonHeight; bool mCloseOnMiddleClick; bool mRaiseOnCurrentDesktop; bool mShowOnlyOneDesktopTasks; int mShowDesktopNum; bool mShowOnlyCurrentScreenTasks; bool mShowOnlyMinimizedTasks; bool mAutoRotate; bool mGroupingEnabled; bool mShowGroupOnHover; bool mIconByClass; bool mCycleOnWheelScroll; //!< flag for processing the wheelEvent bool acceptWindow(WId window) const; void setButtonStyle(Qt::ToolButtonStyle buttonStyle); void wheelEvent(QWheelEvent* event); void changeEvent(QEvent* event); void resizeEvent(QResizeEvent *event); IUKUIPanelPlugin *mPlugin; QWidget *mPlaceHolder; LeftAlignedTextStyle *mStyle; }; #endif // UKUITASKBAR_H ukui-panel/plugin-taskbar/ukuitaskbarconfiguration.ui0000644000175000017500000001621513632320722022154 0ustar fengfeng UKUITaskbarConfiguration 0 0 401 512 Task Manager Settings General 0 0 0 0 0 Show only windows from desktop Show only windows from &panel's screen Show only minimized windows Raise minimized windows on current desktop Close on middle-click Cycle windows on wheel scrolling Window &grouping true Show popup on mouse hover Appearance QFormLayout::AllNonFixedFieldsGrow Button style Maximum button width 0 0 px 1 2147483647 Maximum button height 0 0 px 1 500 Auto&rotate buttons when the panel is vertical Use icons by WindowClass, if available Qt::Vertical 20 40 Qt::Horizontal QDialogButtonBox::Close|QDialogButtonBox::Reset buttons accepted() UKUITaskbarConfiguration accept() 262 496 157 274 buttons rejected() UKUITaskbarConfiguration reject() 330 496 286 274 ukui-panel/plugin-taskbar/ukuitaskclosebutton.cpp0000644000175000017500000000331713633355350021333 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see UKUITaskCloseButton::UKUITaskCloseButton(const WId window, QWidget *parent): QToolButton(parent), mWindow(window) { //connect(parent, &UKUITaskBar::buttonRotationRefreshed, this, &UKUITaskGroup::setAutoRotation); } /************************************************ ************************************************/ void UKUITaskCloseButton::mousePressEvent(QMouseEvent* event) { // const Qt::MouseButton b = event->button(); // if (Qt::LeftButton == b) // mDragStartPosition = event->pos(); // else if (Qt::MidButton == b && parentTaskBar()->closeOnMiddleClick()) // closeApplication(); QToolButton::mousePressEvent(event); } /************************************************ ************************************************/ void UKUITaskCloseButton::mouseReleaseEvent(QMouseEvent* event) { if (event->button()== Qt::LeftButton) { emit sigClicked(); } QToolButton::mouseReleaseEvent(event); } ukui-panel/plugin-taskbar/ukuitaskbarconfiguration.h0000644000175000017500000000326513633355350021775 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Maciej Płaza * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITaskbarCONFIGURATION_H #define UKUITaskbarCONFIGURATION_H #include "../panel/ukuipanelpluginconfigdialog.h" #include "../panel/pluginsettings.h" #include namespace Ui { class UKUITaskbarConfiguration; } class UKUITaskbarConfiguration : public UKUIPanelPluginConfigDialog { Q_OBJECT public: explicit UKUITaskbarConfiguration(PluginSettings *settings, QWidget *parent = nullptr); ~UKUITaskbarConfiguration(); private: Ui::UKUITaskbarConfiguration *ui; /* Read settings from conf file and put data into controls. */ void loadSettings(); private slots: void saveSettings(); }; #endif // UKUITaskbarCONFIGURATION_H ukui-panel/plugin-taskbar/ukuitaskbutton.h0000644000175000017500000001112013633355350017741 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKBUTTON_H #define UKUITASKBUTTON_H #include #include #include #include "../panel/iukuipanel.h" //#include #include class QPainter; class QPalette; class QMimeData; class UKUITaskGroup; class UKUITaskBar; class LeftAlignedTextStyle : public QProxyStyle { using QProxyStyle::QProxyStyle; public: virtual void drawItemText(QPainter * painter, const QRect & rect, int flags , const QPalette & pal, bool enabled, const QString & text , QPalette::ColorRole textRole = QPalette::NoRole) const override; }; class UKUITaskButton : public QToolButton { Q_OBJECT Q_PROPERTY(Qt::Corner origin READ origin WRITE setOrigin) public: explicit UKUITaskButton(const WId window, UKUITaskBar * taskBar, QWidget *parent = 0); virtual ~UKUITaskButton(); bool isApplicationHidden() const; bool isApplicationActive() const; WId windowId() const { return mWindow; } bool hasUrgencyHint() const { return mUrgencyHint; } void setUrgencyHint(bool set); bool isOnDesktop(int desktop) const; bool isOnCurrentScreen() const; bool isMinimized() const; void updateText(); Qt::Corner origin() const; virtual void setAutoRotation(bool value, IUKUIPanel::Position position); UKUITaskBar * parentTaskBar() const {return mParentTaskBar;} void refreshIconGeometry(QRect const & geom); static QString mimeDataFormat() { return QLatin1String("ukui/UKUITaskButton"); } /*! \return true if this buttom received DragEnter event (and no DragLeave event yet) * */ bool hasDragAndDropHover() const; public slots: void raiseApplication(); void minimizeApplication(); void maximizeApplication(); void deMaximizeApplication(); void shadeApplication(); void unShadeApplication(); void closeApplication(); void moveApplicationToDesktop(); void moveApplication(); void resizeApplication(); void setApplicationLayer(); void setOrigin(Qt::Corner); void updateIcon(); protected: virtual void dragEnterEvent(QDragEnterEvent *event); virtual void dragMoveEvent(QDragMoveEvent * event); virtual void dragLeaveEvent(QDragLeaveEvent *event); virtual void dropEvent(QDropEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); virtual void contextMenuEvent(QContextMenuEvent *event); void enterEvent(QEvent *); void leaveEvent(QEvent *); void paintEvent(QPaintEvent *); void setWindowId(WId wid) {mWindow = wid;} virtual QMimeData * mimeData(); static bool sDraggging; inline IUKUIPanelPlugin * plugin() const { return mPlugin; } private: WId mWindow; bool mUrgencyHint; QPoint mDragStartPosition; Qt::Corner mOrigin; QPixmap mPixmap; bool mDrawPixmap; UKUITaskBar * mParentTaskBar; IUKUIPanelPlugin * mPlugin; enum TaskButtonStatus{NORMAL, HOVER, PRESS}; TaskButtonStatus taskbuttonstatus; // Timer for when draggind something into a button (the button's window // must be activated so that the use can continue dragging to the window QTimer * mDNDTimer; private slots: void activateWithDraggable(); signals: void dropped(QObject * dragSource, QPoint const & pos); void dragging(QObject * dragSource, QPoint const & pos); }; //typedef QHash UKUITaskButtonHash; //typedef QHash UKUITaskButtonHash; #endif // UKUITASKBUTTON_H ukui-panel/plugin-taskbar/resources/0000755000175000017500000000000013632320722016505 5ustar fengfengukui-panel/plugin-taskbar/resources/taskbar.desktop.in0000644000175000017500000000026213632320722022134 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Task manager Comment=Switch between running applications Icon=window-duplicate #TRANSLATIONS_DIR=../translations ukui-panel/plugin-taskbar/ukuitaskwidget.cpp0000644000175000017500000004360213642614010020245 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include "../panel/common/ukuisettings.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ukuitaskgroup.h" #include "ukuitaskbar.h" #include "ukuitaskclosebutton.h" #include // Necessary for closeApplication() #include #include bool UKUITaskWidget::sDraggging = false; /************************************************ ************************************************/ //void LeftAlignedTextStyle::drawItemText(QPainter * painter, const QRect & rect, int flags // , const QPalette & pal, bool enabled, const QString & text // , QPalette::ColorRole textRole) const //{ // QString txt = QFontMetrics(painter->font()).elidedText(text, Qt::ElideRight, rect.width()); // return QProxyStyle::drawItemText(painter, rect, (flags & ~Qt::AlignHCenter) | Qt::AlignLeft, pal, enabled, txt, textRole); //} /************************************************ ************************************************/ UKUITaskWidget::UKUITaskWidget(const WId window, UKUITaskBar * taskbar, QWidget *parent) : QWidget(parent), mWindow(window), mUrgencyHint(false), mOrigin(Qt::TopLeftCorner), mDrawPixmap(false), mParentTaskBar(taskbar), mPlugin(mParentTaskBar->plugin()), mDNDTimer(new QTimer(this)) { Q_ASSERT(taskbar); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setMinimumWidth(1); setMinimumHeight(1); setAcceptDrops(true); // QPixmap closePix = style()->standardPixmap(QStyle::SP_TitleBarCloseButton); status=NORMAL; setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 setWindowFlags(Qt::FramelessWindowHint); //设置无边框窗口 //for layout mCloseBtn = new UKUITaskCloseButton(mWindow, this); mCloseBtn->setIcon(QIcon::fromTheme("window-close-symbolic")); mTitleLabel = new QLabel; mThumbnailLabel = new QLabel; mAppIcon = new QLabel; mVWindowsLayout = new QVBoxLayout; mTopBarLayout = new QHBoxLayout; mTitleLabel->setAlignment(Qt::AlignLeft|Qt::AlignVCenter); mAppIcon->setAlignment(Qt::AlignLeft); mAppIcon->setScaledContents(false); // 自动缩放图片 // titleLabel->setScaledContents(true); mThumbnailLabel->setScaledContents(true); // 设置控件缩放方式 QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); sizePolicy.setHorizontalPolicy(QSizePolicy::Expanding); mTitleLabel->setSizePolicy(sizePolicy); mAppIcon->setSizePolicy(sizePolicy); sizePolicy.setVerticalPolicy(QSizePolicy::Expanding); // mTitleLabel->setAttribute(Qt::WA_TranslucentBackground, true); // mAppIcon->setAttribute(Qt::WA_TranslucentBackground, true); mAppIcon->resize(QSize(32,32)); // 设置控件最大尺寸 mTitleLabel->setFixedHeight(32); mTitleLabel->setMinimumWidth(1); mThumbnailLabel->setMinimumSize(QSize(1, 1)); mTitleLabel->setContentsMargins(0, 0, 5, 0); mTopBarLayout->addWidget(mAppIcon); mTopBarLayout->addWidget(mTitleLabel); mTopBarLayout->addWidget(mCloseBtn); mVWindowsLayout->addLayout(mTopBarLayout); mVWindowsLayout->addWidget(mThumbnailLabel); this->setLayout(mVWindowsLayout); updateText(); updateIcon(); mDNDTimer->setSingleShot(true); mDNDTimer->setInterval(700); connect(mDNDTimer, SIGNAL(timeout()), this, SLOT(activateWithDraggable())); connect(UKUi::Settings::globalSettings(), SIGNAL(iconThemeChanged()), this, SLOT(updateIcon())); connect(mParentTaskBar, &UKUITaskBar::iconByClassChanged, this, &UKUITaskWidget::updateIcon); connect(mCloseBtn, SIGNAL(sigClicked()), this, SLOT(closeApplication())); } /************************************************ ************************************************/ UKUITaskWidget::~UKUITaskWidget() { } /************************************************ ************************************************/ void UKUITaskWidget::updateText() { KWindowInfo info(mWindow, NET::WMVisibleName | NET::WMName); QString title = info.visibleName().isEmpty() ? info.name() : info.visibleName(); mTitleLabel->setText(title); QPalette pa; pa.setColor(QPalette::WindowText,Qt::white); mTitleLabel->setPalette(pa); // setText(title.replace("&", "&&")); // setToolTip(title); } /************************************************ ************************************************/ void UKUITaskWidget::updateIcon() { QIcon ico; if (mParentTaskBar->isIconByClass()) { ico = XdgIcon::fromTheme(QString::fromUtf8(KWindowInfo{mWindow, 0, NET::WM2WindowClass}.windowClassClass()).toLower()); } if (ico.isNull()) { ico = KWindowSystem::icon(mWindow); } mAppIcon->setPixmap(ico.pixmap(QSize(32,32))); //mAppIcon->setWindowIcon(ico.isNull() ? XdgIcon::defaultApplicationIcon() : ico); //setIcon(ico.isNull() ? XdgIcon::defaultApplicationIcon() : ico); } /************************************************ ************************************************/ void UKUITaskWidget::refreshIconGeometry(QRect const & geom) { NETWinInfo info(QX11Info::connection(), windowId(), (WId) QX11Info::appRootWindow(), NET::WMIconGeometry, 0); NETRect const curr = info.iconGeometry(); if (curr.pos.x != geom.x() || curr.pos.y != geom.y() || curr.size.width != geom.width() || curr.size.height != geom.height()) { NETRect nrect; nrect.pos.x = geom.x(); nrect.pos.y = geom.y(); nrect.size.height = geom.height(); nrect.size.width = geom.width(); info.setIconGeometry(nrect); } } /************************************************ ************************************************/ void UKUITaskWidget::dragEnterEvent(QDragEnterEvent *event) { // It must be here otherwise dragLeaveEvent and dragMoveEvent won't be called // on the other hand drop and dragmove events of parent widget won't be called event->acceptProposedAction(); if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dragging(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } else { mDNDTimer->start(); } QWidget::dragEnterEvent(event); } void UKUITaskWidget::dragMoveEvent(QDragMoveEvent * event) { if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dragging(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } } void UKUITaskWidget::dragLeaveEvent(QDragLeaveEvent *event) { mDNDTimer->stop(); QWidget::dragLeaveEvent(event); } void UKUITaskWidget::dropEvent(QDropEvent *event) { mDNDTimer->stop(); if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dropped(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } QWidget::dropEvent(event); } /************************************************ ************************************************/ void UKUITaskWidget::mousePressEvent(QMouseEvent* event) { const Qt::MouseButton b = event->button(); if (Qt::LeftButton == b) { mDragStartPosition = event->pos(); } else if (Qt::MidButton == b && parentTaskBar()->closeOnMiddleClick()) closeApplication(); QWidget::mousePressEvent(event); } /************************************************ ************************************************/ void UKUITaskWidget::mouseReleaseEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { // if (isChecked()) // minimizeApplication(); // else raiseApplication(); } status = NORMAL; update(); QWidget::mouseReleaseEvent(event); } /************************************************ ************************************************/ void UKUITaskWidget::enterEvent(QEvent *) { status = HOVER; repaint(); } void UKUITaskWidget::leaveEvent(QEvent *) { status = NORMAL; update(); } QMimeData * UKUITaskWidget::mimeData() { QMimeData *mimedata = new QMimeData; QByteArray ba; QDataStream stream(&ba,QIODevice::WriteOnly); stream << (qlonglong)(mWindow); mimedata->setData(mimeDataFormat(), ba); return mimedata; } /************************************************ ************************************************/ void UKUITaskWidget::mouseMoveEvent(QMouseEvent* event) { } /************************************************ ************************************************/ bool UKUITaskWidget::isApplicationHidden() const { KWindowInfo info(mWindow, NET::WMState); return (info.state() & NET::Hidden); } /************************************************ ************************************************/ bool UKUITaskWidget::isApplicationActive() const { return KWindowSystem::activeWindow() == mWindow; } /************************************************ ************************************************/ void UKUITaskWidget::activateWithDraggable() { // raise app in any time when there is a drag // in progress to allow drop it into an app raiseApplication(); KWindowSystem::forceActiveWindow(mWindow); } /************************************************ ************************************************/ void UKUITaskWidget::raiseApplication() { KWindowInfo info(mWindow, NET::WMDesktop | NET::WMState | NET::XAWMState); if (parentTaskBar()->raiseOnCurrentDesktop() && info.isMinimized()) { KWindowSystem::setOnDesktop(mWindow, KWindowSystem::currentDesktop()); } else { int winDesktop = info.desktop(); if (KWindowSystem::currentDesktop() != winDesktop) KWindowSystem::setCurrentDesktop(winDesktop); } KWindowSystem::activateWindow(mWindow); emit windowMaximize(); setUrgencyHint(false); } /************************************************ ************************************************/ void UKUITaskWidget::minimizeApplication() { KWindowSystem::minimizeWindow(mWindow); } /************************************************ ************************************************/ void UKUITaskWidget::maximizeApplication() { QAction* act = qobject_cast(sender()); if (!act) return; int state = act->data().toInt(); switch (state) { case NET::MaxHoriz: KWindowSystem::setState(mWindow, NET::MaxHoriz); break; case NET::MaxVert: KWindowSystem::setState(mWindow, NET::MaxVert); break; default: KWindowSystem::setState(mWindow, NET::Max); break; } if (!isApplicationActive()) raiseApplication(); } /************************************************ ************************************************/ void UKUITaskWidget::deMaximizeApplication() { KWindowSystem::clearState(mWindow, NET::Max); if (!isApplicationActive()) raiseApplication(); } /************************************************ ************************************************/ void UKUITaskWidget::shadeApplication() { KWindowSystem::setState(mWindow, NET::Shaded); } /************************************************ ************************************************/ void UKUITaskWidget::unShadeApplication() { KWindowSystem::clearState(mWindow, NET::Shaded); } /************************************************ ************************************************/ void UKUITaskWidget::closeApplication() { // FIXME: Why there is no such thing in KWindowSystem?? qDebug()<<"closeApplication"; NETRootInfo(QX11Info::connection(), NET::CloseWindow).closeWindowRequest(mWindow); } /************************************************ ************************************************/ void UKUITaskWidget::setApplicationLayer() { QAction* act = qobject_cast(sender()); if (!act) return; int layer = act->data().toInt(); switch(layer) { case NET::KeepAbove: KWindowSystem::clearState(mWindow, NET::KeepBelow); KWindowSystem::setState(mWindow, NET::KeepAbove); break; case NET::KeepBelow: KWindowSystem::clearState(mWindow, NET::KeepAbove); KWindowSystem::setState(mWindow, NET::KeepBelow); break; default: KWindowSystem::clearState(mWindow, NET::KeepBelow); KWindowSystem::clearState(mWindow, NET::KeepAbove); break; } } /************************************************ ************************************************/ void UKUITaskWidget::moveApplicationToDesktop() { QAction* act = qobject_cast(sender()); if (!act) return; bool ok; int desk = act->data().toInt(&ok); if (!ok) return; KWindowSystem::setOnDesktop(mWindow, desk); } /************************************************ ************************************************/ void UKUITaskWidget::moveApplication() { KWindowInfo info(mWindow, NET::WMDesktop); if (!info.isOnCurrentDesktop()) KWindowSystem::setCurrentDesktop(info.desktop()); if (isMinimized()) KWindowSystem::unminimizeWindow(mWindow); KWindowSystem::forceActiveWindow(mWindow); const QRect& g = KWindowInfo(mWindow, NET::WMGeometry).geometry(); int X = g.center().x(); int Y = g.center().y(); QCursor::setPos(X, Y); NETRootInfo(QX11Info::connection(), NET::WMMoveResize).moveResizeRequest(mWindow, X, Y, NET::Move); } /************************************************ ************************************************/ void UKUITaskWidget::resizeApplication() { KWindowInfo info(mWindow, NET::WMDesktop); if (!info.isOnCurrentDesktop()) KWindowSystem::setCurrentDesktop(info.desktop()); if (isMinimized()) KWindowSystem::unminimizeWindow(mWindow); KWindowSystem::forceActiveWindow(mWindow); const QRect& g = KWindowInfo(mWindow, NET::WMGeometry).geometry(); int X = g.bottomRight().x(); int Y = g.bottomRight().y(); QCursor::setPos(X, Y); NETRootInfo(QX11Info::connection(), NET::WMMoveResize).moveResizeRequest(mWindow, X, Y, NET::BottomRight); } /************************************************ ************************************************/ void UKUITaskWidget::setUrgencyHint(bool set) { if (mUrgencyHint == set) return; if (!set) KWindowSystem::demandAttention(mWindow, false); mUrgencyHint = set; setProperty("urgent", set); style()->unpolish(this); style()->polish(this); update(); } /************************************************ ************************************************/ bool UKUITaskWidget::isOnDesktop(int desktop) const { return KWindowInfo(mWindow, NET::WMDesktop).isOnDesktop(desktop); } bool UKUITaskWidget::isOnCurrentScreen() const { return QApplication::desktop()->screenGeometry(parentTaskBar()).intersects(KWindowInfo(mWindow, NET::WMFrameExtents).frameGeometry()); } bool UKUITaskWidget::isMinimized() const { return KWindowInfo(mWindow,NET::WMState | NET::XAWMState).isMinimized(); } Qt::Corner UKUITaskWidget::origin() const { return mOrigin; } void UKUITaskWidget::setOrigin(Qt::Corner newOrigin) { if (mOrigin != newOrigin) { mOrigin = newOrigin; update(); } } void UKUITaskWidget::setAutoRotation(bool value, IUKUIPanel::Position position) { if (value) { switch (position) { case IUKUIPanel::PositionTop: case IUKUIPanel::PositionBottom: setOrigin(Qt::TopLeftCorner); break; case IUKUIPanel::PositionLeft: setOrigin(Qt::BottomLeftCorner); break; case IUKUIPanel::PositionRight: setOrigin(Qt::TopRightCorner); break; } } else setOrigin(Qt::TopLeftCorner); } void UKUITaskWidget::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); switch(status) { case NORMAL: { p.setBrush(QBrush(QColor(0x13,0x14,0x14,0xb2))); p.setPen(Qt::black); break; } case HOVER: { // p.setBrush(QBrush(QColor(0xFF,0xFF,0xFF,0x19))); p.setBrush(QBrush(QColor(0x13,0x14,0x14,0x19))); p.setPen(Qt::black); break; } case PRESS: { p.setBrush(QBrush(QColor(0xFF,0xFF,0xFF,0x19))); p.setPen(Qt::white); break; } } p.setRenderHint(QPainter::Antialiasing); // 反锯齿; p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } bool UKUITaskWidget::hasDragAndDropHover() const { return mDNDTimer->isActive(); } void UKUITaskWidget::updateTitle() { updateText(); } void UKUITaskWidget::setThumbNail(QPixmap _pixmap) { mThumbnailLabel->setPixmap(_pixmap); } ukui-panel/plugin-taskbar/ukuitaskgroup.cpp0000644000175000017500000007304513642614010020122 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuitaskgroup.h" #include "ukuitaskbar.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../panel/iukuipanelplugin.h" #include #include #define PREVIEW_WIDTH 468 #define PREVIEW_HEIGHT 428 #define SPACE_WIDTH 8 #define SPACE_HEIGHT 8 #define THUMBNAIL_WIDTH (PREVIEW_WIDTH - SPACE_WIDTH) #define THUMBNAIL_HEIGHT (PREVIEW_HEIGHT - SPACE_HEIGHT) #define ICON_WIDTH 48 #define ICON_HEIGHT 48 #define SCREEN_MAX_WIDTH_SIZE 1400 #define SCREEN_MAX_HEIGHT_SIZE 1050 #define SCREEN_MIN_WIDTH_SIZE 800 #define SCREEN_MIN_HEIGHT_SIZE 600 #define SCREEN_MID_WIDTH_SIZE 1600 #define PREVIEW_WIDGET_MAX_WIDTH 352 #define PREVIEW_WIDGET_MAX_HEIGHT 264 #define PREVIEW_WIDGET_MIN_WIDTH 276 #define PREVIEW_WIDGET_MIN_HEIGHT 200 QPixmap qimageFromXImage(XImage* ximage) { QImage::Format format = QImage::Format_ARGB32_Premultiplied; if (ximage->depth == 24) format = QImage::Format_RGB32; else if (ximage->depth == 16) format = QImage::Format_RGB16; QImage image = QImage(reinterpret_cast(ximage->data), ximage->width, ximage->height, ximage->bytes_per_line, format).copy(); // 大端还是小端? if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && ximage->byte_order == MSBFirst) || (QSysInfo::ByteOrder == QSysInfo::BigEndian && ximage->byte_order == LSBFirst)) { for (int i = 0; i < image.height(); i++) { if (ximage->depth == 16) { ushort* p = reinterpret_cast(image.scanLine(i)); ushort* end = p + image.width(); while (p < end) { *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff); p++; } } else { uint* p = reinterpret_cast(image.scanLine(i)); uint* end = p + image.width(); while (p < end) { *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000) | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff); p++; } } } } // 修复alpha通道 if (format == QImage::Format_RGB32) { QRgb* p = reinterpret_cast(image.bits()); for (int y = 0; y < ximage->height; ++y) { for (int x = 0; x < ximage->width; ++x) p[x] |= 0xff000000; p += ximage->bytes_per_line / 4; } } return QPixmap::fromImage(image); } /************************************************ ************************************************/ UKUITaskGroup::UKUITaskGroup(const QString &groupName, WId window, UKUITaskBar *parent) : UKUITaskButton(window, parent, parent), mGroupName(groupName), mPopup(new UKUIGroupPopup(this)), mPreventPopup(false), mSingleButton(true), mTimer(new QTimer(this)), mpWidget(NULL) { Q_ASSERT(parent); taskgroupStatus = NORMAL; setObjectName(groupName); setText(groupName); connect(this, SIGNAL(clicked(bool)), this, SLOT(onClicked(bool))); connect(KWindowSystem::self(), SIGNAL(currentDesktopChanged(int)), this, SLOT(onDesktopChanged(int))); connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), this, SLOT(onActiveWindowChanged(WId))); connect(parent, &UKUITaskBar::buttonRotationRefreshed, this, &UKUITaskGroup::setAutoRotation); connect(parent, &UKUITaskBar::refreshIconGeometry, this, &UKUITaskGroup::refreshIconsGeometry); connect(parent, &UKUITaskBar::buttonStyleRefreshed, this, &UKUITaskGroup::setToolButtonsStyle); connect(parent, &UKUITaskBar::showOnlySettingChanged, this, &UKUITaskGroup::refreshVisibility); connect(parent, &UKUITaskBar::popupShown, this, &UKUITaskGroup::groupPopupShown); mTimer->setTimerType(Qt::PreciseTimer); connect(mTimer, SIGNAL(timeout()), SLOT(timeout())); } UKUITaskGroup::~UKUITaskGroup() { // if(mPopup) // { // mPopup->deleteLater(); // mPopup = NULL; // } // if(mpWidget) // { // mpWidget->deleteLater(); // mpWidget = NULL; // } // if(VLayout) // { // VLayout->deleteLater(); // VLayout = NULL; // } } /************************************************ ************************************************/ void UKUITaskGroup::contextMenuEvent(QContextMenuEvent *event) { setPopupVisible(false, true); mPreventPopup = true; if (mSingleButton) { UKUITaskButton::contextMenuEvent(event); return; } QMenu * menu = new QMenu(tr("Group")); menu->setAttribute(Qt::WA_DeleteOnClose); QAction *a = menu->addAction(XdgIcon::fromTheme("process-stop"), tr("close")); connect(a, SIGNAL(triggered()), this, SLOT(closeGroup())); connect(menu, &QMenu::aboutToHide, [this] { mPreventPopup = false; }); menu->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(event->pos()), menu->sizeHint())); plugin()->willShowWindow(menu); menu->show(); } /************************************************ ************************************************/ void UKUITaskGroup::closeGroup() { //To Do for (UKUITaskWidget *button : qAsConst(mButtonHash) ) if (button->isOnDesktop(KWindowSystem::currentDesktop())) button->closeApplication(); } /************************************************ ************************************************/ QWidget * UKUITaskGroup::addWindow(WId id) { if (mButtonHash.contains(id)) return mButtonHash.value(id); UKUITaskWidget *btn = new UKUITaskWidget(id, parentTaskBar(), mPopup); mButtonHash.insert(id, btn); connect(btn, SIGNAL(clicked()), this, SLOT(onChildButtonClicked())); connect(btn, SIGNAL(windowMaximize()), this, SLOT(onChildButtonClicked())); refreshVisibility(); return btn; } /************************************************ ************************************************/ QWidget * UKUITaskGroup::checkedButton() const { // for (QWidget* button : qAsConst(mButtonHash)) // if (button->isChecked()) // return button; return NULL; } /************************************************ ************************************************/ QWidget * UKUITaskGroup::getNextPrevChildButton(bool next, bool circular) { #if 0 QWidget *button = checkedButton(); int idx = mPopup->indexOf(button); int inc = next ? 1 : -1; idx += inc; // if there is no cheked button, get the first one if next equals true // or the last one if not if (!button) { idx = -1; if (next) { for (int i = 0; i < mPopup->count() && idx == -1; i++) if (mPopup->itemAt(i)->widget()->isVisibleTo(mPopup)) idx = i; } else { for (int i = mPopup->count() - 1; i >= 0 && idx == -1; i--) if (mPopup->itemAt(i)->widget()->isVisibleTo(mPopup)) idx = i; } } if (circular) idx = (idx + mButtonHash.count()) % mButtonHash.count(); else if (mPopup->count() <= idx || idx < 0) return NULL; // return the next or the previous child QLayoutItem *item = mPopup->itemAt(idx); if (item) { button = qobject_cast(item->widget()); if (button->isVisibleTo(mPopup)) return button; } #endif return NULL; } /************************************************ ************************************************/ void UKUITaskGroup::onActiveWindowChanged(WId window) { UKUITaskWidget *button = mButtonHash.value(window, nullptr); // for (QWidget *btn : qAsConst(mButtonHash)) // btn->setChecked(false); // if (button) // { // button->setChecked(true); // if (button->hasUrgencyHint()) // button->setUrgencyHint(false); // } setChecked(nullptr != button); } /************************************************ ************************************************/ void UKUITaskGroup::onDesktopChanged(int number) { refreshVisibility(); } /************************************************ ************************************************/ void UKUITaskGroup::onWindowRemoved(WId window) { if (mButtonHash.contains(window)) { UKUITaskWidget *button = mButtonHash.value(window); mButtonHash.remove(window); mPopup->removeWidget(button); button->deleteLater(); if (mButtonHash.count()) { if(mPopup->isVisible()) { mPopup->hide(); showPreview(); } else { regroup(); } } else { if (isVisible()) emit visibilityChanged(false); hide(); emit groupBecomeEmpty(groupName()); } } } /************************************************ ************************************************/ void UKUITaskGroup::onChildButtonClicked() { setPopupVisible(false, true); parentTaskBar()->setShowGroupOnHover(true); //QToolButton::leaveEvent(event); taskgroupStatus = NORMAL; update(); } /************************************************ ************************************************/ Qt::ToolButtonStyle UKUITaskGroup::popupButtonStyle() const { // do not set icons-only style in the buttons in the group, // as they'll be indistinguishable const Qt::ToolButtonStyle style = toolButtonStyle(); return style == Qt::ToolButtonIconOnly ? Qt::ToolButtonTextBesideIcon : style; } /************************************************ ************************************************/ void UKUITaskGroup::setToolButtonsStyle(Qt::ToolButtonStyle style) { setToolButtonStyle(style); // const Qt::ToolButtonStyle styleInPopup = popupButtonStyle(); // for (auto & button : mButtonHash) // { // button->setToolButtonStyle(styleInPopup); // } } /************************************************ ************************************************/ int UKUITaskGroup::buttonsCount() const { return mButtonHash.count(); } /************************************************ ************************************************/ int UKUITaskGroup::visibleButtonsCount() const { int i = 0; for (UKUITaskWidget *btn : qAsConst(mButtonHash)) if (btn->isVisibleTo(mPopup)) i++; return i; } /************************************************ ************************************************/ void UKUITaskGroup::draggingTimerTimeout() { if (mSingleButton) setPopupVisible(false); } /************************************************ ************************************************/ void UKUITaskGroup::onClicked(bool) { // if (visibleButtonsCount() > 1) // { // setChecked(mButtonHash.contains(KWindowSystem::activeWindow())); // setPopupVisible(true); // } if(mPopup->isVisible()) { if(HOVER == taskgroupStatus) { taskgroupStatus = NORMAL; return; } else { mPopup->hide(); return; } } else { showPreview(); } mTaskGroupEvent = OTHEREVENT; if(mTimer->isActive()) { mTimer->stop(); } } /************************************************ ************************************************/ void UKUITaskGroup::regroup() { int cont = visibleButtonsCount(); recalculateFrameIfVisible(); // if (cont == 1) // { // mSingleButton = false; // // Get first visible button // UKUITaskButton * button = NULL; // for (UKUITaskButton *btn : qAsConst(mButtonHash)) // { // if (btn->isVisibleTo(mPopup)) // { // button = btn; // break; // } // } // if (button) // { // setText(button->text()); // setToolTip(button->toolTip()); // setWindowId(button->windowId()); // } // } /*else*/ if (cont == 0) hide(); else { mSingleButton = false; QString t = QString("%1 - %2 windows").arg(mGroupName).arg(cont); setText(t); setToolTip(parentTaskBar()->isShowGroupOnHover() ? QString() : t); } } /************************************************ ************************************************/ void UKUITaskGroup::recalculateFrameIfVisible() { if (mPopup->isVisible()) { recalculateFrameSize(); if (plugin()->panel()->position() == IUKUIPanel::PositionBottom) recalculateFramePosition(); } } /************************************************ ************************************************/ void UKUITaskGroup::setAutoRotation(bool value, IUKUIPanel::Position position) { // for (QWidget *button : qAsConst(mButtonHash)) // button->setAutoRotation(false, position); //UKUITaskWidget::setAutoRotation(value, position); } /************************************************ ************************************************/ void UKUITaskGroup::refreshVisibility() { bool will = false; UKUITaskBar const * taskbar = parentTaskBar(); const int showDesktop = taskbar->showDesktopNum(); for(UKUITaskWidget * btn : qAsConst(mButtonHash)) { bool visible = taskbar->isShowOnlyOneDesktopTasks() ? btn->isOnDesktop(0 == showDesktop ? KWindowSystem::currentDesktop() : showDesktop) : true; visible &= taskbar->isShowOnlyCurrentScreenTasks() ? btn->isOnCurrentScreen() : true; visible &= taskbar->isShowOnlyMinimizedTasks() ? btn->isMinimized() : true; btn->setVisible(visible); will |= visible; } bool is = isVisible(); setVisible(will); if(!mPopup->isVisible()) { regroup(); } if (is != will) emit visibilityChanged(will); } /************************************************ ************************************************/ QMimeData * UKUITaskGroup::mimeData() { QMimeData *mimedata = new QMimeData; QByteArray byteArray; QDataStream stream(&byteArray, QIODevice::WriteOnly); stream << groupName(); mimedata->setData(mimeDataFormat(), byteArray); return mimedata; } /************************************************ ************************************************/ void UKUITaskGroup::setPopupVisible(bool visible, bool fast) { if (visible && !mPreventPopup && !mSingleButton) { // QTimer::singleShot(400, this,SLOT(showPreview())); showPreview(); /* for origin preview plugin()->willShowWindow(mPopup); mPopup->show(); qDebug()<<"setPopupVisible ********"; emit popupShown(this);*/ } else mPopup->hide(fast); } /************************************************ ************************************************/ void UKUITaskGroup::refreshIconsGeometry() { QRect rect = geometry(); rect.moveTo(mapToGlobal(QPoint(0, 0))); if (mSingleButton) { refreshIconGeometry(rect); return; } // for(UKUITaskButton *but : qAsConst(mButtonHash)) // { // but->refreshIconGeometry(rect); // but->setIconSize(QSize(plugin()->panel()->iconSize(), plugin()->panel()->iconSize())); // } } /************************************************ ************************************************/ QSize UKUITaskGroup::recalculateFrameSize() { int height = recalculateFrameHeight(); mPopup->setMaximumHeight(1000); mPopup->setMinimumHeight(0); int hh = recalculateFrameWidth(); mPopup->setMaximumWidth(hh); mPopup->setMinimumWidth(0); QSize newSize(hh, height); mPopup->resize(newSize); return newSize; } /************************************************ ************************************************/ int UKUITaskGroup::recalculateFrameHeight() const { // int cont = visibleButtonsCount(); // int h = !plugin()->panel()->isHorizontal() && parentTaskBar()->isAutoRotate() ? width() : height(); // return cont * h + (cont + 1) * mPopup->spacing(); return 120; } /************************************************ ************************************************/ int UKUITaskGroup::recalculateFrameWidth() const { const QFontMetrics fm = fontMetrics(); int max = 100 * fm.width (' '); // elide after the max width int txtWidth = 0; // for (UKUITaskButton *btn : qAsConst(mButtonHash)) // txtWidth = qMax(fm.width(btn->text()), txtWidth); return iconSize().width() + qMin(txtWidth, max) + 30/* give enough room to margins and borders*/; } /************************************************ ************************************************/ QPoint UKUITaskGroup::recalculateFramePosition() { // Set position int x_offset = 0, y_offset = 0; switch (plugin()->panel()->position()) { case IUKUIPanel::PositionTop: y_offset += height(); break; case IUKUIPanel::PositionBottom: y_offset = -recalculateFrameHeight(); break; case IUKUIPanel::PositionLeft: x_offset += width(); break; case IUKUIPanel::PositionRight: x_offset = -recalculateFrameWidth(); break; } QPoint pos = mapToGlobal(QPoint(x_offset, y_offset)); mPopup->move(pos); return pos; } /************************************************ ************************************************/ void UKUITaskGroup::leaveEvent(QEvent *event) { //QTimer::singleShot(300, this,SLOT(mouseLeaveOut())); mTaskGroupEvent = LEAVEEVENT; mEvent = event; if(mTimer->isActive()) { mTimer->stop();//stay time is no more than 400 ms need kill timer } else { mTimer->start(300); } } /************************************************ ************************************************/ void UKUITaskGroup::enterEvent(QEvent *event) { //QToolButton::enterEvent(event); mTaskGroupEvent = ENTEREVENT; mEvent = event; mTimer->start(400); // if (sDraggging) // return; // if (parentTaskBar()->isShowGroupOnHover()) // { // setPopupVisible(true); // parentTaskBar()->setShowGroupOnHover(false);//enter this group other groups will be blocked // } // taskgroupStatus = HOVER; // repaint(); } void UKUITaskGroup::handleSavedEvent() { if (sDraggging) return; if (parentTaskBar()->isShowGroupOnHover()) { setPopupVisible(true); } taskgroupStatus = HOVER; repaint(); QToolButton::enterEvent(mEvent); } //void UKUITaskGroup::paintEvent(QPaintEvent *) //{ //} /************************************************ ************************************************/ void UKUITaskGroup::dragEnterEvent(QDragEnterEvent *event) { // only show the popup if we aren't dragging a taskgroup if (!event->mimeData()->hasFormat(mimeDataFormat())) { setPopupVisible(true); } UKUITaskButton::dragEnterEvent(event); } /************************************************ ************************************************/ void UKUITaskGroup::dragLeaveEvent(QDragLeaveEvent *event) { // if draggind something into the taskgroup or the taskgroups' popup, // do not close the popup if (!sDraggging) setPopupVisible(false); UKUITaskButton::dragLeaveEvent(event); } void UKUITaskGroup::mouseMoveEvent(QMouseEvent* event) { // if dragging the taskgroup, do not show the popup setPopupVisible(false, true); UKUITaskButton::mouseMoveEvent(event); } /************************************************ ************************************************/ bool UKUITaskGroup::onWindowChanged(WId window, NET::Properties prop, NET::Properties2 prop2) { // returns true if the class is preserved bool needsRefreshVisibility{false}; QVector buttons; if (mButtonHash.contains(window)) buttons.append(mButtonHash.value(window)); // If group is based on that window properties must be changed also on button group if (window == windowId()) buttons.append(this); if (!buttons.isEmpty()) { // if class is changed the window won't belong to our group any more if (parentTaskBar()->isGroupingEnabled() && prop2.testFlag(NET::WM2WindowClass)) { KWindowInfo info(window, 0, NET::WM2WindowClass); if (info.windowClassClass() != mGroupName) { onWindowRemoved(window); return false; } } // window changed virtual desktop if (prop.testFlag(NET::WMDesktop) || prop.testFlag(NET::WMGeometry)) { if (parentTaskBar()->isShowOnlyOneDesktopTasks() || parentTaskBar()->isShowOnlyCurrentScreenTasks()) { needsRefreshVisibility = true; } } // if (prop.testFlag(NET::WMVisibleName) || prop.testFlag(NET::WMName)) // std::for_each(buttons.begin(), buttons.end(), std::mem_fn(&UKUITaskButton::updateText)); // XXX: we are setting window icon geometry -> don't need to handle NET::WMIconGeometry // Icon of the button can be based on windowClass // if (prop.testFlag(NET::WMIcon) || prop2.testFlag(NET::WM2WindowClass)) // std::for_each(buttons.begin(), buttons.end(), std::mem_fn(&UKUITaskButton::updateIcon)); if (prop.testFlag(NET::WMState)) { KWindowInfo info{window, NET::WMState}; if (info.hasState(NET::SkipTaskbar)) onWindowRemoved(window); // std::for_each(buttons.begin(), buttons.end(), std::bind(&UKUITaskButton::setUrgencyHint, std::placeholders::_1, info.hasState(NET::DemandsAttention))); if (parentTaskBar()->isShowOnlyMinimizedTasks()) { needsRefreshVisibility = true; } } } if (needsRefreshVisibility) refreshVisibility(); return true; } /************************************************ ************************************************/ void UKUITaskGroup::groupPopupShown(UKUITaskGroup * const sender) { //close all popups (should they be visible because of close delay) if (this != sender && isVisible()) setPopupVisible(false, true/*fast*/); } void UKUITaskGroup::removeWidget() { mPopup->layout()->removeWidget(mpWidget); QHBoxLayout *hLayout = dynamic_cast(mpWidget->layout()); QVBoxLayout *vLayout = dynamic_cast(mpWidget->layout()); if(hLayout != NULL) { hLayout->deleteLater(); hLayout = NULL; } if(vLayout != NULL) { vLayout->deleteLater(); vLayout = NULL; } mpWidget->deleteLater(); mpWidget = NULL; } void UKUITaskGroup::setLayOutForPostion() { if(plugin()->panel()->isHorizontal()) { mpWidget->setLayout(new QHBoxLayout); mpWidget->layout()->setSpacing(3); mpWidget->layout()->setMargin(3); } else { mpWidget->setLayout(new QVBoxLayout); mpWidget->layout()->setSpacing(3); mpWidget->layout()->setMargin(3); } } bool UKUITaskGroup::isSetMaxWindow() { int iScreenWidth = QApplication::screens().at(0)->size().width(); int iScreenHeight = QApplication::screens().at(0)->size().height(); if((iScreenWidth >= SCREEN_MID_WIDTH_SIZE)||((iScreenWidth > SCREEN_MAX_WIDTH_SIZE) && (iScreenHeight > SCREEN_MAX_HEIGHT_SIZE))) { return true; } else { return false; } } void UKUITaskGroup::showPreview() { XImage *img = NULL; Display *display = NULL; QPixmap thumbnail; XWindowAttributes attr; int winWidth = 0; int winHeight = 0; int iAverageWidth = calcAverageWidth(); int iAverageHeight = calcAverageHeight(); /*begin get the winsize*/ bool isMaxWinSize = isSetMaxWindow(); if(isMaxWinSize) { if(0 == iAverageWidth) { winHeight = PREVIEW_WIDGET_MAX_HEIGHT < iAverageHeight?PREVIEW_WIDGET_MAX_HEIGHT:iAverageHeight; winWidth = winHeight*PREVIEW_WIDGET_MAX_WIDTH/PREVIEW_WIDGET_MAX_HEIGHT; } else { winWidth = PREVIEW_WIDGET_MAX_WIDTH < iAverageWidth?PREVIEW_WIDGET_MAX_WIDTH:iAverageWidth; winHeight = winWidth*PREVIEW_WIDGET_MAX_HEIGHT/PREVIEW_WIDGET_MAX_WIDTH; } } else { if(0 == iAverageWidth) { winHeight = PREVIEW_WIDGET_MIN_HEIGHT < iAverageHeight?PREVIEW_WIDGET_MIN_HEIGHT:iAverageHeight; winWidth = winHeight*PREVIEW_WIDGET_MIN_WIDTH/PREVIEW_WIDGET_MIN_HEIGHT; } else { winWidth = PREVIEW_WIDGET_MIN_WIDTH < iAverageWidth?PREVIEW_WIDGET_MIN_WIDTH:iAverageWidth; winHeight = winWidth*PREVIEW_WIDGET_MIN_HEIGHT/PREVIEW_WIDGET_MIN_WIDTH; } } /*end get the winsize*/ if(mPopup->layout()->count() > 0) { removeWidget(); } mpWidget = new QWidget; mpWidget->setAttribute(Qt::WA_TranslucentBackground); setLayOutForPostion(); /*begin catch preview picture*/ for (UKUITaskButtonHash::const_iterator it = mButtonHash.begin();it != mButtonHash.end();it++) { UKUITaskWidget *btn = it.value(); display = XOpenDisplay(nullptr); XGetWindowAttributes(display, it.key(), &attr); img = XGetImage(display, it.key(), 0, 0, attr.width, attr.height, 0xffffffff,ZPixmap); if(img) { thumbnail = qimageFromXImage(img).scaled(THUMBNAIL_WIDTH,THUMBNAIL_HEIGHT,Qt::KeepAspectRatio,Qt::SmoothTransformation); //thumbnail.save(QString("/tmp/picture/%1.png").arg(it.key())); test picture if correct btn->setThumbNail(thumbnail); } else { QPixmap emptyThumbnail; btn->setThumbNail(emptyThumbnail); qDebug()<<"can not catch picture"; } // UKUITaskWidget *btn = it.value(); // btn->setThumbNail(thumbnail); btn->updateTitle(); btn->setFixedSize(winWidth, winHeight); mpWidget->layout()->setContentsMargins(0,0,0,0); mpWidget->layout()->addWidget(btn); if(img) { XDestroyImage(img); } if(display) { XCloseDisplay(display); } } /*end*/ plugin()->willShowWindow(mPopup); mPopup->layout()->addWidget(mpWidget); adjustPopWindowSize(winWidth, winHeight); mPopup->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(0,0)), mPopup->size())); mPopup->show(); emit popupShown(this); } void UKUITaskGroup::adjustPopWindowSize(int winWidth, int winHeight) { if(plugin()->panel()->isHorizontal()) { mPopup->setFixedSize(winWidth*mButtonHash.size() + (mButtonHash.size() + 1)*3, winHeight + 6); } else { mPopup->setFixedSize(winWidth + 6,winHeight*mButtonHash.size() + (mButtonHash.size() + 1)*3); } mPopup->adjustSize(); } void UKUITaskGroup::timeout() { if(mTaskGroupEvent == ENTEREVENT) { if(mTimer->isActive()) { mTimer->stop(); } handleSavedEvent(); } else if(mTaskGroupEvent == LEAVEEVENT) { if(mTimer->isActive()) { mTimer->stop(); } setPopupVisible(false); QToolButton::leaveEvent(mEvent); taskgroupStatus = NORMAL; update(); } else { setPopupVisible(false); } } int UKUITaskGroup::calcAverageHeight() { if(plugin()->panel()->isHorizontal()) { return 0; } else { int iScreenHeight = QApplication::screens().at(0)->size().height(); int iMarginHeight = (mButtonHash.size()+1)*3; int iAverageHeight = (iScreenHeight - iMarginHeight)/mButtonHash.size();//calculate average width of window return iAverageHeight; } } int UKUITaskGroup::calcAverageWidth() { if(plugin()->panel()->isHorizontal()) { int iScreenWidth = QApplication::screens().at(0)->size().width(); int iMarginWidth = (mButtonHash.size()+1)*3; int iAverageWidth = (iScreenWidth - iMarginWidth)/mButtonHash.size();//calculate average width of window return iAverageWidth; } else { return 0; } } void UKUITaskGroup::showAllWindowByList() { } void UKUITaskGroup::showAllWindowByThumbnail() { } ukui-panel/plugin-taskbar/ukuitaskbarplugin.cpp0000644000175000017500000000270513633355350020755 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuitaskbarplugin.h" UKUITaskBarPlugin::UKUITaskBarPlugin(const IUKUIPanelPluginStartupInfo &startupInfo): QObject(), IUKUIPanelPlugin(startupInfo) { mTaskBar = new UKUITaskBar(this); } UKUITaskBarPlugin::~UKUITaskBarPlugin() { delete mTaskBar; } QDialog *UKUITaskBarPlugin::configureDialog() { return new UKUITaskbarConfiguration(settings()); } void UKUITaskBarPlugin::realign() { mTaskBar->realign(); } ukui-panel/plugin-taskbar/ukuitaskbarplugin.h0000644000175000017500000000423113633355350020416 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKBARPLUGIN_H #define UKUITASKBARPLUGIN_H #include "../panel/iukuipanel.h" #include "../panel/iukuipanelplugin.h" #include "ukuitaskbar.h" #include class UKUITaskBar; class UKUITaskBarPlugin : public QObject, public IUKUIPanelPlugin { Q_OBJECT public: UKUITaskBarPlugin(const IUKUIPanelPluginStartupInfo &startupInfo); ~UKUITaskBarPlugin(); QString themeId() const { return "TaskBar"; } virtual Flags flags() const { return HaveConfigDialog | NeedsHandle; } QWidget *widget() { return mTaskBar; } QDialog *configureDialog(); void settingsChanged() { mTaskBar->settingsChanged(); } void realign(); bool isSeparate() const { return true; } bool isExpandable() const { return true; } private: UKUITaskBar *mTaskBar; }; class UKUITaskBarPluginLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT // Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new UKUITaskBarPlugin(startupInfo);} }; #endif // UKUITASKBARPLUGIN_H ukui-panel/plugin-taskbar/ukuitaskwidget.h0000644000175000017500000001023113642614010017702 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include "../panel/iukuipanel.h" //#include #include #include #include #include class QPainter; class QPalette; class QMimeData; class UKUITaskGroup; class UKUITaskBar; class UKUITaskCloseButton; class UKUITaskWidget : public QWidget { Q_OBJECT Q_PROPERTY(Qt::Corner origin READ origin WRITE setOrigin) public: explicit UKUITaskWidget(const WId window, UKUITaskBar * taskBar, QWidget *parent = 0); virtual ~UKUITaskWidget(); bool isApplicationHidden() const; bool isApplicationActive() const; WId windowId() const { return mWindow; } bool hasUrgencyHint() const { return mUrgencyHint; } void setUrgencyHint(bool set); bool isOnDesktop(int desktop) const; bool isOnCurrentScreen() const; bool isMinimized() const; void updateText(); Qt::Corner origin() const; virtual void setAutoRotation(bool value, IUKUIPanel::Position position); UKUITaskBar * parentTaskBar() const {return mParentTaskBar;} void refreshIconGeometry(QRect const & geom); static QString mimeDataFormat() { return QLatin1String("ukui/UKUITaskWidget"); } /*! \return true if this buttom received DragEnter event (and no DragLeave event yet) * */ bool hasDragAndDropHover() const; void setThumbNail(QPixmap _pixmap); void updateTitle(); public slots: void raiseApplication(); void minimizeApplication(); void maximizeApplication(); void deMaximizeApplication(); void shadeApplication(); void unShadeApplication(); void closeApplication(); void moveApplicationToDesktop(); void moveApplication(); void resizeApplication(); void setApplicationLayer(); void setOrigin(Qt::Corner); void updateIcon(); protected: virtual void dragEnterEvent(QDragEnterEvent *event); virtual void dragMoveEvent(QDragMoveEvent * event); virtual void dragLeaveEvent(QDragLeaveEvent *event); virtual void dropEvent(QDropEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void enterEvent(QEvent *); void leaveEvent(QEvent *); void paintEvent(QPaintEvent *); void setWindowId(WId wid) {mWindow = wid;} virtual QMimeData * mimeData(); static bool sDraggging; inline IUKUIPanelPlugin * plugin() const { return mPlugin; } private: WId mWindow; bool mUrgencyHint; QPoint mDragStartPosition; Qt::Corner mOrigin; QPixmap mPixmap; bool mDrawPixmap; UKUITaskBar * mParentTaskBar; IUKUIPanelPlugin * mPlugin; QLabel *mTitleLabel; QLabel *mThumbnailLabel; QLabel *mAppIcon; UKUITaskCloseButton *mCloseBtn; QVBoxLayout *mVWindowsLayout; QHBoxLayout *mTopBarLayout; // Timer for when draggind something into a button (the button's window // must be activated so that the use can continue dragging to the window QTimer * mDNDTimer; enum TaskWidgetStatus{NORMAL, HOVER, PRESS}; TaskWidgetStatus status; bool taskWidgetPress; //按钮左键是否按下 private slots: void activateWithDraggable(); signals: void dropped(QObject * dragSource, QPoint const & pos); void dragging(QObject * dragSource, QPoint const & pos); void windowMaximize(); }; typedef QHash UKUITaskButtonHash; #endif // UKUITASKWIDGET_H ukui-panel/plugin-taskbar/ukuigrouppopup.h0000644000175000017500000000451213642614010017761 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKPOPUP_H #define UKUITASKPOPUP_H #include #include #include #include #include #include "ukuitaskbutton.h" #include "ukuitaskgroup.h" #include "ukuitaskbar.h" class UKUIGroupPopup: public QFrame { Q_OBJECT public: UKUIGroupPopup(UKUITaskGroup *group); ~UKUIGroupPopup(); void hide(bool fast = false); void show(); // Layout int indexOf(UKUITaskButton *button) { return layout()->indexOf(button); } int count() { return layout()->count(); } QLayoutItem * itemAt(int i) { return layout()->itemAt(i); } int spacing() { return layout()->spacing(); } void addButton(UKUITaskButton* button) { layout()->addWidget(button); } void removeWidget(QWidget *button) { layout()->removeWidget(button); } protected: void dragEnterEvent(QDragEnterEvent * event); void dragLeaveEvent(QDragLeaveEvent *event); void dropEvent(QDropEvent * event); void leaveEvent(QEvent * event); void enterEvent(QEvent * event); void paintEvent(QPaintEvent * event); void closeTimerSlot(); private: UKUITaskGroup *mGroup; QTimer mCloseTimer; private slots: void killTimerDelay(); void closeWindowDelay(); }; #endif // UKUITASKPOPUP_H ukui-panel/plugin-taskbar/ukuigrouppopup.cpp0000644000175000017500000001300713642614010020313 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuigrouppopup.h" #include #include #include #include #include #include #include #include #include /************************************************ this class is just a container of window buttons the main purpose is showing window buttons in vertical layout and drag&drop feature inside group ************************************************/ UKUIGroupPopup::UKUIGroupPopup(UKUITaskGroup *group): QFrame(group), mGroup(group) { Q_ASSERT(group); setAcceptDrops(true); setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip); setAttribute(Qt::WA_AlwaysShowToolTips); setAttribute(Qt::WA_TranslucentBackground); setLayout(new QHBoxLayout); layout()->setSpacing(3); layout()->setMargin(3); connect(&mCloseTimer, &QTimer::timeout, this, &UKUIGroupPopup::closeTimerSlot); mCloseTimer.setSingleShot(true); mCloseTimer.setInterval(400); setMaximumWidth(QApplication::screens().at(0)->size().width()); setMaximumHeight(QApplication::screens().at(0)->size().height()); } UKUIGroupPopup::~UKUIGroupPopup() { } void UKUIGroupPopup::dropEvent(QDropEvent *event) { qlonglong temp; QDataStream stream(event->mimeData()->data(UKUITaskButton::mimeDataFormat())); stream >> temp; WId window = (WId) temp; UKUITaskButton *button = nullptr; int oldIndex(0); // get current position of the button being dragged for (int i = 0; i < layout()->count(); i++) { UKUITaskButton *b = qobject_cast(layout()->itemAt(i)->widget()); if (b && b->windowId() == window) { button = b; oldIndex = i; break; } } if (button == nullptr) return; int newIndex = -1; // find the new position to place it in for (int i = 0; i < oldIndex && newIndex == -1; i++) { QWidget *w = layout()->itemAt(i)->widget(); if (w && w->pos().y() + w->height() / 2 > event->pos().y()) newIndex = i; } const int size = layout()->count(); for (int i = size - 1; i > oldIndex && newIndex == -1; i--) { QWidget *w = layout()->itemAt(i)->widget(); if (w && w->pos().y() + w->height() / 2 < event->pos().y()) newIndex = i; } if (newIndex == -1 || newIndex == oldIndex) return; QVBoxLayout * l = qobject_cast(layout()); l->takeAt(oldIndex); l->insertWidget(newIndex, button); l->invalidate(); } void UKUIGroupPopup::dragEnterEvent(QDragEnterEvent *event) { event->accept(); QWidget::dragEnterEvent(event); } void UKUIGroupPopup::dragLeaveEvent(QDragLeaveEvent *event) { hide(false/*not fast*/); QFrame::dragLeaveEvent(event); } /************************************************ * ************************************************/ void UKUIGroupPopup::leaveEvent(QEvent *event) { // qDebug()<<"UKUIGroupPopup::leaveEvent:"<drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } void UKUIGroupPopup::hide(bool fast) { if (fast) close(); else mCloseTimer.start(); } void UKUIGroupPopup::show() { mCloseTimer.stop(); QFrame::show(); } void UKUIGroupPopup::closeTimerSlot() { bool button_has_dnd_hover = false; QLayout* l = layout(); for (int i = 0; l->count() > i; ++i) { UKUITaskWidget const * const button = dynamic_cast(l->itemAt(i)->widget()); if (0 != button && button->hasDragAndDropHover()) { button_has_dnd_hover = true; break; } } if (!button_has_dnd_hover) close(); } ukui-panel/plugin-taskbar/CMakeLists.txt0000644000175000017500000000147013632320722017235 0ustar fengfengset(PLUGIN "taskbar") set(HEADERS ukuitaskbar.h ukuitaskbutton.h ukuitaskbarconfiguration.h ukuitaskbarplugin.h ukuitaskgroup.h ukuigrouppopup.h ukuitaskwidget.h ukuitaskclosebutton.h ) set(SOURCES ukuitaskbar.cpp ukuitaskbutton.cpp ukuitaskbarconfiguration.cpp ukuitaskbarplugin.cpp ukuitaskgroup.cpp ukuigrouppopup.cpp ukuitaskwidget.cpp ukuitaskclosebutton.cpp ) set(UIS ukuitaskbarconfiguration.ui ) set(LIBRARIES Qt5Xdg Qt5X11Extras ) find_package(X11 REQUIRED) #find_package(PkgConfig) ##configure_file(no_keywords link_pkgconfig) #pkg_check_modules(TASKBAR_DEPS REQUIRED Qt5X11Extras) #include_directories(${TASKBAR_DEPS_INCLUDE_DIRS}) #ADD_DEFINITIONS(-DQT_NO_KEYWORDS) #link_libraries(libQt5X11Extras.so) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel/plugin-taskbar/ukuitaskbar.cpp0000644000175000017500000005673113642614010017535 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include #include #include #include #include #include #include #include #include #include #include #include #include "../panel/common/ukuigridlayout.h" #include #include "ukuitaskbar.h" #include "ukuitaskgroup.h" using namespace UKUi; /************************************************ ************************************************/ UKUITaskBar::UKUITaskBar(IUKUIPanelPlugin *plugin, QWidget *parent) : QFrame(parent), mSignalMapper(new QSignalMapper(this)), mButtonStyle(Qt::ToolButtonTextBesideIcon), mButtonWidth(400), mButtonHeight(100), mCloseOnMiddleClick(true), mRaiseOnCurrentDesktop(true), mShowOnlyOneDesktopTasks(false), mShowDesktopNum(0), mShowOnlyCurrentScreenTasks(false), mShowOnlyMinimizedTasks(false), mAutoRotate(true), mGroupingEnabled(true), mShowGroupOnHover(true), mIconByClass(false), mCycleOnWheelScroll(true), mPlugin(plugin), mPlaceHolder(new QWidget(this)), mStyle(new LeftAlignedTextStyle()) { taskstatus=NORMAL; setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 setWindowFlags(Qt::FramelessWindowHint); //设置无边框窗口 setStyle(mStyle); mLayout = new UKUi::GridLayout(this); setLayout(mLayout); mLayout->setMargin(0); mLayout->setStretch(UKUi::GridLayout::StretchHorizontal | UKUi::GridLayout::StretchVertical); realign(); mPlaceHolder->setMinimumSize(1, 1); mPlaceHolder->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); mPlaceHolder->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); mLayout->addWidget(mPlaceHolder); QTimer::singleShot(0, this, SLOT(settingsChanged())); setAcceptDrops(true); connect(mSignalMapper, static_cast(&QSignalMapper::mapped), this, &UKUITaskBar::activateTask); QTimer::singleShot(0, this, &UKUITaskBar::registerShortcuts); connect(KWindowSystem::self(), static_cast(&KWindowSystem::windowChanged) , this, &UKUITaskBar::onWindowChanged); connect(KWindowSystem::self(), &KWindowSystem::windowAdded, this, &UKUITaskBar::onWindowAdded); connect(KWindowSystem::self(), &KWindowSystem::windowRemoved, this, &UKUITaskBar::onWindowRemoved); } /************************************************ ************************************************/ UKUITaskBar::~UKUITaskBar() { delete mStyle; } /************************************************ ************************************************/ bool UKUITaskBar::acceptWindow(WId window) const { QFlags ignoreList; ignoreList |= NET::DesktopMask; ignoreList |= NET::DockMask; ignoreList |= NET::SplashMask; ignoreList |= NET::ToolbarMask; ignoreList |= NET::MenuMask; ignoreList |= NET::PopupMenuMask; ignoreList |= NET::NotificationMask; KWindowInfo info(window, NET::WMWindowType | NET::WMState, NET::WM2TransientFor); if (!info.valid()) return false; if (NET::typeMatchesMask(info.windowType(NET::AllTypesMask), ignoreList)) return false; if (info.state() & NET::SkipTaskbar) return false; // WM_TRANSIENT_FOR hint not set - normal window WId transFor = info.transientFor(); if (transFor == 0 || transFor == window || transFor == (WId) QX11Info::appRootWindow()) return true; info = KWindowInfo(transFor, NET::WMWindowType); QFlags normalFlag; normalFlag |= NET::NormalMask; normalFlag |= NET::DialogMask; normalFlag |= NET::UtilityMask; return !NET::typeMatchesMask(info.windowType(NET::AllTypesMask), normalFlag); } /************************************************ ************************************************/ void UKUITaskBar::dragEnterEvent(QDragEnterEvent* event) { if (event->mimeData()->hasFormat(UKUITaskGroup::mimeDataFormat())) { event->acceptProposedAction(); buttonMove(nullptr, qobject_cast(event->source()), event->pos()); } else event->ignore(); QWidget::dragEnterEvent(event); } /************************************************ ************************************************/ void UKUITaskBar::dragMoveEvent(QDragMoveEvent * event) { //we don't get any dragMoveEvents if dragEnter wasn't accepted buttonMove(nullptr, qobject_cast(event->source()), event->pos()); QWidget::dragMoveEvent(event); } /************************************************ ************************************************/ void UKUITaskBar::buttonMove(UKUITaskGroup * dst, UKUITaskGroup * src, QPoint const & pos) { int src_index; if (!src || -1 == (src_index = mLayout->indexOf(src))) { qDebug() << "Dropped invalid"; return; } const int size = mLayout->count(); Q_ASSERT(0 < size); //dst is nullptr in case the drop occured on empty space in taskbar int dst_index; if (nullptr == dst) { //moving based on taskbar (not signaled by button) QRect occupied = mLayout->occupiedGeometry(); QRect last_empty_row{occupied}; const QRect last_item_geometry = mLayout->itemAt(size - 1)->geometry(); if (mPlugin->panel()->isHorizontal()) { if (isRightToLeft()) { last_empty_row.setTopRight(last_item_geometry.topLeft()); } else { last_empty_row.setTopLeft(last_item_geometry.topRight()); } } else { if (isRightToLeft()) { last_empty_row.setTopRight(last_item_geometry.topRight()); } else { last_empty_row.setTopLeft(last_item_geometry.topLeft()); } } if (occupied.contains(pos) && !last_empty_row.contains(pos)) return; dst_index = size; } else { //moving based on signal from child button dst_index = mLayout->indexOf(dst); } //moving lower index to higher one => consider as the QList::move => insert(to, takeAt(from)) if (src_index < dst_index) { if (size == dst_index || src_index + 1 != dst_index) { --dst_index; } else { //switching positions of next standing const int tmp_index = src_index; src_index = dst_index; dst_index = tmp_index; } } if (dst_index == src_index || mLayout->animatedMoveInProgress() ) return; mLayout->moveItem(src_index, dst_index, true); } /************************************************ ************************************************/ void UKUITaskBar::groupBecomeEmptySlot() { //group now contains no buttons - clean up in hash and delete the group UKUITaskGroup * const group = qobject_cast(sender()); Q_ASSERT(group); for (auto i = mKnownWindows.begin(); mKnownWindows.end() != i; ) { if (group == *i) i = mKnownWindows.erase(i); else ++i; } mLayout->removeWidget(group); group->deleteLater(); } /************************************************ ************************************************/ void UKUITaskBar::addWindow(WId window) { // If grouping disabled group behaves like regular button const QString group_id = mGroupingEnabled ? KWindowInfo(window, 0, NET::WM2WindowClass).windowClassClass() : QString("%1").arg(window); UKUITaskGroup *group = nullptr; auto i_group = mKnownWindows.find(window); if (mKnownWindows.end() != i_group) { if ((*i_group)->groupName() == group_id) group = *i_group; else (*i_group)->onWindowRemoved(window); } //check if window belongs to some existing group if (!group && mGroupingEnabled) { for (auto i = mKnownWindows.cbegin(), i_e = mKnownWindows.cend(); i != i_e; ++i) { if ((*i)->groupName() == group_id) { group = *i; break; } } } if (!group) { group = new UKUITaskGroup(group_id, window, this); connect(group, SIGNAL(groupBecomeEmpty(QString)), this, SLOT(groupBecomeEmptySlot())); connect(group, SIGNAL(visibilityChanged(bool)), this, SLOT(refreshPlaceholderVisibility())); connect(group, &UKUITaskGroup::popupShown, this, &UKUITaskBar::popupShown); connect(group, &UKUITaskButton::dragging, this, [this] (QObject * dragSource, QPoint const & pos) { buttonMove(qobject_cast(sender()), qobject_cast(dragSource), pos); }); group->setFixedSize(panel()->panelSize(),panel()->panelSize()); mLayout->addWidget(group); group->setToolButtonsStyle(mButtonStyle); } mKnownWindows[window] = group; group->addWindow(window); group->groupName(); } /************************************************ ************************************************/ auto UKUITaskBar::removeWindow(windowMap_t::iterator pos) -> windowMap_t::iterator { WId const window = pos.key(); UKUITaskGroup * const group = *pos; auto ret = mKnownWindows.erase(pos); group->onWindowRemoved(window); return ret; } /************************************************ ************************************************/ void UKUITaskBar::refreshTaskList() { QList new_list; // Just add new windows to groups, deleting is up to the groups const auto wnds = KWindowSystem::stackingOrder(); for (auto const wnd: wnds) { if (acceptWindow(wnd)) { new_list << wnd; addWindow(wnd); } } //emulate windowRemoved if known window not reported by KWindowSystem for (auto i = mKnownWindows.begin(), i_e = mKnownWindows.end(); i != i_e; ) { if (0 > new_list.indexOf(i.key())) { i = removeWindow(i); } else ++i; } refreshPlaceholderVisibility(); } /************************************************ ************************************************/ void UKUITaskBar::onWindowChanged(WId window, NET::Properties prop, NET::Properties2 prop2) { auto i = mKnownWindows.find(window); if (mKnownWindows.end() != i) { if (!(*i)->onWindowChanged(window, prop, prop2) && acceptWindow(window)) { // window is removed from a group because of class change, so we should add it again addWindow(window); } } } void UKUITaskBar::onWindowAdded(WId window) { auto const pos = mKnownWindows.find(window); if (mKnownWindows.end() == pos && acceptWindow(window)) addWindow(window); } /************************************************ ************************************************/ void UKUITaskBar::onWindowRemoved(WId window) { auto const pos = mKnownWindows.find(window); if (mKnownWindows.end() != pos) { removeWindow(pos); } } /************************************************ ************************************************/ void UKUITaskBar::refreshButtonRotation() { bool autoRotate = mAutoRotate && (mButtonStyle != Qt::ToolButtonIconOnly); IUKUIPanel::Position panelPosition = mPlugin->panel()->position(); emit buttonRotationRefreshed(autoRotate, panelPosition); } /************************************************ ************************************************/ void UKUITaskBar::refreshPlaceholderVisibility() { // if no visible group button show placeholder widget bool haveVisibleWindow = false; for (auto i = mKnownWindows.cbegin(), i_e = mKnownWindows.cend(); i_e != i; ++i) { if ((*i)->isVisible()) { haveVisibleWindow = true; break; } } mPlaceHolder->setVisible(!haveVisibleWindow); if (haveVisibleWindow) mPlaceHolder->setFixedSize(0, 0); else { mPlaceHolder->setMinimumSize(1, 1); mPlaceHolder->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); } } /************************************************ ************************************************/ void UKUITaskBar::setButtonStyle(Qt::ToolButtonStyle buttonStyle) { const Qt::ToolButtonStyle old_style = mButtonStyle; mButtonStyle = buttonStyle; if (old_style != mButtonStyle) emit buttonStyleRefreshed(mButtonStyle); } void UKUITaskBar::setShowGroupOnHover(bool bFlag) { mShowGroupOnHover = bFlag; } /************************************************ ************************************************/ void UKUITaskBar::settingsChanged() { bool groupingEnabledOld = mGroupingEnabled; bool showOnlyOneDesktopTasksOld = mShowOnlyOneDesktopTasks; const int showDesktopNumOld = mShowDesktopNum; bool showOnlyCurrentScreenTasksOld = mShowOnlyCurrentScreenTasks; bool showOnlyMinimizedTasksOld = mShowOnlyMinimizedTasks; const bool iconByClassOld = mIconByClass; mButtonWidth = mPlugin->settings()->value("buttonWidth", 400).toInt(); mButtonHeight = mPlugin->settings()->value("buttonHeight", 100).toInt(); QString s = mPlugin->settings()->value("buttonStyle").toString().toUpper(); if (s == "ICON") setButtonStyle(Qt::ToolButtonIconOnly); else if (s == "TEXT") setButtonStyle(Qt::ToolButtonTextOnly); else setButtonStyle(Qt::ToolButtonIconOnly); mShowOnlyOneDesktopTasks = mPlugin->settings()->value("showOnlyOneDesktopTasks", mShowOnlyOneDesktopTasks).toBool(); mShowDesktopNum = mPlugin->settings()->value("showDesktopNum", mShowDesktopNum).toInt(); mShowOnlyCurrentScreenTasks = mPlugin->settings()->value("showOnlyCurrentScreenTasks", mShowOnlyCurrentScreenTasks).toBool(); mShowOnlyMinimizedTasks = mPlugin->settings()->value("showOnlyMinimizedTasks", mShowOnlyMinimizedTasks).toBool(); mAutoRotate = mPlugin->settings()->value("autoRotate", true).toBool(); mCloseOnMiddleClick = mPlugin->settings()->value("closeOnMiddleClick", true).toBool(); mRaiseOnCurrentDesktop = mPlugin->settings()->value("raiseOnCurrentDesktop", false).toBool(); mGroupingEnabled = mPlugin->settings()->value("groupingEnabled",true).toBool(); mShowGroupOnHover = mPlugin->settings()->value("showGroupOnHover",true).toBool(); mIconByClass = mPlugin->settings()->value("iconByClass", false).toBool(); mCycleOnWheelScroll = mPlugin->settings()->value("cycleOnWheelScroll", true).toBool(); // Delete all groups if grouping feature toggled and start over if (groupingEnabledOld != mGroupingEnabled) { for (int i = mLayout->count() - 1; 0 <= i; --i) { UKUITaskGroup * group = qobject_cast(mLayout->itemAt(i)->widget()); if (nullptr != group) { mLayout->takeAt(i); group->deleteLater(); } } mKnownWindows.clear(); } if (showOnlyOneDesktopTasksOld != mShowOnlyOneDesktopTasks || (mShowOnlyOneDesktopTasks && showDesktopNumOld != mShowDesktopNum) || showOnlyCurrentScreenTasksOld != mShowOnlyCurrentScreenTasks || showOnlyMinimizedTasksOld != mShowOnlyMinimizedTasks ) emit showOnlySettingChanged(); if (iconByClassOld != mIconByClass) emit iconByClassChanged(); refreshTaskList(); } /************************************************ ************************************************/ void UKUITaskBar::realign() { mLayout->setEnabled(false); refreshButtonRotation(); IUKUIPanel *panel = mPlugin->panel(); //set taskbar width by panel QSize maxSize = QSize(100, mButtonHeight); QSize minSize = QSize(0, 0); int iconsize = panel->iconSize(); int panelsize = panel->panelSize(); bool rotated = false; if (panel->isHorizontal()) { mLayout->setRowCount(panel->lineCount()); mLayout->setColumnCount(0); } else { mLayout->setRowCount(0); if (mButtonStyle == Qt::ToolButtonIconOnly) { // Vertical + Icons mLayout->setColumnCount(panel->lineCount()); } else { rotated = mAutoRotate && (panel->position() == IUKUIPanel::PositionLeft || panel->position() == IUKUIPanel::PositionRight); // Vertical + Text if (rotated) { maxSize.rwidth() = mButtonHeight; maxSize.rheight() = mButtonWidth; mLayout->setColumnCount(panel->lineCount()); } else { mLayout->setColumnCount(1); } } } for(auto it= mKnownWindows.begin(); it != mKnownWindows.end();it++) { UKUITaskGroup *group = it.value(); group->setFixedSize(panelsize, panelsize); group->setIconSize(QSize(iconsize,iconsize)); group->updateIcon(); } mLayout->setCellMinimumSize(minSize); mLayout->setCellMaximumSize(maxSize); mLayout->setDirection(rotated ? UKUi::GridLayout::TopToBottom : UKUi::GridLayout::LeftToRight); mLayout->setEnabled(true); //our placement on screen could have been changed emit showOnlySettingChanged(); emit refreshIconGeometry(); } /************************************************ ************************************************/ void UKUITaskBar::wheelEvent(QWheelEvent* event) { #if 0 if (!mCycleOnWheelScroll) return QFrame::wheelEvent(event); static int threshold = 0; threshold += abs(event->delta()); if (threshold < 300) return QFrame::wheelEvent(event); else threshold = 0; int delta = event->delta() < 0 ? 1 : -1; // create temporary list of visible groups in the same order like on the layout QList list; UKUITaskGroup *group = NULL; for (int i = 0; i < mLayout->count(); i++) { QWidget * o = mLayout->itemAt(i)->widget(); UKUITaskGroup * g = qobject_cast(o); if (!g) continue; if (g->isVisible()) list.append(g); if (g->isChecked()) group = g; } if (list.isEmpty()) return QFrame::wheelEvent(event); if (!group) group = list.at(0); UKUITaskButton *button = NULL; // switching between groups from temporary list in modulo addressing while (!button)conSize() { button = group->getNextPrevChildButton(delta == 1, !(list.count() - 1)); if (button) button->raiseApplication(); int idx = (list.indexOf(group) + delta + list.count()) % list.count(); group = list.at(idx); } QFrame::wheelEvent(event); #endif } /************************************************ ************************************************/ void UKUITaskBar::resizeEvent(QResizeEvent* event) { emit refreshIconGeometry(); return QWidget::resizeEvent(event); } /************************************************ ************************************************/ void UKUITaskBar::changeEvent(QEvent* event) { // if current style is changed, reset the base style of the proxy style // so we can apply the new style correctly to task buttons. if(event->type() == QEvent::StyleChange) mStyle->setBaseStyle(NULL); QFrame::changeEvent(event); } /************************************************ ************************************************/ void UKUITaskBar::registerShortcuts() { // Register shortcuts to switch to the task // mPlaceHolder is always at position 0 // tasks are at positions 1..10 // GlobalKeyShortcut::Action * gshortcut; // QString path; // QString description; // for (int i = 1; i <= 10; ++i) // { // path = QString("/panel/%1/task_%2").arg(mPlugin->settings()->group()).arg(i); // description = tr("Activate task %1").arg(i); // gshortcut = GlobalKeyShortcut::Client::instance()->addAction(QStringLiteral(), path, description, this); // if (nullptr != gshortcut) // { // mKeys << gshortcut; // connect(gshortcut, &GlobalKeyShortcut::Action::registrationFinished, this, &UKUITaskBar::shortcutRegistered); // connect(gshortcut, &GlobalKeyShortcut::Action::activated, mSignalMapper, static_cast(&QSignalMapper::map)); // mSignalMapper->setMapping(gshortcut, i); // } // } } void UKUITaskBar::shortcutRegistered() { // GlobalKeyShortcut::Action * const shortcut = qobject_cast(sender()); // disconnect(shortcut, &GlobalKeyShortcut::Action::registrationFinished, this, &UKUITaskBar::shortcutRegistered); // const int i = mKeys.indexOf(shortcut); // Q_ASSERT(-1 != i); // if (shortcut->shortcut().isEmpty()) // { // // Shortcuts come in order they were registered // // starting from index 0 // const int key = (i + 1) % 10; // shortcut->changeShortcut(QStringLiteral("Meta+%1").arg(key)); // } } void UKUITaskBar::activateTask(int pos) { for (int i = 1; i < mLayout->count(); ++i) { QWidget * o = mLayout->itemAt(i)->widget(); UKUITaskGroup * g = qobject_cast(o); if (g && g->isVisible()) { pos--; if (pos == 0) { g->raiseApplication(); break; } } } } void UKUITaskBar::enterEvent(QEvent *) { taskstatus=HOVER; update(); } void UKUITaskBar::leaveEvent(QEvent *) { taskstatus=NORMAL; update(); } void UKUITaskBar::paintEvent(QPaintEvent *) { QStyleOption opt; opt.initFrom(this); QPainter p(this); switch(taskstatus) { case NORMAL: { // p.setBrush(QBrush(QColor(0xFF,0xFF,0xFF,0x19))); p.setPen(Qt::NoPen); break; } case HOVER: { // p.setBrush(QBrush(QColor(0xFF,0xFF,0xFF,0x19))); p.setPen(Qt::NoPen); break; } case PRESS: { // p.setBrush(QBrush(QColor(0x13,0x14,0x14,0xb2))); p.setPen(Qt::NoPen); break; } } p.setRenderHint(QPainter::Antialiasing); // 反锯齿; p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } ukui-panel/plugin-taskbar/ukuitaskgroup.h0000644000175000017500000001070013642614010017554 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKGROUP_H #define UKUITASKGROUP_H #include "../panel/iukuipanel.h" #include "../panel/iukuipanelplugin.h" #include "ukuitaskbar.h" #include "ukuigrouppopup.h" #include "ukuitaskwidget.h" #include "ukuitaskbutton.h" #include #include class QVBoxLayout; class IUKUIPanelPlugin; class UKUIGroupPopup; class UKUiMasterPopup; class UKUITaskGroup: public UKUITaskButton { Q_OBJECT public: UKUITaskGroup(const QString & groupName, WId window, UKUITaskBar * parent); virtual ~UKUITaskGroup(); QString groupName() const { return mGroupName; } int buttonsCount() const; int visibleButtonsCount() const; QWidget * addWindow(WId id); QWidget * checkedButton() const; // Returns the next or the previous button in the popup // if circular is true, then it will go around the list of buttons QWidget * getNextPrevChildButton(bool next, bool circular); bool onWindowChanged(WId window, NET::Properties prop, NET::Properties2 prop2); void setAutoRotation(bool value, IUKUIPanel::Position position); Qt::ToolButtonStyle popupButtonStyle() const; void setToolButtonsStyle(Qt::ToolButtonStyle style); void setPopupVisible(bool visible = true, bool fast = false); void removeWidget(); bool isSetMaxWindow(); void showPreview(); int calcAverageWidth(); int calcAverageHeight(); void showAllWindowByList();//when number of window is more than 30,need show all window of app by a list void showAllWindowByThumbnail();//when number of window is no more than 30,need show all window of app by a thumbnail public slots: void onWindowRemoved(WId window); void timeout(); protected: QMimeData * mimeData(); void leaveEvent(QEvent * event); void enterEvent(QEvent * event); void dragEnterEvent(QDragEnterEvent * event); void dragLeaveEvent(QDragLeaveEvent * event); void contextMenuEvent(QContextMenuEvent * event); void mouseMoveEvent(QMouseEvent * event); // void paintEvent(QPaintEvent *); int recalculateFrameHeight() const; int recalculateFrameWidth() const; void setLayOutForPostion(); void draggingTimerTimeout(); private slots: void onClicked(bool checked); void onChildButtonClicked(); void onActiveWindowChanged(WId window); void onDesktopChanged(int number); void closeGroup(); void refreshIconsGeometry(); void refreshVisibility(); void groupPopupShown(UKUITaskGroup* sender); void handleSavedEvent(); signals: void groupBecomeEmpty(QString name); void visibilityChanged(bool visible); void popupShown(UKUITaskGroup* sender); private: QString mGroupName; UKUIGroupPopup * mPopup; QVBoxLayout *VLayout; UKUITaskButtonHash mButtonHash; bool mPreventPopup; bool mSingleButton; //!< flag if this group should act as a "standard" button (no groupping or only one "shown" window in group) enum TaskGroupStatus{NORMAL, HOVER, PRESS}; enum TaskGroupEvent{ENTEREVENT, LEAVEEVENT, OTHEREVENT}; TaskGroupStatus taskgroupStatus; TaskGroupEvent mTaskGroupEvent; QWidget *mpWidget; QEvent * mEvent; QTimer *mTimer; QSize recalculateFrameSize(); QPoint recalculateFramePosition(); void recalculateFrameIfVisible(); void adjustPopWindowSize(int width, int height); void regroup(); }; #endif // UKUITASKGROUP_H ukui-panel/plugin-taskbar/ukuitaskclosebutton.h0000644000175000017500000000221313633355350020772 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include class UKUITaskCloseButton : public QToolButton { Q_OBJECT public: explicit UKUITaskCloseButton(const WId window, QWidget *parent = 0); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); private: WId mWindow; signals: void sigClicked(); }; #endif // UKUITASKCLOSEBUTTON_H ukui-panel/plugin-taskview/0000755000175000017500000000000013643551442014710 5ustar fengfengukui-panel/plugin-taskview/taskview.cpp0000644000175000017500000000534413643551442017257 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include "../panel/customstyle.h" #include #include TaskViewButton::TaskViewButton(){ } TaskViewButton::~TaskViewButton(){ } TaskView::TaskView(const IUKUIPanelPluginStartupInfo &startupInfo) : QObject(), IUKUIPanelPlugin(startupInfo) { mButton =new TaskViewButton(); mButton->setStyle(new CustomStyle()); mButton->setIcon(QIcon("/usr/share/ukui-panel/panel/img/taskview.svg")); mButton->paintTooltipStyle(); mButton->setToolTip(tr("taskviewWindow")); realign(); } TaskView::~TaskView() { } void TaskView::realign() { mButton->setFixedSize(panel()->panelSize(),panel()->panelSize()); mButton->setIconSize(QSize(panel()->iconSize(),panel()->iconSize())); } void TaskViewButton::mousePressEvent(QMouseEvent *event) { const Qt::MouseButton b = event->button(); if (Qt::LeftButton == b) { //Two ways to call the taskview //system("ukui-window-switch --show-workspace"); QDBusInterface interface("org.ukui.WindowSwitch", "/org/ukui/WindowSwitch", "org.ukui.WindowSwitch", QDBusConnection::sessionBus()); if (!interface.isValid()) { qCritical() << QDBusConnection::sessionBus().lastError().message(); exit(1); } //调用远程的value方法 QDBusReply reply = interface.call("handleWorkspace"); if (reply.isValid()) { if (!reply.value()) qWarning() << "Handle Workspace View Failed"; } else { qCritical() << "Call Dbus method failed"; } } QWidget::mousePressEvent(event); } void TaskViewButton::mouseMoveEvent(QMouseEvent *e) { qDebug()<<"mouse move enent"; QWidget::mouseMoveEvent(e); } void TaskViewButton::contextMenuEvent(QContextMenuEvent *event){ } ukui-panel/plugin-taskview/img/0000755000175000017500000000000013632320722015455 5ustar fengfengukui-panel/plugin-taskview/img/taskview.svg0000644000175000017500000000740713632320722020043 0ustar fengfeng32ukui-panel/plugin-taskview/resources/0000755000175000017500000000000013632320722016713 5ustar fengfengukui-panel/plugin-taskview/resources/taskview.desktop.in0000644000175000017500000000030013632320722022541 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=TaskView Comment=Get the taskview Icon=taskView #TRANSLATIONS_DIR=../translations Name=任务视图 Comment=任务视图插件 ukui-panel/plugin-taskview/CMakeLists.txt0000644000175000017500000000042013632320722017435 0ustar fengfengset(PLUGIN "taskview") set(HEADERS taskview.h ) set(SOURCES taskview.cpp ) set(UIS ) set(LIBRARIES Qt5Xdg ) install(FILES img/taskview.svg DESTINATION "/usr/share/ukui-panel/plugin-taskview/img" COMPONENT Runtime ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel/plugin-taskview/taskview.h0000644000175000017500000000443513643551442016724 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include #include #include "../panel/plugin.h" #include "../panel/ukuipanel.h" #include "../panel/ukuicontrolstyle.h" #define DEFAULT_SHORTCUT "Alt+F1" class TaskViewButton:public UkuiToolButton { Q_OBJECT public: TaskViewButton(); ~TaskViewButton(); protected: void contextMenuEvent(QContextMenuEvent *event); void mousePressEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent*); private: void paintTaskViewStyle(); }; class TaskView: public QObject, public IUKUIPanelPlugin { Q_OBJECT public: TaskView(const IUKUIPanelPluginStartupInfo &startupInfo); ~TaskView(); virtual QWidget *widget() { return mButton; } virtual QString themeId() const { return QStringLiteral("taskview"); } void realign(); virtual IUKUIPanelPlugin::Flags flags() const { return PreferRightAlignment | HaveConfigDialog ; } private: TaskViewButton *mButton; }; class TaskViewLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new TaskView(startupInfo); } }; #endif ukui-panel/plugin-quicklaunch/0000755000175000017500000000000013640370604015356 5ustar fengfengukui-panel/plugin-quicklaunch/resources/0000755000175000017500000000000013632320722017365 5ustar fengfengukui-panel/plugin-quicklaunch/resources/quicklaunch.desktop.in0000644000175000017500000000026313632320722023675 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Quick launch Comment=Easy access to your favourite applications. Icon=quickopen #TRANSLATIONS_DIR=../translations ukui-panel/plugin-quicklaunch/quicklaunchaction.h0000644000175000017500000000545413632320722021241 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef QUICKLAUNCHACTION_H #define QUICKLAUNCHACTION_H #include class XdgDesktopFile; /*! \brief Special action representation forUKUIQuickLaunch plugin. It supports XDG desktop files or "legacy" launching of specified apps. All process management is handled internally. \author Petr Vanek */ class QuickLaunchAction : public QAction { Q_OBJECT public: /*! Constructor for "legacy" launchers. \warning The XDG way is preferred this is only for older or non-standard apps \param name a name to display in tooltip \param exec a executable with path \param icon a valid QIcon */ QuickLaunchAction(const QString & name, const QString & exec, const QString & icon, QWidget * parent); /*! Constructor for XDG desktop handlers. */ QuickLaunchAction(const XdgDesktopFile * xdg, QWidget * parent); /*! Constructor for regular files */ QuickLaunchAction(const QString & fileName, QWidget * parent); //! Returns true if the action is valid (contains all required properties). bool isValid() { return m_valid; } QHash settingsMap() { return m_settingsMap; } /*! Returns list of additional actions to present for user (in menu). * Currently there are only "Addtitional application actions" for the ActionXdg type * (the [Desktop Action %s] in .desktop files) */ QList addtitionalActions() const { return m_addtitionalActions; } QHash m_settingsMap; public slots: void execAction(QString additionalAction = QString{}); private: enum ActionType { ActionLegacy, ActionXdg, ActionFile }; ActionType m_type; QString m_data; bool m_valid; QList m_addtitionalActions; }; #endif ukui-panel/plugin-quicklaunch/ukuiquicklaunch.cpp0000644000175000017500000003702513640370604021276 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2012 Razor team * Authors: * Petr Vanek * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuiquicklaunch.h" #include "quicklaunchbutton.h" #include "quicklaunchaction.h" #include "../panel/iukuipanelplugin.h" #include #include #include #include #include #include #include #include #include #include #include #include "../panel/common/ukuigridlayout.h" #include "../panel/pluginsettings.h" #include #include #include #include #include #include #include #include using namespace std; UKUIQuickLaunch::UKUIQuickLaunch(IUKUIPanelPlugin *plugin, QWidget* parent) : QFrame(parent), mPlugin(plugin), mPlaceHolder(0) { setAcceptDrops(true); mVBtn.clear(); mLayout = new UKUi::GridLayout(this); setLayout(mLayout); QString desktop; QString file; QString execname; QString exec; QString icon; const auto apps = mPlugin->settings()->readArray("apps"); for (const QMap &app : apps) { desktop = app.value("desktop", "").toString(); file = app.value("file", "").toString(); if (!desktop.isEmpty()) { XdgDesktopFile xdg; if (!xdg.load(desktop)) { qDebug() << "XdgDesktopFile" << desktop << "is not valid"; continue; } if (!xdg.isSuitable()) { qDebug() << "XdgDesktopFile" << desktop << "is not applicable"; continue; } addButton(new QuickLaunchAction(&xdg, this)); } else if (! file.isEmpty()) { addButton(new QuickLaunchAction(file, this)); } else { execname = app.value("name", "").toString(); exec = app.value("exec", "").toString(); icon = app.value("icon", "").toString(); if (icon.isNull()) { qDebug() << "Icon" << icon << "is not valid (isNull). Skipped."; continue; } addButton(new QuickLaunchAction(execname, exec, icon, this)); } } // for if (mLayout->isEmpty()) showPlaceHolder(); realign(); } UKUIQuickLaunch::~UKUIQuickLaunch() { for(auto it = mVBtn.begin(); it != mVBtn.end();) { (*it)->deleteLater(); mVBtn.erase(it); } mVBtn.clear(); } int UKUIQuickLaunch::indexOfButton(QuickLaunchButton* button) const { return mLayout->indexOf(button); } int UKUIQuickLaunch::countOfButtons() const { return mLayout->count(); } void UKUIQuickLaunch::realign() { // btn->setIconSize(QSize(mPlugin->panel()->iconSize(),mPlugin->panel()->iconSize())); for(auto it = mVBtn.begin(); it != mVBtn.end(); it++) { (*it)->setFixedSize(mPlugin->panel()->panelSize(),mPlugin->panel()->panelSize()); (*it)->setIconSize(QSize(mPlugin->panel()->iconSize(),mPlugin->panel()->iconSize())); } mLayout->setEnabled(false); IUKUIPanel *panel = mPlugin->panel(); if (mPlaceHolder) { mLayout->setColumnCount(1); mLayout->setRowCount(1); } else { if (panel->isHorizontal()) { mLayout->setRowCount(panel->lineCount()); mLayout->setColumnCount(0); } else { mLayout->setColumnCount(panel->lineCount()); mLayout->setRowCount(0); } } mLayout->setEnabled(true); } void UKUIQuickLaunch::addButton(QuickLaunchAction* action) { mLayout->setEnabled(false); btn = new QuickLaunchButton(action, mPlugin, this); btn->setArrowType(Qt::NoArrow); // btn->setMenu(Qt::InstantPopup); mVBtn.push_back(btn); mLayout->addWidget(btn); btn->setIconSize(QSize(mPlugin->panel()->panelSize(),mPlugin->panel()->panelSize())); connect(btn, SIGNAL(switchButtons(QuickLaunchButton*,QuickLaunchButton*)), this, SLOT(switchButtons(QuickLaunchButton*,QuickLaunchButton*))); connect(btn, SIGNAL(buttonDeleted()), this, SLOT(buttonDeleted())); connect(btn, SIGNAL(movedLeft()), this, SLOT(buttonMoveLeft())); connect(btn, SIGNAL(movedRight()), this, SLOT(buttonMoveRight())); mLayout->removeWidget(mPlaceHolder); mPlaceHolder->deleteLater(); mPlaceHolder = NULL; mLayout->setEnabled(true); realign(); } bool UKUIQuickLaunch::checkButton(QuickLaunchAction* action) { bool checkresult; QuickLaunchButton* btn = new QuickLaunchButton(action, mPlugin, this); int i = 0; QLayoutItem *child; while ((child = mLayout->layout()->itemAt(i))) { QuickLaunchButton *b = qobject_cast(mLayout->itemAt(i)->widget()); if (b->file_name == btn->file_name) { qDebug()<<" already insert "; checkresult=true; break; } else { ++i; qDebug()<<"don't insert "; checkresult=false; } } saveSettings(); return checkresult; } //check by filename void UKUIQuickLaunch::checkButton(QString *filename) { int i = 0; QLayoutItem *child; while ((child = mLayout->layout()->itemAt(i))) { qDebug()<(mLayout->itemAt(i)->widget()); if (b->file_name == filename) { qDebug()<<" already insert "<removeItem(child); } else { ++i; qDebug()<<"not insert "; } } saveSettings(); } void UKUIQuickLaunch::removeButton(QuickLaunchAction* action) { QuickLaunchButton* btn = new QuickLaunchButton(action, mPlugin, this); qDebug()<<"btn->file_name *** >>>"<file_name; int i = 0; QLayoutItem *child; while ((child = mLayout->layout()->itemAt(i))) { qDebug()<(mLayout->itemAt(i)->widget()); qDebug()<<"b->file_name ---"<file_name == btn->file_name) { qDebug()<<"child >>>"<removeItem(child); mLayout->removeWidget(b); //b->deleteLater(); } else { ++i; } } saveSettings(); } //remove by filename void UKUIQuickLaunch::removeButton(QString *filename) { int i = 0; QLayoutItem *child; while ((child = mLayout->layout()->itemAt(i))) { qDebug()<(mLayout->itemAt(i)->widget()); qDebug()<<"b->file_name ---"<file_name; if (b->file_name == filename) { qDebug()<<"child >>>"<removeItem(child); mLayout->removeWidget(b); b->deleteLater(); } else { ++i; } } saveSettings(); } void UKUIQuickLaunch::dragEnterEvent(QDragEnterEvent *e) { // Getting URL from mainmenu... if (e->mimeData()->hasUrls()) { e->acceptProposedAction(); return; } if (e->source() && e->source()->parent() == this) { e->acceptProposedAction(); } } void UKUIQuickLaunch::dropEvent(QDropEvent *e) { const auto urls = e->mimeData()->urls().toSet(); for (const QUrl &url : urls) { QString fileName(url.isLocalFile() ? url.toLocalFile() : url.url()); QFileInfo fi(fileName); XdgDesktopFile xdg; if (xdg.load(fileName)) { if (xdg.isSuitable()) addButton(new QuickLaunchAction(&xdg, this)); } else if (fi.exists() && fi.isExecutable() && !fi.isDir()) { addButton(new QuickLaunchAction(fileName, fileName, "", this)); } else if (fi.exists()) { addButton(new QuickLaunchAction(fileName, this)); } else { qWarning() << "XdgDesktopFile" << fileName << "is not valid"; QMessageBox::information(this, tr("Drop Error"), tr("File/URL '%1' cannot be embedded into QuickLaunch for now").arg(fileName) ); } } saveSettings(); } void UKUIQuickLaunch::paintEvent(QPaintEvent *) { //设置quicklaunch 区域底色 QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } bool UKUIQuickLaunch::AddToTaskbar(QString arg) { const auto url=QUrl(arg); QString fileName(url.isLocalFile() ? url.toLocalFile() : url.url()); QFileInfo fi(fileName); XdgDesktopFile xdg; if (xdg.load(fileName)) { /*This fuction returns true if the desktop file is applicable to the current environment. but I don't need this attributes now */ // if (xdg.isSuitable()) addButton(new QuickLaunchAction(&xdg, this)); } else if (fi.exists() && fi.isExecutable() && !fi.isDir()) { addButton(new QuickLaunchAction(fileName, fileName, "", this)); } else if (fi.exists()) { addButton(new QuickLaunchAction(fileName, this)); } else { qWarning() << "XdgDesktopFile" << fileName << "is not valid"; QMessageBox::information(this, tr("Drop Error"), tr("File/URL '%1' cannot be embedded into QuickLaunch for now").arg(fileName) ); } saveSettings(); return true; } bool UKUIQuickLaunch::CheckIfExist(QString arg) { const auto url=QUrl(arg); QString fileName(url.isLocalFile() ? url.toLocalFile() : url.url()); QFileInfo fi(fileName); XdgDesktopFile xdg; xdg.load(fileName); return checkButton(new QuickLaunchAction(&xdg, this)); } bool UKUIQuickLaunch::RemoveFromTaskbar(QString arg) { const auto url=QUrl(arg); QString fileName(url.isLocalFile() ? url.toLocalFile() : url.url()); QFileInfo fi(fileName); XdgDesktopFile xdg; xdg.load(fileName); removeButton(new QuickLaunchAction(&xdg, this)); return true; } int UKUIQuickLaunch::GetPanelPosition(QString arg) { return mPlugin->panel()->position(); } int UKUIQuickLaunch::GetPanelSize(QString arg) { return mPlugin->panel()->panelSize(); } void UKUIQuickLaunch::switchButtons(QuickLaunchButton *button1, QuickLaunchButton *button2) { if (button1 == button2) return; int n1 = mLayout->indexOf(button1); int n2 = mLayout->indexOf(button2); int l = qMin(n1, n2); int m = qMax(n1, n2); mLayout->moveItem(l, m); mLayout->moveItem(m-1, l); saveSettings(); } void UKUIQuickLaunch::buttonDeleted() { QuickLaunchButton *btn = qobject_cast(sender()); if (!btn) return; mLayout->removeWidget(btn); for(auto it = mVBtn.begin(); it != mVBtn.end();) { if(*it == btn) { mVBtn.erase(it); break; } else { it++; } } btn->deleteLater(); saveSettings(); if (mLayout->isEmpty()) showPlaceHolder(); realign(); } void UKUIQuickLaunch::buttonMoveLeft() { QuickLaunchButton *btn = qobject_cast(sender()); if (!btn) return; int index = indexOfButton(btn); if (index > 0) { mLayout->moveItem(index, index - 1); saveSettings(); } } void UKUIQuickLaunch::buttonMoveRight() { QuickLaunchButton *btn1 = qobject_cast(sender()); if (!btn1) return; int index = indexOfButton(btn1); if (index < countOfButtons() - 1) { mLayout->moveItem(index, index + 1); saveSettings(); } } void UKUIQuickLaunch::saveSettings() { PluginSettings *settings = mPlugin->settings(); settings->remove("apps"); QList > hashList; int size = mLayout->count(); for (int j = 0; j < size; ++j) { QuickLaunchButton *b = qobject_cast(mLayout->itemAt(j)->widget()); if (!b) continue; // convert QHash to QMap QMap map; QHashIterator it(b->settingsMap()); while (it.hasNext()) { it.next(); map[it.key()] = it.value(); } hashList << map; } settings->setArray("apps", hashList); hashList.removeLast(); } void UKUIQuickLaunch::showPlaceHolder() { if (!mPlaceHolder) { mPlaceHolder = new QLabel(this); mPlaceHolder->setAlignment(Qt::AlignCenter); mPlaceHolder->setObjectName("QuickLaunchPlaceHolder"); mPlaceHolder->setText(tr("Drop application\nicons here")); } mLayout->addWidget(mPlaceHolder); } /* * Implementation of adaptor class FilectrlAdaptor */ FilectrlAdaptor::FilectrlAdaptor(QObject *parent) : QDBusAbstractAdaptor(parent) { // constructor setAutoRelaySignals(true); } FilectrlAdaptor::~FilectrlAdaptor() { // destructor } bool FilectrlAdaptor::AddToTaskbar(const QString &arg) { // handle method call com.kylin.security.controller.filectrl.AddToTaskbar bool out0; QMetaObject::invokeMethod(parent(), "AddToTaskbar", Q_RETURN_ARG(bool, out0), Q_ARG(QString, arg)); emit addtak(3); return out0; } bool FilectrlAdaptor::CheckIfExist(const QString &arg) { // handle method call com.kylin.security.controller.filectrl.CheckIfExist bool out0; QMetaObject::invokeMethod(parent(), "CheckIfExist", Q_RETURN_ARG(bool, out0), Q_ARG(QString, arg)); return out0; } bool FilectrlAdaptor::RemoveFromTaskbar(const QString &arg) { // handle method call com.kylin.security.controller.filectrl.RemoveFromTaskbar bool out0; QMetaObject::invokeMethod(parent(), "RemoveFromTaskbar", Q_RETURN_ARG(bool, out0), Q_ARG(QString, arg)); qDebug()<<"revove set is here"< * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "quicklaunchaction.h" #include #include #include #include #include #include #include #include #include QuickLaunchAction::QuickLaunchAction(const QString & name, const QString & exec, const QString & icon, QWidget * parent) : QAction(name, parent), m_valid(true) { m_type = ActionLegacy; m_settingsMap["name"] = name; m_settingsMap["exec"] = exec; m_settingsMap["icon"] = icon; if (icon == "" || icon.isNull()) setIcon(XdgIcon::defaultApplicationIcon()); else setIcon(QIcon(icon)); setData(exec); connect(this, &QAction::triggered, this, [this] { execAction(); }); } QuickLaunchAction::QuickLaunchAction(const XdgDesktopFile * xdg, QWidget * parent) : QAction(parent), m_valid(true) { m_type = ActionXdg; m_settingsMap["desktop"] = xdg->fileName(); QString title(xdg->localizedValue("Name").toString()); QString gn(xdg->localizedValue("GenericName").toString()); if (!gn.isEmpty()) title += " (" + gn + ")"; setText(title); setIcon(xdg->icon(XdgIcon::defaultApplicationIcon())); setData(xdg->fileName()); connect(this, &QAction::triggered, this, [this] { execAction(); }); // populate the additional actions for (auto const & action : const_cast(xdg->actions())) { QAction * act = new QAction{xdg->actionIcon(action), xdg->actionName(action), this}; act->setData(action); connect(act, &QAction::triggered, [this, act] { execAction(act->data().toString()); }); m_addtitionalActions.push_back(act); } } QuickLaunchAction::QuickLaunchAction(const QString & fileName, QWidget * parent) : QAction(parent), m_valid(true) { m_type = ActionFile; setText(fileName); setData(fileName); m_settingsMap["file"] = fileName; QFileInfo fi(fileName); if (fi.isDir()) { QFileIconProvider ip; setIcon(ip.icon(fi)); } else { QMimeDatabase db; XdgMimeType mi(db.mimeTypeForFile(fi)); setIcon(mi.icon()); } connect(this, &QAction::triggered, this, [this] { execAction(); }); } void QuickLaunchAction::execAction(QString additionalAction) { QString exec(data().toString()); switch (m_type) { case ActionLegacy: QProcess::startDetached(exec); break; case ActionXdg: { XdgDesktopFile xdg; if(xdg.load(exec)) { if (additionalAction.isEmpty()) xdg.startDetached(); else xdg.actionActivate(additionalAction, QStringList{}); } break; } case ActionFile: QDesktopServices::openUrl(QUrl(exec)); break; } } ukui-panel/plugin-quicklaunch/ukuiquicklaunch.h0000644000175000017500000001076513632320722020742 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2012 Razor team * Authors: * Petr Vanek * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIQUICKLAUNCH_H #define UKUIQUICKLAUNCH_H #include "../panel/ukuipanel.h" #include #include #include #include #include "qlayout.h" #include "qlayoutitem.h" #include "qlayoutitem.h" #include "qgridlayout.h" #include #include #include QT_BEGIN_NAMESPACE class QByteArray; template class QList; template class QMap; class QString; class QStringList; class QVariant; QT_END_NAMESPACE class XdgDesktopFile; class QuickLaunchAction; class QDragEnterEvent; class QuickLaunchButton; class QSettings; class QLabel; namespace UKUi { class GridLayout; } /*! \brief Loader for "quick launcher" icons in the panel. \author Petr Vanek */ class UKUIQuickLaunch : public QFrame { Q_OBJECT public: UKUIQuickLaunch(IUKUIPanelPlugin *plugin, QWidget* parent = 0); ~UKUIQuickLaunch(); int indexOfButton(QuickLaunchButton* button) const; int countOfButtons() const; void realign(); //virtual QLayoutItem *takeAt(int index) = 0; void saveSettings(); void showPlaceHolder(); friend class FilectrlAdaptor; private: UKUi::GridLayout *mLayout; IUKUIPanelPlugin *mPlugin; QLabel *mPlaceHolder; void dragEnterEvent(QDragEnterEvent *e); void dropEvent(QDropEvent *e); void paintEvent(QPaintEvent *); QVector mVBtn; QuickLaunchButton* btn; private slots: void addButton(QuickLaunchAction* action); bool checkButton(QuickLaunchAction* action); void checkButton(QString *filename); void removeButton(QString *filename); void removeButton(QuickLaunchAction* action); void switchButtons(QuickLaunchButton *button1, QuickLaunchButton *button2); void buttonDeleted(); void buttonMoveLeft(); void buttonMoveRight(); public slots: bool AddToTaskbar(QString arg); bool RemoveFromTaskbar(QString arg); bool CheckIfExist(QString arg); int GetPanelPosition(QString arg); int GetPanelSize(QString arg); }; class FilectrlAdaptor: public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "com.ukui.panel.desktop") Q_CLASSINFO("D-Bus Introspection", "" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "") public: FilectrlAdaptor(QObject *parent); virtual ~FilectrlAdaptor(); public: // PROPERTIES public Q_SLOTS: // METHODS bool AddToTaskbar(const QString &arg); bool CheckIfExist(const QString &arg); bool RemoveFromTaskbar(const QString &arg); int GetPanelPosition(const QString &arg); int GetPanelSize(const QString &arg); Q_SIGNALS: // SIGNALS signals: void addtak(int); }; #endif ukui-panel/plugin-quicklaunch/ukuiquicklaunchplugin.cpp0000644000175000017500000000326413632320722022510 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2013 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuiquicklaunchplugin.h" #include "ukuiquicklaunch.h" UKUIQuickLaunchPlugin::UKUIQuickLaunchPlugin(const IUKUIPanelPluginStartupInfo &startupInfo): QObject(), IUKUIPanelPlugin(startupInfo), mWidget(new UKUIQuickLaunch(this)) { FilectrlAdaptor *f; f=new FilectrlAdaptor(mWidget); QDBusConnection con=QDBusConnection::sessionBus(); if(!con.registerService("com.ukui.panel.desktop") || !con.registerObject("/",mWidget)) { qDebug()<<"fail"; } } UKUIQuickLaunchPlugin::~UKUIQuickLaunchPlugin() { delete mWidget; } QWidget *UKUIQuickLaunchPlugin::widget() { return mWidget; } void UKUIQuickLaunchPlugin::realign() { mWidget->realign(); } ukui-panel/plugin-quicklaunch/CMakeLists.txt0000644000175000017500000000072213632320722020114 0ustar fengfengset(PLUGIN "quicklaunch") set(HEADERS ukuiquicklaunchplugin.h ukuiquicklaunch.h quicklaunchbutton.h quicklaunchaction.h ../panel/customstyle.h ) set(SOURCES ukuiquicklaunchplugin.cpp ukuiquicklaunch.cpp quicklaunchbutton.cpp quicklaunchaction.cpp ../panel/customstyle.cpp ) set(LIBRARIES Qt5Xdg ) include_directories( ${UKUI_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/../panel" ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel/plugin-quicklaunch/quicklaunchbutton.h0000644000175000017500000000575113640356061021303 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2012 Razor team * Authors: * Petr Vanek * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIQUICKLAUNCHBUTTON_H #define UKUIQUICKLAUNCHBUTTON_H #include "quicklaunchaction.h" #include #include #include "../panel/customstyle.h" #include #include #include "popupmenu.h" class IUKUIPanelPlugin; //class CustomStyle; #include "../panel/ukuicontrolstyle.h" class QuicklaunchMenu:public QMenu { public: QuicklaunchMenu(); ~QuicklaunchMenu(); protected: void contextMenuEvent(QContextMenuEvent*); }; class QuickLaunchButton : public QToolButton { Q_OBJECT public: QuickLaunchButton(QuickLaunchAction * act, IUKUIPanelPlugin * plugin, QWidget* parent = 0); ~QuickLaunchButton(); QHash settingsMap(); QString file_name; signals: void buttonDeleted(); void switchButtons(QuickLaunchButton *from, QuickLaunchButton *to); void movedLeft(); void movedRight(); protected: //! Disable that annoying small arrow when there is a menu void mousePressEvent(QMouseEvent *e); void mouseMoveEvent(QMouseEvent *e); void dragEnterEvent(QDragEnterEvent *e); void dragMoveEvent(QDragMoveEvent * e); void contextMenuEvent(QContextMenuEvent*); void enterEvent(QEvent *); void leaveEvent(QEvent *); private: QuickLaunchAction *mAct; IUKUIPanelPlugin * mPlugin; QAction *mDeleteAct; QAction *mMoveLeftAct; QAction *mMoveRightAct; QuicklaunchMenu *mMenu; QPoint mDragStart; enum QuickLaunchStatus{NORMAL, HOVER, PRESS}; QuickLaunchStatus quicklanuchstatus; CustomStyle toolbuttonstyle; private slots: void this_customContextMenuRequested(const QPoint & pos); public slots: void selfRemove(); }; class ButtonMimeData: public QMimeData { Q_OBJECT public: ButtonMimeData(): QMimeData(), mButton(0) { } QuickLaunchButton *button() const { return mButton; } void setButton(QuickLaunchButton *button) { mButton = button; } private: QuickLaunchButton *mButton; }; #endif ukui-panel/plugin-quicklaunch/quicklaunchbutton.cpp0000644000175000017500000001232213640356061021626 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "quicklaunchbutton.h" #include "ukuiquicklaunch.h" #include "../panel/iukuipanelplugin.h" #include #include #include #include #include #include #include #include #include #define MIMETYPE "x-ukui/quicklaunch-button" QuickLaunchButton::QuickLaunchButton(QuickLaunchAction * act, IUKUIPanelPlugin * plugin, QWidget * parent) : QToolButton(parent), mAct(act), mPlugin(plugin) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setAcceptDrops(true); setAutoRaise(true); quicklanuchstatus = NORMAL; setDefaultAction(mAct); mAct->setParent(this); mMoveLeftAct = new QAction(XdgIcon::fromTheme("go-previous"), tr("move to left"), this); connect(mMoveLeftAct, SIGNAL(triggered()), this, SIGNAL(movedLeft())); mMoveRightAct = new QAction(XdgIcon::fromTheme("go-next"), tr("move to right"), this); connect(mMoveRightAct, SIGNAL(triggered()), this, SIGNAL(movedRight())); mDeleteAct = new QAction(XdgIcon::fromTheme("dialog-close"), tr("delete from quicklaunch"), this); connect(mDeleteAct, SIGNAL(triggered()), this, SLOT(selfRemove())); addAction(mDeleteAct); mMenu = new QuicklaunchMenu(); mMenu->addAction(mAct); mMenu->addActions(mAct->addtitionalActions()); mMenu->addSeparator(); mMenu->addAction(mMoveLeftAct); mMenu->addAction(mMoveRightAct); mMenu->addSeparator(); mMenu->addAction(mDeleteAct); setContextMenuPolicy(Qt::CustomContextMenu); // mMenu.exec(QCursor::pos()); connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(this_customContextMenuRequested(const QPoint&))); //file_name=act->m_settingsMap["name"]; file_name=act->m_settingsMap["desktop"]; this->setStyle(new CustomStyle()); repaint(); } QuickLaunchButton::~QuickLaunchButton() { //m_act->deleteLater(); } QHash QuickLaunchButton::settingsMap() { Q_ASSERT(mAct); return mAct->settingsMap(); } void QuickLaunchButton::this_customContextMenuRequested(const QPoint & pos) { UKUIQuickLaunch *panel = qobject_cast(parent()); mMoveLeftAct->setEnabled( panel && panel->indexOfButton(this) > 0); mMoveRightAct->setEnabled(panel && panel->indexOfButton(this) < panel->countOfButtons() - 1); mPlugin->willShowWindow(mMenu); mMenu->popup(mPlugin->panel()->calculatePopupWindowPos(mapToGlobal({0, 0}), mMenu->sizeHint()).topLeft()); } void QuickLaunchButton::selfRemove() { emit buttonDeleted(); } void QuickLaunchButton::enterEvent(QEvent *) { quicklanuchstatus =HOVER; repaint(); } void QuickLaunchButton::leaveEvent(QEvent *) { quicklanuchstatus=NORMAL; repaint(); } void QuickLaunchButton::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton && e->modifiers() == Qt::ControlModifier) { mDragStart = e->pos(); return; } QToolButton::mousePressEvent(e); } void QuickLaunchButton::mouseMoveEvent(QMouseEvent *e) { if (!(e->buttons() & Qt::LeftButton)) { return; } if ((e->pos() - mDragStart).manhattanLength() < QApplication::startDragDistance()) { return; } if (e->modifiers() != Qt::ControlModifier) { return; } QDrag *drag = new QDrag(this); ButtonMimeData *mimeData = new ButtonMimeData(); mimeData->setButton(this); drag->setMimeData(mimeData); drag->exec(Qt::MoveAction); // Icon was droped outside the panel, remove button if (!drag->target()) { selfRemove(); } } void QuickLaunchButton::dragMoveEvent(QDragMoveEvent * e) { if (e->mimeData()->hasFormat(MIMETYPE)) e->acceptProposedAction(); else e->ignore(); } void QuickLaunchButton::dragEnterEvent(QDragEnterEvent *e) { const ButtonMimeData *mimeData = qobject_cast(e->mimeData()); if (mimeData && mimeData->button()) { emit switchButtons(mimeData->button(), this); } } void QuickLaunchButton::contextMenuEvent(QContextMenuEvent *){ } QuicklaunchMenu::QuicklaunchMenu(){ } QuicklaunchMenu::~QuicklaunchMenu(){ } void QuicklaunchMenu::contextMenuEvent(QContextMenuEvent *) { } ukui-panel/plugin-quicklaunch/ukuiquicklaunchplugin.h0000644000175000017500000000374613632320722022162 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2013 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIQUICKLAUNCHPLUGIN_H #define UKUIQUICKLAUNCHPLUGIN_H #include "../panel/iukuipanelplugin.h" #include class UKUIQuickLaunch; class UKUIQuickLaunchPlugin: public QObject, public IUKUIPanelPlugin { Q_OBJECT public: explicit UKUIQuickLaunchPlugin(const IUKUIPanelPluginStartupInfo &startupInfo); ~UKUIQuickLaunchPlugin(); virtual QWidget *widget(); virtual QString themeId() const { return "QuickLaunch"; } virtual Flags flags() const { return NeedsHandle; } void realign(); bool isSeparate() const { return true; } private: UKUIQuickLaunch *mWidget; }; class UKUIQuickLaunchPluginLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT // Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new UKUIQuickLaunchPlugin(startupInfo); } }; #endif // UKUIQUICKLAUNCHPLUGIN_H ukui-panel/AUTHORS0000644000175000017500000000056313633610704012627 0ustar fengfengUpstream Authors: LXQT team: https://lxqt.org Razor team: http://razor-qt.org kylin team: https://www.ukui.com Copyright: Copyright (c) 2010-2012 Razor team Copyright (c) 2012-2017 iLXQT team Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * License: LGPL-2.1+ The full text of the licenses can be found in the 'COPYING' file. ukui-panel/plugin-spacer/0000755000175000017500000000000013632320722014321 5ustar fengfengukui-panel/plugin-spacer/spacerconfiguration.ui0000644000175000017500000000523213632320722020727 0ustar fengfeng SpacerConfiguration 0 0 289 135 Spacer Settings Space width: 4 2048 8 Space type: Qt::Horizontal QDialogButtonBox::Close fixed false expandable buttons clicked(QAbstractButton*) SpacerConfiguration close() 20 20 20 20 sizeFixedRB toggled(bool) sizeSB setEnabled(bool) 152 21 244 21 ukui-panel/plugin-spacer/spacerconfiguration.h0000644000175000017500000000326013632320722020540 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef SPACERCONFIGURATION_H #define SPACERCONFIGURATION_H #include "../panel/ukuipanelpluginconfigdialog.h" #include "../panel/pluginsettings.h" class QAbstractButton; namespace Ui { class SpacerConfiguration; } class SpacerConfiguration : public UKUIPanelPluginConfigDialog { Q_OBJECT public: explicit SpacerConfiguration(PluginSettings *settings, QWidget *parent = nullptr); ~SpacerConfiguration(); public: static const QStringList msTypes; private: Ui::SpacerConfiguration *ui; private slots: /* Saves settings in conf file. */ void loadSettings(); void sizeChanged(int value); void typeChanged(int index); void widthTypeChanged(bool expandableChecked); }; #endif // SPACERCONFIGURATION_H ukui-panel/plugin-spacer/resources/0000755000175000017500000000000013632320722016333 5ustar fengfengukui-panel/plugin-spacer/resources/spacer.desktop.in0000644000175000017500000000023213632320722021605 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Spacer Comment=Space between widgets Icon=bookmark-new #TRANSLATIONS_DIR=../translations ukui-panel/plugin-spacer/spacer.cpp0000644000175000017500000000724313632320722016310 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "spacer.h" #include "spacerconfiguration.h" #include void SpacerWidget::setType(QString const & type) { if (type != mType) { mType = type; QEvent e{QEvent::ThemeChange}; QApplication::sendEvent(this, &e); } } void SpacerWidget::setOrientation(QString const & orientation) { if (orientation != mOrientation) { mOrientation = orientation; QEvent e{QEvent::ThemeChange}; QApplication::sendEvent(this, &e); } } /************************************************ ************************************************/ Spacer::Spacer(const IUKUIPanelPluginStartupInfo &startupInfo) : QObject() , IUKUIPanelPlugin(startupInfo) , mSize(8) , mExpandable(false) { settingsChanged(); } /************************************************ ************************************************/ void Spacer::settingsChanged() { mSize = settings()->value(QStringLiteral("size"), 8).toInt(); const bool old_expandable = mExpandable; mExpandable = settings()->value(QStringLiteral("expandable"), false).toBool(); mSpacer.setType(settings()->value(QStringLiteral("spaceType"), SpacerConfiguration::msTypes[0]).toString()); setSizes(); if (old_expandable != mExpandable) pluginFlagsChanged(); } /************************************************ ************************************************/ QDialog *Spacer::configureDialog() { return new SpacerConfiguration(settings()); } /************************************************ ************************************************/ void Spacer::setSizes() { if (mExpandable) { mSpacer.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); mSpacer.setMinimumSize({1, 1}); mSpacer.setMaximumSize({QWIDGETSIZE_MAX, QWIDGETSIZE_MAX}); mSpacer.setOrientation(panel()->isHorizontal() ? QStringLiteral("horizontal") : QStringLiteral("vertical")); } else { if (panel()->isHorizontal()) { mSpacer.setOrientation(QStringLiteral("horizontal")); mSpacer.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); mSpacer.setFixedWidth(mSize); mSpacer.setMinimumHeight(0); mSpacer.setMaximumHeight(QWIDGETSIZE_MAX); } else { mSpacer.setOrientation(QStringLiteral("vertical")); mSpacer.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); mSpacer.setFixedHeight(mSize); mSpacer.setMinimumWidth(0); mSpacer.setMaximumWidth(QWIDGETSIZE_MAX); } } } /************************************************ ************************************************/ void Spacer::realign() { setSizes(); } ukui-panel/plugin-spacer/CMakeLists.txt0000644000175000017500000000031113632320722017054 0ustar fengfengset(PLUGIN "spacer") set(HEADERS spacer.h spacerconfiguration.h ) set(SOURCES spacer.cpp spacerconfiguration.cpp ) set(UIS spacerconfiguration.ui ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel/plugin-spacer/spacer.h0000644000175000017500000000501513632320722015750 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef SPACER_H #define SPACER_H #include "../panel/iukuipanelplugin.h" #include class SpacerWidget : public QFrame { Q_OBJECT Q_PROPERTY(QString type READ getType) Q_PROPERTY(QString orientation READ getOrientation) public: const QString& getType() const throw () { return mType; } void setType(QString const & type); const QString& getOrientation() const throw () { return mOrientation; } void setOrientation(QString const & orientation); private: QString mType; QString mOrientation; }; class Spacer : public QObject, public IUKUIPanelPlugin { Q_OBJECT public: Spacer(const IUKUIPanelPluginStartupInfo &startupInfo); virtual QWidget *widget() override { return &mSpacer; } virtual QString themeId() const override { return QStringLiteral("Spacer"); } bool isSeparate() const override { return true; } bool isExpandable() const override { return mExpandable; } virtual IUKUIPanelPlugin::Flags flags() const override { return HaveConfigDialog; } QDialog *configureDialog() override; virtual void realign() override; private slots: virtual void settingsChanged() override; private: void setSizes(); private: SpacerWidget mSpacer; int mSize; bool mExpandable; }; class SpacerPluginLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT // Q_PLUGIN_METADATA(IID "lxqt.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new Spacer(startupInfo);} }; #endif ukui-panel/plugin-spacer/spacerconfiguration.cpp0000644000175000017500000000640713632320722021101 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "spacerconfiguration.h" #include "ui_spacerconfiguration.h" //Note: strings can't actually be translated here (in static initialization time) // the QT_TR_NOOP here is just for qt translate tools to get the strings for translation const QStringList SpacerConfiguration::msTypes = { QStringLiteral(QT_TR_NOOP("lined")) , QStringLiteral(QT_TR_NOOP("dotted")) , QStringLiteral(QT_TR_NOOP("invisible")) }; SpacerConfiguration::SpacerConfiguration(PluginSettings *settings, QWidget *parent) : UKUIPanelPluginConfigDialog(settings, parent), ui(new Ui::SpacerConfiguration) { setAttribute(Qt::WA_DeleteOnClose); setObjectName(QStringLiteral("SpacerConfigurationWindow")); ui->setupUi(this); //Note: translation is needed here in runtime (translator is attached already) for (auto const & type : msTypes) ui->typeCB->addItem(tr(type.toStdString().c_str()), type); loadSettings(); connect(ui->sizeSB, static_cast(&QSpinBox::valueChanged), this, &SpacerConfiguration::sizeChanged); connect(ui->typeCB, static_cast(&QComboBox::currentIndexChanged), this, &SpacerConfiguration::typeChanged); //Note: if there will be more than 2 radio buttons for width/size type, this simple setting logic will break connect(ui->sizeExpandRB, &QAbstractButton::toggled, this, &SpacerConfiguration::widthTypeChanged); } SpacerConfiguration::~SpacerConfiguration() { delete ui; } void SpacerConfiguration::loadSettings() { ui->sizeSB->setValue(settings().value(QStringLiteral("size"), 8).toInt()); ui->typeCB->setCurrentIndex(ui->typeCB->findData(settings().value(QStringLiteral("spaceType"), msTypes[0]).toString())); const bool expandable = settings().value(QStringLiteral("expandable"), false).toBool(); ui->sizeExpandRB->setChecked(expandable); ui->sizeFixedRB->setChecked(!expandable); ui->sizeSB->setDisabled(expandable); } void SpacerConfiguration::sizeChanged(int value) { settings().setValue(QStringLiteral("size"), value); } void SpacerConfiguration::typeChanged(int index) { settings().setValue(QStringLiteral("spaceType"), ui->typeCB->itemData(index, Qt::UserRole)); } void SpacerConfiguration::widthTypeChanged(bool expandableChecked) { settings().setValue(QStringLiteral("expandable"), expandableChecked); } ukui-panel/COPYING0000644000175000017500000005763613632320722012624 0ustar fengfeng GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS ukui-panel/doc/0000755000175000017500000000000013633355350012323 5ustar fengfengukui-panel/doc/studyLink0000644000175000017500000000043413632320722014227 0ustar fengfengQt拖放(1):拖放基本原理(QDrag类) https://blog.csdn.net/hyongilfmmm/article/details/83238239 QT---之Q_D和d指针概念2 https://blog.csdn.net/weixin_39609623/article/details/83152662 Qt中使用Q指针和D指针 https://blog.csdn.net/u013399898/article/details/83930426 ukui-panel/doc/ukui-panel-Requirements-Document.doc0000644000175000017500000003413513632320722021321 0ustar fengfengPK N@ docProps/PKN@^rdocProps/app.xmlQo0ߗ?ޡiLhrf6m5WdQ{MO܃Π ba{ ,>S36R¿ oT-a~m#dX -5[ )nuRWH%gԂ( Q@{'dʯCj|t8MXHbtwV`HQ?ԅ!FjʬSg~½tf?$M+MU}3 &-$m sFm*ww9J3j]yVqh7(yy͂d2˂(-U&Af8FQ0aIs{1nPKN@/>_docProps/core.xml[K0C}U]9(ޅVl$iu ^&'o|/*QZjS"ykyu{SpCjkpQ0)G){C1v| $*km%ah7063B w،F4(fg^ 8$(pzO.HY g^?#wmy_#O?j\8ߎr ̃;%jL~EfnB *w£Kj fw`ƹA2ݺx8cXOfqN~YNE*՗~PKN@h+docProps/custom.xmlMo EM{؎Tt&ΐ@[3wr_Nνl0K5%L4 e%|=:#YEznoسtAI"^B =H$&&u tgl^qZ>iia>`5q+_|2F݊}D ?ڬiیd$QBk'L!0_"VL<ԓIC1o>4MvS2*WrPK N@word/PKN@ > 2hword/styles.xml][sH~ߪOlcO\Q:5v[g[вzʯ݀Où|>& W4oyIx@4\|2ɣ%OYNx_.JY$e[:dbDiXiX켂8HEd.>\."՟ =JFeʳ0NOKkA^\&WJF}S꿍Ipx`H'H @eVLS()-_T4dYr'8ڇhrkh q<p 8q6:!%bړp#w9pwʎܝ#wI?pw)LP (C%( KP,4,AQhXаa 6/pȊoG )L<(+<t|t+Ph4{ꌘisw BTjb O8J ߏ M( F0!dIDƃLbtra-X"oy7[D$o, F\.mh4-X"<4DmF7rxcY\o,+:}ˆ7[D%o,xcI'Xxc\hj[D.yhmq뇸7zvtNUpD V_=~y@>O龍߼0x @*Fm/¸Ճk˵^d\;lNw-o\'ˮ́jEXR0x}ugO3]>4LCf6 Woh 1N\8'd 퐹tDq[W-%6[t'6K;e6_z5|yɓ䞙* ~0+F$|!ۣC#[C2?_1=\Tgn/3xĿ3x7Ňv<."P`7x0қ.Bih[(+W\=6 s`ήC:Y{Ib~ 5?p۬j82PKN@^# word/settings.xmlV[s8~ߙ t :}F$_# f:s|H ہ6LI \Ln'鿋zRYP$L=]7kQЄ4'Qim &/APs*(-Oꪟ+QQ2ƙFeԙQ2L˵2jcJ6C4sm=4pAISkWae0{+AoIv6J/?Sl>]A|1 K=t#]\LSیpQ+ZZw@6v)A=,:xkdh $7IS>, ƣִԬe9iEs$V0SqS=cf }|0#鑷Tߢ xP#HkۺNOWyqQqkN99 \Bwl בhd85mYMY[Oh*1i6+X\,-]1 w]J8 ݫڶ~~'a Dv{f Ukv)x0_ ms,){,>a 7GV ]i}W@bqWgmg՚,p:~٠I|B*L8|a mv?_ '8#rEȌ̎9WWd/:xd1Op={Ekys>%b|~sEc2:e'wikr [*2hoIfL~5'=9:sشfn'ORq}zv4菸w+ѴP$αtSgiВx5bP&hGjE[d1uj0:g`:uXӪ7ƓU;5_>Hڏl;x_~% #Ju<4n@2A$%L> GG(U] N#/B;Kpf)S1W#;PK N@ word/theme/PKN@Ѯ$word/theme/theme1.xmlYMo7X콱d#2">vDJ)-ˈ\݊X@Ѵȡ^z(HhkHS CjEJT>E}3|!WWޏw ,iK%ɐ$ ~˾'$JDY և\A21>GRkkbH\b)NوIõ#ӵR#^bp{c4"C?f;HPC{7L46BLErѦ쨏KߣHHxK_ۺ6s#*Wv]x]A1iRԶ @2S:ŸVq1}Vw;j5@GvQ%Uo5(_Yw-נ _]W*VkP-vn5($/KFk2bt oT+z|j(KM1b\Uk1x H$')!q Q2'a$4h#y64KCjFO 9Ie$E1^߾g~=~/#j%i/y<ڍ&ϟ?Wn l9Wnb3nb; J## }}(rv;D6gE|"^[(쩹0'I螜OL-]sPb3IA=e+͛%8Scb 9l$A>X47%1e"bspaԵ6>+ucjH\QL̀#H|h:BBCL .k$}ĝ:m$d3m6nE(N]I"C"&.wy@t!JjpӤ4/dU)!R$'w6 7Ho8x_TĹgvznQ[sM6rz/ߋ|EM1^a;f w. 10ʫ KQ& 1^ Gs4b(K|5拾?T$&s/B")2q]W"L*kD<4$p|{JVcp>ST5 gQVc /A[C`u-( VI*mP  qLR"Nڼ#!>VEvɓ -}%-.(h6xŸۥ^b4!RJ=k*(UXQ]bC Ƿ4kz ykE} #ؑR}ߗ6T@G@ΨrRWYiī %z*^M  uG.'N:՛J)E rH|lJ19;,*;(»]T;ccxTߩx'HEFY1pxiǻ*QZt I2<_jKh';{;XخYiؽKmr+2mbvQ8*NۑTD;7V@q9mrż3a=BϪDA5@ҎJvI#H5c5͉/脰ҵGw&/WSUiHe8}L]$V Γ'1$"v](qV20WhA@v{El)[ME8Yadڥ(e(,MFuӪ0oiA҄Mm(\_19oCqHǼE񯬭t{` H"ϭc {hf]s?'^{P TW 'uC"jxD(( 3x .ҡ&C. dpp<]r.#lA錑//7nnSfg׵ܑ=B1CFM{ϕ}D+x6e@AG׽JAzZPt!n4;_x2i{{N9H3V&kŕBo~/`~놱02pG+K|Š S?\o=ߗ=dpQĎ7Ah429#dL1j*c\$[ֳ I٤˘ IYt# Hˍ[+;$q{M1#3ڦ0WZX'ell-] k˘\ILamy!XFI\!> +p@ӳhْل!sx;_52X\%mOVf6fVΜ 0x_Ic 1yֵB3?y*m#-d.OU8>2X4fF~g}_[o楣U6A2>`jpUaAX{a-…n'sDQyWGy+HO+f-:}T~I<< NeԾucd'}x 620Z䷦\#7jɸ-0-}XO6޽n-&^@q+s߹cdޘ&(xBC]wġ 3ߐ&'LzPPk禱f }@s,3]6&r7֣lHUk mXH^E (XG!f+uc6gbPŎjNݵ2wyIͯ~SxAT|.C'2<X)G=_+D1fruM3}952Ak,Z(/ _"eC^M0b^{)ֻLX*󑟈<(ť|*qQn4 χJDj7H_OH'h.˫|B17N ZuN+`m%8/ben )ۮBrγ?qƍBSn'8~,+llWkgz8JW9鏅­$y%>Po[6 v:/꺵 n;6;eA0;muĜ@Znwf~<89_fC͎zRqOI Oi>jrN%.nw#Tԣ F)S r^EupM(SbMK C9}x|A1 uRWQTAgig>A40%viXdTxV`Ssr[%b'2+,G8Y$el]'0Ԁo!O4gM4Y7J(rP_mQh^(~D T|$C}F^9 ex?r7/y$ȪEHin*gREmgXeNt{"_$'ܻeEga(6d2'OvpR/0q7gaoWπNcފ wY"!E Ntާ3lWB߷.%lb'N}PK N@ customXml/PKN@>ϕcustomXml/item1.xml 0DnՋ$=xivSѿPśיyÓţݍzR%)G-]\·C<9OPJrn'L0b>!Vp acI8iZ*oQmp7 IkX 3OuPKN@cC{EGcustomXml/itemProps1.xmleQk0r5Fb,N`!^ۀI17t}{9]\ph4!@-L'kXuZՏUgw:3ѡ Byl|imބIM\а!LfC,k =28;7n ⌊ȌٛIqt"ƈYv$'"f{{+j$ReFBSiJu7? uEW}{ PKN@^}word/numbering.xmln0  ]֭F[!P X,Bu$ۏAIƲEO̓QKeJ(SQIT@o(s%iԢ].#`HwvNIbIM`(*%UUФSL.,ߴQZ Xآ'4\2;+O6^]cv3wvz9aT#Q"! h\3≼CZFP4(ike%֓"Z'NgYPKf6Q3( >3N#H89)ɀy[kN G=Oh>F?P^'4*($2xAQ-#Gxg5":ڔJ{iY }J_QEM[ʷM'gponNh>ON-d3.C(i"gddEk,(eM2]o/zEC*ch4/ s4w0S78][fy>(QD9+Խ}qw+JBLh6uex֘"q6+)*O~QogTIy?t4KZ Y(z2BFl.v/7eXg|NDQq&ت<< FsסM8Z.܋ 8g7)kBpQT T0s܏·dle=$7QRfkCȃ5XSF#AD*¡zU:d*SR4 ?5_~?u'oeh| mKVmb+ˇP]P"{ xǡ(+*lh!tssP T5I؝N3`yngClWvBd)I dP;"LNTδZ@"(TSi\ETC=P] C1NʆS'IcxAiYhhê/Ke,(I$ 4(V tgT¶`.MۆW^`c(iQ/^Qļ(QzZb fI:IR@^lo5c(BRrT\i*͞͡'ȥTʝUG=( S'@VT`ܳ3h;l_92qHvJ0Cq<$IMF4&X58Ũ*c}ƾ|M\5IuDb1 #s~ôs>VYHWsEuiX4[ݵܮ5փ/JfﵚfK`̧:nzM7=ptQBc0vʍL٨j+㝔Y0W!/6$\ɈzU]ikANl;tr(Θ:b!i> rfu>JG1ے7Pay,]1<h|Tn,PYkZA@ k9rq6ԵPlVT~ɲB9]:ڍj#1e~1s:8i{!leAAֽ !=޹7Gl7fɛ} PKN@x E1[Content_Types].xmlPK N@e-_rels/PKN@""  -_rels/.relsPK N@ $customXml/PK N@.customXml/_rels/PKN@t?9z( .customXml/_rels/item1.xml.relsPKN@>ϕ $customXml/item1.xmlPKN@cC{EG %customXml/itemProps1.xmlPK N@ docProps/PKN@^r 'docProps/app.xmlPKN@/>_ docProps/core.xmlPKN@h+ docProps/custom.xmlPK N@Oword/PK N@ /word/_rels/PKN@&J  /word/_rels/document.xml.relsPKN@-CrlT s Aword/document.xmlPKN@* H" )word/fontTable.xmlPKN@^} &word/numbering.xmlPKN@^#  word/settings.xmlPKN@ > 2h rword/styles.xmlPK N@ word/theme/PKN@Ѯ$ word/theme/theme1.xmlPKY2ukui-panel/plugin-calendar/0000755000175000017500000000000013643625333014625 5ustar fengfengukui-panel/plugin-calendar/ukuiwebviewdialog.h0000644000175000017500000000333513640356061020524 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include "../panel/iukuipanelplugin.h" namespace Ui { class UkuiWebviewDialog; } enum CalendarShowMode { lunarSunday = 0,//show lunar and first day a week is sunday lunarMonday = 1,//show lunar and first day a week is monday solarSunday = 2,//show solar and first day a week is sunday solarMonday = 3,//show solar and first day a week is monday Unknown = 0xff }; class UkuiWebviewDialog : public QDialog { Q_OBJECT public: explicit UkuiWebviewDialog(QWidget *parent = nullptr); ~UkuiWebviewDialog(); void creatwebview(int _mode); void showinfo(QString string); QWebView *webview(){return mWebView;} Q_SIGNALS: void deactivated(); private: Ui::UkuiWebviewDialog *ui; QWebView *mWebView; QSize mQsize; protected: virtual bool event(QEvent *event); }; #endif // UKUIWEBVIEWDIALOG_H ukui-panel/plugin-calendar/ukuiwebviewdialog.cpp0000644000175000017500000000763013643551442021064 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include UkuiWebviewDialog::UkuiWebviewDialog(QWidget *parent) : QDialog(parent, Qt::Popup), mWebView(NULL), ui(new Ui::UkuiWebviewDialog) { ui->setupUi(this); } UkuiWebviewDialog::~UkuiWebviewDialog() { delete ui; if(mWebView != NULL) { mWebView->deleteLater(); mWebView = NULL; } } void UkuiWebviewDialog::creatwebview(int _mode) { int iViewWidth = 454; int iViewHeight = 704; if(!mWebView) { mWebView = new QWebView(this); } else { //deletePopup(); } if(mWebView != NULL) { QString htmlFilePath = QLatin1String(PACKAGE_DATA_DIR); if (QLocale::system().name() == "zh_CN") { if(_mode == lunarMonday) { //first day a week is monday in lunar mode iViewHeight = 704; htmlFilePath = QLatin1String("file://") + htmlFilePath + QLatin1String("/plugin-calendar/html/ukui-mon.html"); } else if(_mode == solarSunday) { //first day a week is sunday in solar mode iViewHeight = 600; htmlFilePath = QLatin1String("file://") + htmlFilePath + QLatin1String("/plugin-calendar/html/ukui-solar-cn.html"); } else if(_mode == solarMonday) { //first day a week is monday in solar mode iViewHeight = 600; htmlFilePath = QLatin1String("file://") + htmlFilePath + QLatin1String("/plugin-calendar/html/ukui-solar-cn-mon.html"); } else { //first day a week is sunday in lunar mode htmlFilePath = QLatin1String("file://") + htmlFilePath + QLatin1String("/plugin-calendar/html/ukui.html"); } } else { if(_mode == solarSunday) { htmlFilePath = QLatin1String("file://") + htmlFilePath + QLatin1String("/plugin-calendar/html/ukui-solar-en.html"); } else { htmlFilePath = QLatin1String("file://") + htmlFilePath + QLatin1String("/plugin-calendar/html/ukui-solar-en-mon.html"); } iViewHeight = 600; } // htmlFilePath = QLatin1String("file://") + QLatin1String(PACKAGE_DATA_DIR) + QLatin1String("/plugin-calendar/html/ukui-solar-en.html"); qDebug()<<"load html-----------------------------"<setWindowFlags(Qt::FramelessWindowHint); /*set window size*/ mWebView->resize(iViewWidth,iViewHeight); mWebView->settings()->setAttribute(QWebSettings::JavascriptEnabled,true); mWebView->settings()->setAttribute(QWebSettings::WebAttribute::LocalStorageEnabled, true); mWebView->setContextMenuPolicy(Qt::NoContextMenu); mWebView->load(QUrl(htmlFilePath)); } } bool UkuiWebviewDialog::event(QEvent *event) { if (event->type() == QEvent::Close) { Q_EMIT deactivated(); } return QDialog::event(event); } ukui-panel/plugin-calendar/html/0000755000175000017500000000000013643571462015574 5ustar fengfengukui-panel/plugin-calendar/html/ukui-mon.html0000644000175000017500000001520713640356061020224 0ustar fengfeng

12:42:53

2020年1月1日 星期三 腊月初七

2020年3月
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  1. 甲午年【马年】丙子月 庚辰日
宜忌
ukui-panel/plugin-calendar/html/ukui-en.html0000644000175000017500000000426013632320722020026 0ustar fengfeng
Sun Mon Thes Wed Thur Fri Sat
  1. 2015-02-04 星期三
  2. 4
  3. 十一月十四
  4. 甲午年【马年】
  5. 丙子月 庚辰日
ukui-panel/plugin-calendar/html/arm64-en.html0000644000175000017500000000564513633355350020020 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see
  1. 2015-02-04 星期三
  2. 4
  3. 十一月十四
  4. 甲午年【马年】
  5. 丙子月 庚辰日
ukui-panel/plugin-calendar/html/index-en.js0000644000175000017500000004135213633355350017641 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see div_range.year.x_max || x < div_range.year.x_min || y > div_range.year.y_max || y < div_range.year.y_min) { year_div.className = 'hidden_div'; } } if (month_div.className === 'visible_div') { if (x > div_range.month.x_max || x < div_range.month.x_min || y > div_range.month.y_max || y < div_range.month.y_min ) { month_div.className = 'hidden_div'; } } /* if (holiday_div.className === 'visible_div') { if (x > div_range.holiday.x_max || x < div_range.holiday.x_min || y > div_range.holiday.y_max || y < div_range.holiday.y_min ) { holiday_div.className = 'hidden_div'; } }*/ }); for (var index = year_range['low']; index <= year_range['high']; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); // new year implies new month year_list.appendChild(li); if (index === year) { year_selector.value = index; } } for (var index = 1; index <= 12; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); month_list.appendChild(li); if (index === month + 1) { month_selector.value = index; } } var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low']; month_selector.value = month_offset % 12 === 0 ? 1 : month_offset % 12 + 1; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } /* var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); }*/ // var holiday_button = document.getElementById('holiday_button'); // holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear(); month_selector.value = today.getMonth() + 1; highlight_day = today.getDate(); create_page(today.getFullYear(), today.getMonth() + 1); }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if (index < month_stuff['firstDay'] || index >= month_stuff['firstDay'] + month_stuff['monthDays']) { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; // worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; // worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + ''; if (worktime && current_cell.className !== 'day_other_month') { // current_cell.appendChild(worktime); } } } update_right_pane(year, month, highlight_day); month_stuff = null; } function new_month_selected() { if (this.parentNode.id === 'year_list') { year_selector.value = this.innerHTML; document.getElementById('year_div').className = 'hidden_div'; } else if (this.parentNode.id === 'month_list') { month_selector.value = this.innerHTML; document.getElementById('month_div').className = 'hidden_div'; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_selector') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; } else if (this.id === 'month_selector') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; } /* else if (this.id === 'holiday_button') { div = document.getElementById('holiday_div'); div.style.width = '64px'; div.style.height = '100px'; div_range.holiday.x_min = x; div_range.holiday.x_max = x + width; div_range.holiday.y_min = y; div_range.holiday.y_max = y + height; }*/else { return; } if (div.className === 'hidden_div') { div.className = 'visible_div'; } else { div.className = 'hidden_div'; } div.style.left = x + 'px'; div.style.top = y + height + 'px'; } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true); var general_datetime_list = document.getElementById('general_datetime_list'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } general_datetime_list.children[0].innerHTML = month_str + '-' + day_str + '-' + year + ' ' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = ' '; general_datetime_list.children[3].innerHTML = ' '; general_datetime_list.children[4].innerHTML = ' '; update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ /*function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year; month_selector.value = month + 'Month'; highlight_day = day; create_page(year, month); month_stuff = null; }*/ ukui-panel/plugin-calendar/html/ukui-solar-cn-mon.html0000644000175000017500000001002313640356061021727 0ustar fengfeng

12:42:53

2020年1月1日

2020年3月
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ukui-panel/plugin-calendar/html/ukui-pt.html0000644000175000017500000000560213633355350020056 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see
DOM SEG TER QUA QUI SEX SAB
  1. 2015-02-04 星期三
  2. 4
  3. 十一月十四
  4. 甲午年【马年】
  5. 丙子月 庚辰日
ukui-panel/plugin-calendar/html/ukui-ru.html0000644000175000017500000000562313633355350020064 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see
ВС ПН ВТ СР ЧТ ПТ СБ
  1. 2015-02-04 星期三
  2. 4
  3. 十一月十四
  4. 甲午年【马年】
  5. 丙子月 庚辰日
ukui-panel/plugin-calendar/html/index-ru.js0000644000175000017500000004137013633355350017665 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see div_range.year.x_max || x < div_range.year.x_min || y > div_range.year.y_max || y < div_range.year.y_min) { year_div.className = 'hidden_div'; } } if (month_div.className === 'visible_div') { if (x > div_range.month.x_max || x < div_range.month.x_min || y > div_range.month.y_max || y < div_range.month.y_min ) { month_div.className = 'hidden_div'; } } /* if (holiday_div.className === 'visible_div') { if (x > div_range.holiday.x_max || x < div_range.holiday.x_min || y > div_range.holiday.y_max || y < div_range.holiday.y_min ) { holiday_div.className = 'hidden_div'; } }*/ }); for (var index = year_range['low']; index <= year_range['high']; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); // new year implies new month year_list.appendChild(li); if (index === year) { year_selector.value = index; } } for (var index = 1; index <= 12; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); month_list.appendChild(li); if (index === month + 1) { month_selector.value = index; } } var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low']; month_selector.value = month_offset % 12 === 0 ? 1 : month_offset % 12 + 1; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } /* var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); }*/ // var holiday_button = document.getElementById('holiday_button'); // holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear(); month_selector.value = today.getMonth() + 1; highlight_day = today.getDate(); create_page(today.getFullYear(), today.getMonth() + 1); }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if (index < month_stuff['firstDay'] || index >= month_stuff['firstDay'] + month_stuff['monthDays']) { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; // worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; // worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + ''; if (worktime && current_cell.className !== 'day_other_month') { // current_cell.appendChild(worktime); } } } update_right_pane(year, month, highlight_day); month_stuff = null; } function new_month_selected() { if (this.parentNode.id === 'year_list') { year_selector.value = this.innerHTML; document.getElementById('year_div').className = 'hidden_div'; } else if (this.parentNode.id === 'month_list') { month_selector.value = this.innerHTML; document.getElementById('month_div').className = 'hidden_div'; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_selector') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; } else if (this.id === 'month_selector') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; } /* else if (this.id === 'holiday_button') { div = document.getElementById('holiday_div'); div.style.width = '64px'; div.style.height = '100px'; div_range.holiday.x_min = x; div_range.holiday.x_max = x + width; div_range.holiday.y_min = y; div_range.holiday.y_max = y + height; }*/else { return; } if (div.className === 'hidden_div') { div.className = 'visible_div'; } else { div.className = 'hidden_div'; } div.style.left = x + 'px'; div.style.top = y + height + 'px'; } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true); var general_datetime_list = document.getElementById('general_datetime_list'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } general_datetime_list.children[0].innerHTML = month_str + '-' + day_str + '-' + year + ' ' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = ' '; general_datetime_list.children[3].innerHTML = ' '; general_datetime_list.children[4].innerHTML = ' '; //update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ /*function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year; month_selector.value = month + 'Month'; highlight_day = day; create_page(year, month); month_stuff = null; }*/ ukui-panel/plugin-calendar/html/LunarCalendar-en.js0000644000175000017500000006127413633355350021252 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0 ? between : lunarYearDays.yearDays - Math.abs(between); var monthDays = lunarYearDays.monthDays; var tempDays = 0; var month = 0; for(var i=0;i end){ month = i; tempDays = tempDays-monthDays[i]; break; } } return [year,month,end - tempDays + 1]; }; /** * 根据距离正月初一的天数计算农历日期 * @param {Number} year 公历年,月,日 */ function getLunarByBetween(year,month,day){ var yearData = lunarInfo[year-minYear]; var zenMonth = yearData[1]; var zenDay = yearData[2]; var between = getDaysBetweenSolar(year,zenMonth-1,zenDay,year,month,day); if(between==0){ //正月初一 return [year,0,1]; }else{ var lunarYear = between>0 ? year : year-1; return getLunarDateByBetween(lunarYear,between); } }; /** * 两个公历日期之间的天数 */ function getDaysBetweenSolar(year,month,day,year1,month1,day1){ var date = new Date(year,month,day).getTime(); var date1 = new Date(year1,month1,day1).getTime(); return (date1-date) / 86400000; }; /** * 计算农历日期离正月初一有多少天 * @param {Number} year,month,day 农年,月(0-12,有闰月),日 */ function getDaysBetweenZheng(year,month,day){ var lunarYearDays = getLunarYearDays(year); var monthDays = lunarYearDays.monthDays; var days = 0; for(var i=0;i maxYear)return {error:100, msg:errorCode[100]}; return { year : year, month : month, day : day }; }; /** * 将农历转换为公历 * @param {Number} year,month,day 农历年,月(1-13,有闰月),日 */ function lunarToSolar(_year,_month,_day){ var inputDate = formateDate(_year,_month,_day); if(inputDate.error)return inputDate; var year = inputDate.year; var month = inputDate.month; var day = inputDate.day; var between = getDaysBetweenZheng(year,month,day); //离正月初一的天数 var yearData = lunarInfo[year-minYear]; var zenMonth = yearData[1]; var zenDay = yearData[2]; var offDate = new Date(year,zenMonth-1,zenDay).getTime() + between * 86400000; offDate = new Date(offDate); return { year : offDate.getFullYear(), month : offDate.getMonth()+1, day : offDate.getDate() }; }; /** * 将公历转换为农历 * @param {Number} year,month,day 公历年,月,日 */ function solarToLunar(_year,_month,_day){ var inputDate = formateDate(_year,_month,_day,minYear); if(inputDate.error)return inputDate; var year = inputDate.year; var month = inputDate.month; var day = inputDate.day; cacheUtil.setCurrent(year); //立春日期 var term2 = cacheUtil.get('term2') ? cacheUtil.get('term2') : cacheUtil.set('term2',getTerm(year,2)); //二十四节气 var termList = cacheUtil.get('termList') ? cacheUtil.get('termList') : cacheUtil.set('termList',getYearTerm(year)); var firstTerm = getTerm(year,month*2); //某月第一个节气开始日期 var GanZhiYear = (month>1 || month==1 && day>=term2) ? year+1 : year;//干支所在年份 var GanZhiMonth = day>=firstTerm ? month+1 : month; //干支所在月份(以节气为界) var lunarDate = getLunarByBetween(year,month,day); var lunarLeapMonth = getLunarLeapYear(lunarDate[0]); var lunarMonthName = ''; if(lunarLeapMonth>0 && lunarLeapMonth==lunarDate[1]){ lunarMonthName = '闰'+DATA.monthCn[lunarDate[1]-1]+'月'; }else if(lunarLeapMonth>0 && lunarDate[1]>lunarLeapMonth){ lunarMonthName = DATA.monthCn[lunarDate[1]-1]+'月'; }else{ lunarMonthName = DATA.monthCn[lunarDate[1]]+'月'; } //农历节日判断 var lunarFtv = ''; var lunarMonthDays = getLunarYearDays(lunarDate[0]).monthDays; //除夕 if(lunarDate[1] == lunarMonthDays.length-1 && lunarDate[2]==lunarMonthDays[lunarMonthDays.length-1]){ lunarFtv = lunarFestival['d0100']; }else if(lunarLeapMonth>0 && lunarDate[1]>lunarLeapMonth){ lunarFtv = lunarFestival[formateDayD4(lunarDate[1]-1,lunarDate[2])]; }else{ lunarFtv = lunarFestival[formateDayD4(lunarDate[1],lunarDate[2])]; } var res = { zodiac : getYearZodiac(GanZhiYear), GanZhiYear : getLunarYearName(GanZhiYear), GanZhiMonth : getLunarMonthName(year,GanZhiMonth), GanZhiDay : getLunarDayName(year,month,day), //放假安排:0无特殊安排,1工作,2放假 worktime : worktime['y'+year] && worktime['y'+year][formateDayD4(month,day)] ? worktime['y'+year][formateDayD4(month,day)] : 0, term : termList[formateDayD4(month,day)], lunarYear : lunarDate[0], lunarMonth : lunarDate[1]+1, lunarDay : lunarDate[2], lunarMonthName : lunarMonthName, lunarDayName : DATA.dateCn[lunarDate[2]-1], lunarLeapMonth : lunarLeapMonth, solarFestival : solarFestival[formateDayD4(month,day)], lunarFestival : lunarFtv }; return res; }; /** * 获取指定公历月份的农历数据 * return res{Object} * @param {Number} year,month 公历年,月 * @param {Boolean} fill 是否用上下月数据补齐首尾空缺,首例数据从周日开始 */ function calendar(_year,_month,fill){ var inputDate = formateDate(_year,_month); if(inputDate.error)return inputDate; var year = inputDate.year; var month = inputDate.month; var calendarData = solarCalendar(year,month+1,fill); for(var i=0;i 0){ //前补 var preYear = month-1<0 ? year-1 : year; var preMonth = month-1<0 ? 11 : month-1; preMonthDays = getSolarMonthDays(preYear,preMonth); preMonthData = creatLenArr(preYear,preMonth+1,res.firstDay,preMonthDays-res.firstDay+1); res.monthData = preMonthData.concat(res.monthData); } if(7*6 - res.monthData.length!=0){ //后补 var nextYear = month+1>11 ? year+1 : year; var nextMonth = month+1>11 ? 0 : month+1; var fillLen = 7*6 - res.monthData.length; nextMonthData = creatLenArr(nextYear,nextMonth+1,fillLen,1); res.monthData = res.monthData.concat(nextMonthData); } } return res; }; /** * 设置放假安排【对外暴露接口】 * @param {Object} workData */ function setWorktime(workData){ extend(worktime,workData); }; var LunarCalendar = { solarToLunar : solarToLunar, lunarToSolar : lunarToSolar, calendar : calendar, solarCalendar : solarCalendar, setWorktime : setWorktime, getSolarMonthDays : getSolarMonthDays }; if (typeof define === 'function'){ define (function (){ return LunarCalendar; }); }else if(typeof exports === 'object'){ module.exports = LunarCalendar; }else{ window.LunarCalendar = LunarCalendar; }; })(); ukui-panel/plugin-calendar/html/index-solar-en.js0000644000175000017500000010217513643551442020761 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0) { scrollUp_count--; } else { scrollUp_count = 2; } } for(var index = 0; index <16; index++) { // li.children[0].children[index].innerHTML = '
'; //li.children[0].children[index].innerHTML = '
'+ list[index]+ '月'; li.children[0].children[index].innerHTML =''+ list[index] + ''; // li.children[0].children[index].innerHTML = list[index]+ '月'; // document.getElementsByTagName('span').style="float:left;width:250px;background:#6C3;"; if(index >= bind_click_position) { if(scrollUp_count%3 ===2) { if(bind_click_count < 8) { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; } continue; } if(bind_click_count < 12) // max bind _count of month click is no more than 12 { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; } } else { li.children[0].children[index].style.color = "#FFFFFF33"; } } } function update_year_month_ui() { var li = document.getElementById('year_div'); for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var curretYear = year + index; li.children[0].children[index].innerHTML= ''+curretYear +'' ; //li.children[0].children[index].innerHTML= '
'+curretYear+ '年'; // if(index === 0) // { // li.children[0].children[index].style.backgroundColor = "#2b87a8"; // } li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // year_list.appendChild(li); // if (index === year) { // year_selector.value = index + '年'; // } } li = document.getElementById('month_div'); for (var index = 0; index < 16; index++) { li.children[0].children[index].removeEventListener('click', new_month_selected); li.children[0].children[index].style.color = "#FFFFFFFF"; if(index >=12) { var newIndex = index -12 + 1; li.children[0].children[index].style.color = "#FFFFFF33"; //li.children[0].children[index].innerHTML = '
' + new_index + '月'; li.children[0].children[index].innerHTML= ''+newIndex +'' ; //li.children[0].children[index].innerHTML = "1月"; } else { var newIndex = index + 1; //li.children[0].children[index].innerHTML ='
' + newIndex+ '月'; li.children[0].children[index].innerHTML =''+ newIndex + '' ; } if(index < 12) { li.children[0].children[index].addEventListener('click', new_month_selected); } // month_list.appendChild(li); if (index === month + 1) { month_selector.value = index; } } } function updateUi() { year_selector.value = year; update_year_month_ui(); // var li = document.getElementById('year_div'); // for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML= year + index + '年'; // li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // // year_list.appendChild(li); // // if (index === year) { // // year_selector.value = index + '年'; // // } // } // li = document.getElementById('month_div'); // for (var index = 0; index < 16; index++) { // if(index >=12) // { // var new_index = index -12; // li.children[0].children[index].innerHTML = new_index +1+ '月'; // } // else // { // li.children[0].children[index].innerHTML = index +1+ '月'; // } // li.children[0].children[index].addEventListener('click', new_month_selected); // // month_list.appendChild(li); // if (index === month + 1) { // month_selector.value = index + '月'; // } // } } function scroll_div(event) { var e = event||window.event; if(e.wheelDelta > 0) { if(this.id === 'year_div') { year = year - 4; } else if(this.id === 'month_div') { scrollUp_count++; update_month_ui(0); return; } } else { if(this.id === 'year_div') { year = year + 4; } else if(this.id === 'month_div') { scrollDown_count++; update_month_ui(1); return; } } updateUi(); } function update_yiji_area() { "use strict"; var year = parseInt(year_selector.value, 10); var month = parseInt(month_selector.value, 10); var hl_table = document.getElementById('hl_table'); var current_row; var current_cell; if (year !== parseInt(hl_script.id, 10)) { load_hl_script(year); return; } if (typeof HuangLi['y' + year] === 'undefined') { for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if (row === 1) { current_cell.innerHTML = ''; } else { current_cell.innerHTML = ''; } } } } var day = highlight_day; var month_str = month.toString(); var day_str = day.toString(); if (month <= 9) { month_str = '0' + month; } if (day <= 9) { day_str = '0' + day; } var yi_str = HuangLi['y' + year]['d' + month_str + day_str]['y']; var ji_str = HuangLi['y' + year]['d' + month_str + day_str]['j']; var hl_yi_data = yi_str.split('.'); var hl_ji_data = ji_str.split('.'); for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if(0 == row ) { if(hl_yi_data[column-1]) { current_cell.innerHTML = hl_yi_data[column-1]; } else { current_cell.innerHTML = ''; } } else { if(hl_ji_data[column-1]) { current_cell.innerHTML = hl_ji_data[column-1]; } else { current_cell.innerHTML =''; } } } } } function load_hl_script(year) { "use strict"; if (hl_script) { document.body.removeChild(hl_script); hl_script = null; } hl_script = document.createElement("SCRIPT"); hl_script.type = "text/javascript"; hl_script.src = "hl/hl" + year + '.js'; hl_script.id = year; hl_script.onload = function() { update_yiji_area(); }; document.body.appendChild(hl_script); } window.onload = function () { "use strict"; load_hl_script(today.getFullYear()); // var year_list = document.getElementById('year_list'); // var month_list = document.getElementById('month_list'); year = today.getFullYear(); month = today.getMonth(); var real_month = month + 1; selected_date_div = document.getElementById('selected_date_div'); year_selector = document.createElement('year_selector'); month_selector = document.createElement('month_selector'); year_selector.value = year; month_selector.value = real_month; selected_date_div.innerHTML = year_selector.value +'.'+month_selector.value; // year_selector = document.getElementById('year_selector'); // // year_selector.addEventListener('click', popup_div); // month_selector = document.getElementById('month_selector'); // month_selector.addEventListener('click', popup_div); //end // alert("begin"); year_button = document.getElementById('year_button'); year_button.addEventListener('click', popup_div); // alert("end"); month_button= document.getElementById('month_button'); month_button.addEventListener('click', popup_div); document.getElementById('year_div').addEventListener('mousewheel',scroll_div); document.getElementById('month_div').addEventListener('mousewheel',scroll_div); document.addEventListener('click', function(event) { }); updateUi(); var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); //page the year ui if(document.getElementById('year_div').className ==='visible_div') { var li = document.getElementById('year_div'); if(this.id === 'go_prev_month') { year = year -16; year_selector.value = year; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
' + curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else if(this.id === 'go_next_month') { year = year + 16; year_selector.value = year; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
'+ curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } return; } else if(document.getElementById('month_div').className ==='visible_div')//page the month ui { if(this.id === 'go_prev_month') { year --; year_selector.value = year; selected_date_div.innerHTML = year_selector.value + '.' +month_selector.value; } else if(this.id === 'go_next_month') { year++; year_selector.value = year; selected_date_div.innerHTML = year_selector.value + '.' + month_selector.value; } return; } // var year = parseInt(year_selector.value); // var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low']; month_selector.value = month_offset % 12 === 0 ? 1 : month_offset % 12 + 1; selected_date_div.innerHTML = year_selector.value + '.' +month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); } //var holiday_button = document.getElementById('holiday_button'); //holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear(); month_selector.value = today.getMonth() + 1; selected_date_div.innerHTML = year_selector.value + '.' + month_selector.value; highlight_day = today.getDate(); convertToNormal(); year = today.getFullYear(); month = today.getMonth(); create_page(today.getFullYear(), today.getMonth() + 1); update_year_month_ui(); var header_id=document.getElementById("header"); var header_color=header_id.style.background; var x=document.getElementsByClassName("day_today"); var i; if (header_color == "rgb(0, 0, 0)"){ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = "#3593b5"; } } else{ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = header_color; } } }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true,0); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if ((index < (month_stuff['firstDay'] -1) && month_stuff['firstDay'] != 0)//每周从周一开始,当月第一天不是星期天,上个月的日期 ||(index < 6 && month_stuff['firstDay'] === 0)//第一天是星期天 || (month_stuff['firstDay']===0 && index >= (month_stuff['monthDays'] + 6))//第一天是星期天下月的日期 ||( month_stuff['firstDay'] != 0 && index >= month_stuff['firstDay'] + month_stuff['monthDays']-1)) //第一天不是星期天下月日期 { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; worktime.innerHTML = ' '; } else if (month_stuff['monthData'][index]['worktime'] === 1) { worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; worktime.innerHTML = ' '; } else { } /*myworktime.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + lunar_day + '';*/ // if (worktime && current_cell.className !== 'day_other_month') { // //current_cell.appendChild(worktime); // //
// // document.getElementById('aa').innerHTML = worktime.innerHTML; // current_cell.innerHTML = worktime.innerHTML+ // // '
'+ // ' ' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // // current_cell.innerHTML = '123' // // +'
' + '456'+ // // '
' +'789'; // } // else // { // current_cell.innerHTML = '' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' } } update_right_pane(year, month, highlight_day); month_stuff = null; if (header_color == "rgb(0, 0, 0)"){ var day_this_month_len=document.getElementsByClassName('day_this_month').length; for (var i=0; i",""); year_selector.value = str.replace("",""); document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = ""; } else if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; } selected_date_div.innerHTML = year_selector.value + '.' + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_button') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else if (this.id === 'month_button') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else { return; } // if (div.className === 'hidden_div') { // div.className = 'visible_div'; // calendar.style.display = "none"; // } else { // div.className = 'hidden_div'; // calendar.style.display = ""; // } div.style.left = x + 'px'; div.style.top = y + height + 'px'; update_year_month_ui(); //updateUi(); } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true, 0); var general_datetime_list = document.getElementById('general_datetime_list'); var datetime_container = document.getElementById('datetime_container'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; console.log(highlight_index); var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } if(NeedChangeCurrentTime) { datetime_container.children[1].innerHTML = year + '-' + month_str + '-' + day_str + ' ' + weekday /* + ' '+lunar_month_name + lunar_day_name*/; NeedChangeCurrentTime = 0; } /* general_datetime_list.children[0].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = lunar_month_name + lunar_day_name;*/ //general_datetime_list.children[0].innerHTML = ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; // general_datetime_list.children[1].innerHTML = ganzhi_month + '月 ' + ganzhi_day + '日'; updateTime(); update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false, 0); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false, 0); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year; month_selector.value = month; highlight_day = day; create_page(year, month); month_stuff = null; } ukui-panel/plugin-calendar/html/hl/0000755000175000017500000000000013633355350016172 5ustar fengfengukui-panel/plugin-calendar/html/hl/hl2016.js0000644000175000017500000031526613633355350017461 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0) { scrollUp_count--; } else { scrollUp_count = 2; } } for(var index = 0; index <16; index++) { // li.children[0].children[index].innerHTML = '
'; //li.children[0].children[index].innerHTML = '
'+ list[index]+ '月'; li.children[0].children[index].innerHTML =''+ list[index]+ '月' + ''; // li.children[0].children[index].innerHTML = list[index]+ '月'; // document.getElementsByTagName('span').style="float:left;width:250px;background:#6C3;"; if(index >= bind_click_position) { if(scrollUp_count%3 ===2) { if(bind_click_count < 8) { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; } continue; } if(bind_click_count < 12) // max bind _count of month click is no more than 12 { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; } } else { li.children[0].children[index].style.color = "#FFFFFF33"; } } } function update_year_month_ui() { var li = document.getElementById('year_div'); for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var curretYear = year + index; li.children[0].children[index].innerHTML= ''+curretYear+ '年' +'' ; //li.children[0].children[index].innerHTML= '
'+curretYear+ '年'; // if(index === 0) // { // li.children[0].children[index].style.backgroundColor = "#2b87a8"; // } li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // year_list.appendChild(li); // if (index === year) { // year_selector.value = index + '年'; // } } li = document.getElementById('month_div'); for (var index = 0; index < 16; index++) { li.children[0].children[index].removeEventListener('click', new_month_selected); li.children[0].children[index].style.color = "#FFFFFFFF"; if(index >=12) { var newIndex = index -12 + 1; li.children[0].children[index].style.color = "#FFFFFF33"; //li.children[0].children[index].innerHTML = '
' + new_index + '月'; li.children[0].children[index].innerHTML= ''+newIndex + '月' +'' ; //li.children[0].children[index].innerHTML = "1月"; } else { var newIndex = index + 1; //li.children[0].children[index].innerHTML ='
' + newIndex+ '月'; li.children[0].children[index].innerHTML =''+ newIndex+ '月' + '' ; } if(index < 12) { li.children[0].children[index].addEventListener('click', new_month_selected); } // month_list.appendChild(li); if (index === month + 1) { month_selector.value = index + '月'; } } } function updateUi() { year_selector.value = year + '年'; update_year_month_ui(); // var li = document.getElementById('year_div'); // for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML= year + index + '年'; // li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // // year_list.appendChild(li); // // if (index === year) { // // year_selector.value = index + '年'; // // } // } // li = document.getElementById('month_div'); // for (var index = 0; index < 16; index++) { // if(index >=12) // { // var new_index = index -12; // li.children[0].children[index].innerHTML = new_index +1+ '月'; // } // else // { // li.children[0].children[index].innerHTML = index +1+ '月'; // } // li.children[0].children[index].addEventListener('click', new_month_selected); // // month_list.appendChild(li); // if (index === month + 1) { // month_selector.value = index + '月'; // } // } } function scroll_div(event) { var e = event||window.event; if(e.wheelDelta > 0) { if(this.id === 'year_div') { year = year - 4; } else if(this.id === 'month_div') { scrollUp_count++; update_month_ui(0); return; } } else { if(this.id === 'year_div') { year = year + 4; } else if(this.id === 'month_div') { scrollDown_count++; update_month_ui(1); return; } } updateUi(); } function update_yiji_area() { "use strict"; var year = parseInt(year_selector.value, 10); var month = parseInt(month_selector.value, 10); var hl_table = document.getElementById('hl_table'); var current_row; var current_cell; if (year !== parseInt(hl_script.id, 10)) { load_hl_script(year); return; } if (typeof HuangLi['y' + year] === 'undefined') { for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if (row === 1) { current_cell.innerHTML = '无数据'; } else { current_cell.innerHTML = ''; } } } } var day = highlight_day; var month_str = month.toString(); var day_str = day.toString(); if (month <= 9) { month_str = '0' + month; } if (day <= 9) { day_str = '0' + day; } var yi_str = HuangLi['y' + year]['d' + month_str + day_str]['y']; var ji_str = HuangLi['y' + year]['d' + month_str + day_str]['j']; var hl_yi_data = yi_str.split('.'); var hl_ji_data = ji_str.split('.'); for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if(0 == row ) { if(hl_yi_data[column-1]) { current_cell.innerHTML = hl_yi_data[column-1]; } else { current_cell.innerHTML = ''; } } else { if(hl_ji_data[column-1]) { current_cell.innerHTML = hl_ji_data[column-1]; } else { current_cell.innerHTML =''; } } } } } function load_hl_script(year) { "use strict"; if (hl_script) { document.body.removeChild(hl_script); hl_script = null; } hl_script = document.createElement("SCRIPT"); hl_script.type = "text/javascript"; hl_script.src = "hl/hl" + year + '.js'; hl_script.id = year; hl_script.onload = function() { update_yiji_area(); }; document.body.appendChild(hl_script); } window.onload = function () { "use strict"; load_hl_script(today.getFullYear()); // var year_list = document.getElementById('year_list'); // var month_list = document.getElementById('month_list'); year = today.getFullYear(); month = today.getMonth(); var real_month = month + 1; selected_date_div = document.getElementById('selected_date_div'); year_selector = document.createElement('year_selector'); month_selector = document.createElement('month_selector'); year_selector.value = year + '年'; month_selector.value = real_month +'月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; // year_selector = document.getElementById('year_selector'); // // year_selector.addEventListener('click', popup_div); // month_selector = document.getElementById('month_selector'); // month_selector.addEventListener('click', popup_div); //end // alert("begin"); year_button = document.getElementById('year_button'); year_button.addEventListener('click', popup_div); // alert("end"); month_button= document.getElementById('month_button'); month_button.addEventListener('click', popup_div); document.getElementById('year_div').addEventListener('mousewheel',scroll_div); document.getElementById('month_div').addEventListener('mousewheel',scroll_div); document.addEventListener('click', function(event) { }); updateUi(); var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); //page the year ui if(document.getElementById('year_div').className ==='visible_div') { var li = document.getElementById('year_div'); if(this.id === 'go_prev_month') { year = year -16; year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
' + curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '月' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else if(this.id === 'go_next_month') { year = year + 16; year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
'+ curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '月' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } return; } else if(document.getElementById('month_div').className ==='visible_div')//page the month ui { if(this.id === 'go_prev_month') { year --; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } else if(this.id === 'go_next_month') { year++; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } return; } // var year = parseInt(year_selector.value); // var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low'] + '年'; month_selector.value = month_offset % 12 === 0 ? 1 +'月': month_offset % 12 + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); } //var holiday_button = document.getElementById('holiday_button'); //holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear() + '年'; month_selector.value = today.getMonth() + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; highlight_day = today.getDate(); convertToNormal(); year = today.getFullYear(); month = today.getMonth(); create_page(today.getFullYear(), today.getMonth() + 1); update_year_month_ui(); var header_id=document.getElementById("header"); var header_color=header_id.style.background; var x=document.getElementsByClassName("day_today"); var i; if (header_color == "rgb(0, 0, 0)"){ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = "#3593b5"; } } else{ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = header_color; } } }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true,0); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if (index < month_stuff['firstDay'] || index >= month_stuff['firstDay'] + month_stuff['monthDays']) { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; worktime.innerHTML = ' '; } else if (month_stuff['monthData'][index]['worktime'] === 1) { worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; worktime.innerHTML = ' '; } else { } /*myworktime.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + lunar_day + '';*/ // if (worktime && current_cell.className !== 'day_other_month') { // //current_cell.appendChild(worktime); // //
// // document.getElementById('aa').innerHTML = worktime.innerHTML; // current_cell.innerHTML = worktime.innerHTML+ // // '
'+ // ' ' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // // current_cell.innerHTML = '123' // // +'
' + '456'+ // // '
' +'789'; // } // else // { // current_cell.innerHTML = '' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' } } update_right_pane(year, month, highlight_day); month_stuff = null; if (header_color == "rgb(0, 0, 0)"){ var day_this_month_len=document.getElementsByClassName('day_this_month').length; for (var i=0; i",""); year_selector.value = str.replace("",""); document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = ""; } else if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; } selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_button') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else if (this.id === 'month_button') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else { return; } // if (div.className === 'hidden_div') { // div.className = 'visible_div'; // calendar.style.display = "none"; // } else { // div.className = 'hidden_div'; // calendar.style.display = ""; // } div.style.left = x + 'px'; div.style.top = y + height + 'px'; update_year_month_ui(); //updateUi(); } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true, 0); var general_datetime_list = document.getElementById('general_datetime_list'); var datetime_container = document.getElementById('datetime_container'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } if(NeedChangeCurrentTime) { datetime_container.children[1].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday /* + ' '+lunar_month_name + lunar_day_name*/; NeedChangeCurrentTime = 0; } /* general_datetime_list.children[0].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = lunar_month_name + lunar_day_name;*/ //general_datetime_list.children[0].innerHTML = ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; // general_datetime_list.children[1].innerHTML = ganzhi_month + '月 ' + ganzhi_day + '日'; updateTime(); update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false, 0); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false, 0); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year + '年'; month_selector.value = month + '月'; highlight_day = day; create_page(year, month); month_stuff = null; } ukui-panel/plugin-calendar/html/arm64.css0000644000175000017500000001210513633355350017231 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see

12:42:53

2020-01-01

2020.3
Sun Mon Tue Wed Thur Fri Sat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ukui-panel/plugin-calendar/html/index-pt.js0000644000175000017500000004136113633355350017662 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see div_range.year.x_max || x < div_range.year.x_min || y > div_range.year.y_max || y < div_range.year.y_min) { year_div.className = 'hidden_div'; } } if (month_div.className === 'visible_div') { if (x > div_range.month.x_max || x < div_range.month.x_min || y > div_range.month.y_max || y < div_range.month.y_min ) { month_div.className = 'hidden_div'; } } /* if (holiday_div.className === 'visible_div') { if (x > div_range.holiday.x_max || x < div_range.holiday.x_min || y > div_range.holiday.y_max || y < div_range.holiday.y_min ) { holiday_div.className = 'hidden_div'; } }*/ }); for (var index = year_range['low']; index <= year_range['high']; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); // new year implies new month year_list.appendChild(li); if (index === year) { year_selector.value = index; } } for (var index = 1; index <= 12; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); month_list.appendChild(li); if (index === month + 1) { month_selector.value = index; } } var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low']; month_selector.value = month_offset % 12 === 0 ? 1 : month_offset % 12 + 1; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } /* var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); }*/ // var holiday_button = document.getElementById('holiday_button'); // holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear(); month_selector.value = today.getMonth() + 1; highlight_day = today.getDate(); create_page(today.getFullYear(), today.getMonth() + 1); }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if (index < month_stuff['firstDay'] || index >= month_stuff['firstDay'] + month_stuff['monthDays']) { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; // worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; // worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + ''; if (worktime && current_cell.className !== 'day_other_month') { // current_cell.appendChild(worktime); } } } update_right_pane(year, month, highlight_day); month_stuff = null; } function new_month_selected() { if (this.parentNode.id === 'year_list') { year_selector.value = this.innerHTML; document.getElementById('year_div').className = 'hidden_div'; } else if (this.parentNode.id === 'month_list') { month_selector.value = this.innerHTML; document.getElementById('month_div').className = 'hidden_div'; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_selector') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; } else if (this.id === 'month_selector') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; } /* else if (this.id === 'holiday_button') { div = document.getElementById('holiday_div'); div.style.width = '64px'; div.style.height = '100px'; div_range.holiday.x_min = x; div_range.holiday.x_max = x + width; div_range.holiday.y_min = y; div_range.holiday.y_max = y + height; }*/else { return; } if (div.className === 'hidden_div') { div.className = 'visible_div'; } else { div.className = 'hidden_div'; } div.style.left = x + 'px'; div.style.top = y + height + 'px'; } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true); var general_datetime_list = document.getElementById('general_datetime_list'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } general_datetime_list.children[0].innerHTML = month_str + '-' + day_str + '-' + year + ' ' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = ' '; general_datetime_list.children[3].innerHTML = ' '; general_datetime_list.children[4].innerHTML = ' '; //update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ /*function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year; month_selector.value = month + 'Month'; highlight_day = day; create_page(year, month); month_stuff = null; }*/ ukui-panel/plugin-calendar/html/index.js0000644000175000017500000011702113643571462017243 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0) { scrollUp_count--; } else { scrollUp_count = 2; } } for(var index = 0; index <16; index++) { // li.children[0].children[index].innerHTML = '
'; //li.children[0].children[index].innerHTML = '
'+ list[index]+ '月'; li.children[0].children[index].innerHTML =''+ list[index]+ '月' + ''; // li.children[0].children[index].innerHTML = list[index]+ '月'; // document.getElementsByTagName('span').style="float:left;width:250px;background:#6C3;"; if(index >= bind_click_position) { if(scrollUp_count%3 ===2) { if(bind_click_count < 8) { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; } continue; } if(bind_click_count < 12) // max bind _count of month click is no more than 12 { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; } } else { li.children[0].children[index].style.color = "#FFFFFF33"; } } } function update_year_month_ui() { var li = document.getElementById('year_div'); for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var curretYear = year + index; li.children[0].children[index].innerHTML= ''+curretYear+ '年' +'' ; //li.children[0].children[index].innerHTML= '
'+curretYear+ '年'; // if(index === 0) // { // li.children[0].children[index].style.backgroundColor = "#2b87a8"; // } li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // year_list.appendChild(li); // if (index === year) { // year_selector.value = index + '年'; // } } li = document.getElementById('month_div'); for (var index = 0; index < 16; index++) { li.children[0].children[index].removeEventListener('click', new_month_selected); li.children[0].children[index].style.color = "#FFFFFFFF"; if(index >=12) { var newIndex = index -12 + 1; li.children[0].children[index].style.color = "#FFFFFF33"; //li.children[0].children[index].innerHTML = '
' + new_index + '月'; li.children[0].children[index].innerHTML= ''+newIndex + '月' +'' ; //li.children[0].children[index].innerHTML = "1月"; } else { var newIndex = index + 1; //li.children[0].children[index].innerHTML ='
' + newIndex+ '月'; li.children[0].children[index].innerHTML =''+ newIndex+ '月' + '' ; } if(index < 12) { li.children[0].children[index].addEventListener('click', new_month_selected); } // month_list.appendChild(li); if (index === month + 1) { month_selector.value = index + '月'; } } } function updateUi() { year_selector.value = year + '年'; update_year_month_ui(); // var li = document.getElementById('year_div'); // for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML= year + index + '年'; // li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // // year_list.appendChild(li); // // if (index === year) { // // year_selector.value = index + '年'; // // } // } // li = document.getElementById('month_div'); // for (var index = 0; index < 16; index++) { // if(index >=12) // { // var new_index = index -12; // li.children[0].children[index].innerHTML = new_index +1+ '月'; // } // else // { // li.children[0].children[index].innerHTML = index +1+ '月'; // } // li.children[0].children[index].addEventListener('click', new_month_selected); // // month_list.appendChild(li); // if (index === month + 1) { // month_selector.value = index + '月'; // } // } } function scroll_div(event) { var e = event||window.event; if(e.wheelDelta > 0) { if(this.id === 'year_div') { year = year - 4; } else if(this.id === 'month_div') { scrollUp_count++; update_month_ui(0); return; } } else { if(this.id === 'year_div') { year = year + 4; } else if(this.id === 'month_div') { scrollDown_count++; update_month_ui(1); return; } } updateUi(); } function update_yiji_area() { "use strict"; var year = parseInt(year_selector.value, 10); var month = parseInt(month_selector.value, 10); var hl_table = document.getElementById('hl_table'); var current_row; var current_cell; if (year !== parseInt(hl_script.id, 10)) { load_hl_script(year); return; } if (typeof HuangLi['y' + year] === 'undefined') { for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if (row === 1) { current_cell.innerHTML = '无数据'; } else { current_cell.innerHTML = ''; } } } } var day = highlight_day; var month_str = month.toString(); var day_str = day.toString(); if (month <= 9) { month_str = '0' + month; } if (day <= 9) { day_str = '0' + day; } var yi_str = HuangLi['y' + year]['d' + month_str + day_str]['y']; var ji_str = HuangLi['y' + year]['d' + month_str + day_str]['j']; var hl_yi_data = yi_str.split('.'); var hl_ji_data = ji_str.split('.'); for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if(0 == row ) { if(hl_yi_data[column-1]) { current_cell.innerHTML = hl_yi_data[column-1]; } else { current_cell.innerHTML = ''; } } else { if(hl_ji_data[column-1]) { current_cell.innerHTML = hl_ji_data[column-1]; } else { current_cell.innerHTML =''; } } } } } function load_hl_script(year) { "use strict"; if (hl_script) { document.body.removeChild(hl_script); hl_script = null; } hl_script = document.createElement("SCRIPT"); hl_script.type = "text/javascript"; hl_script.src = "hl/hl" + year + '.js'; hl_script.id = year; hl_script.onload = function() { update_yiji_area(); }; document.body.appendChild(hl_script); } window.onload = function () { var checkbox = document.getElementById('advice_checkbox'); if (localStorage.getItem('hl_table') == "display"){ checkbox.setAttribute("checked", true); hl_table.setAttribute("style", "visibility:display"); //var zodiac_icon = document.getElementById('zodiac_icon'); //zodiac_icon.setAttribute("style", "display:none"); } checkbox.onclick = function(){ console.log("checkbox triggerd"); if(this.checked){ var hl_table = document.getElementById('hl_table'); hl_table.setAttribute("style", "visibility:display"); //var zodiac_icon = document.getElementById('zodiac_icon'); //zodiac_icon.setAttribute("style", "display:none"); localStorage.setItem('hl_table', "display"); } else{ var hl_table = document.getElementById('hl_table'); hl_table.setAttribute("style", "visibility:hidden"); // var zodiac_icon = document.getElementById('zodiac_icon'); // zodiac_icon.setAttribute("style", "display:block"); //zodiac_icon.setAttribute("style", "padding-top: 33px"); localStorage.setItem('hl_table', "hidden"); } } "use strict"; load_hl_script(today.getFullYear()); // var year_list = document.getElementById('year_list'); // var month_list = document.getElementById('month_list'); year = today.getFullYear(); month = today.getMonth(); var real_month = month + 1; //begin before modify year button selected_date_div = document.getElementById('selected_date_div'); year_selector = document.createElement('year_selector'); month_selector = document.createElement('month_selector'); year_selector.value = year + '年'; month_selector.value = real_month +'月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; // year_selector = document.getElementById('year_selector'); // // year_selector.addEventListener('click', popup_div); // month_selector = document.getElementById('month_selector'); // month_selector.addEventListener('click', popup_div); //end // alert("begin"); year_button = document.getElementById('year_button'); year_button.addEventListener('click', popup_div); // alert("end"); month_button= document.getElementById('month_button'); month_button.addEventListener('click', popup_div); document.getElementById('year_div').addEventListener('mousewheel',scroll_div); document.getElementById('month_div').addEventListener('mousewheel',scroll_div); // year_button = document.getElementById('year_button'); // year_button.addEventListener('click', popup_div); // month_button = document.getElementById('month_button'); // month_button.addEventListener('click', popup_div); // document.addEventListener('mousewheel', function(event) // { // //alert("sroll??"); // }) document.addEventListener('click', function(event) { // var year_div = document.getElementById('year_div'); // var month_div = document.getElementById('month_div'); // var holiday_div = document.getElementById('holiday_div'); // var x = event.clientX; // var y = event.clientY; // if (year_div.className === 'visible_div') { // if (x > div_range.year.x_max || x < div_range.year.x_min || // y > div_range.year.y_max || y < div_range.year.y_min) { // year_div.className = 'hidden_div'; // } // } // if (month_div.className === 'visible_div') { // if (x > div_range.month.x_max || x < div_range.month.x_min || // y > div_range.month.y_max || y < div_range.month.y_min ) { // month_div.className = 'hidden_div'; // } // } // if (holiday_div.className === 'visible_div') { // if (x > div_range.holiday.x_max || x < div_range.holiday.x_min || // y > div_range.holiday.y_max || y < div_range.holiday.y_min ) { // holiday_div.className = 'hidden_div'; // } // } // var header_id=document.getElementById("header"); // var header_color=header_id.style.background; // var x=document.getElementsByClassName("day_highlight"); // if (header_color == "rgb(0, 0, 0)"){ // for (i = 0; i < x.length; i++) { // x[i].style.backgroundColor = "#2b87a8"; // } // var day_highlight_len=document.getElementsByClassName('day_highlight').length; // for (var i=0; i'; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else if(this.id === 'go_next_month') { year = year + 16; year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
'+ curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '月' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } return; } else if(document.getElementById('month_div').className ==='visible_div')//page the month ui { if(this.id === 'go_prev_month') { year --; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } else if(this.id === 'go_next_month') { year++; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } return; } // var year = parseInt(year_selector.value); // var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low'] + '年'; month_selector.value = month_offset % 12 === 0 ? 1 +'月': month_offset % 12 + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; NeedUpdateYijiArea = false; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); NeedUpdateYijiArea = true; }); } var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); } //var holiday_button = document.getElementById('holiday_button'); //holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear() + '年'; month_selector.value = today.getMonth() + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; highlight_day = today.getDate(); convertToNormal(); year = today.getFullYear(); month = today.getMonth(); create_page(today.getFullYear(), today.getMonth() + 1); update_year_month_ui(); var header_id=document.getElementById("header"); var header_color=header_id.style.background; var x=document.getElementsByClassName("day_today"); var i; if (header_color == "rgb(0, 0, 0)"){ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = "#3593b5"; } } else{ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = header_color; } } }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true,0); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { // if(this.children[0].innerHTML === "") // { // highlight_day = parseInt(this.children[1].innerHTML); // } // else // { highlight_day = parseInt(this.children[0].innerHTML); // } //highlight_day = parseInt(this.children[0].innerText); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } // var header_id=document.getElementById("header"); // var header_color=header_id.style.background; // if (header_color == "rgb(0, 0, 0)"){ // var x=document.getElementsByClassName("day_highlight"); // for (i = 0; i < x.length; i++) { // x[i].style.backgroundColor = "#151a1e"; // } // } // else{ // var x=document.getElementsByClassName("day_highlight"); // for (i = 0; i < x.length; i++) { // x[i].style.backgroundColor = "#ffffff"; // } // } // if((year == today.getFullYear()) && (month == today.getMonth())) // { // var x=document.getElementsByClassName("day_today"); // for (i = 0; i < x.length; i++) { // // x[i].style.backgroundColor = "#3593b5"; // x[i].style.backgroundColor = "#3d6be5"; // } // } // x=document.getElementsByClassName("day_today"); // for (i = 0; i < x.length; i++) { // // x[i].style.backgroundColor = "#3593b5"; // x[i].style.backgroundColor = "#3d6be5"; // } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if (index < month_stuff['firstDay'] || index >= month_stuff['firstDay'] + month_stuff['monthDays']) { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + lunar_day + ''; if (worktime && current_cell.className !== 'day_other_month') { current_cell.appendChild(worktime); } // if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); // worktime.className = 'worktime2'; // worktime.innerHTML = ' '; // } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); // worktime.className = 'worktime1'; // worktime.innerHTML = ' '; // } else { // } // if (worktime && current_cell.className !== 'day_other_month') { // current_cell.innerHTML = worktime.innerHTML+ // ' ' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } // else // { // current_cell.innerHTML = '' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } } } update_right_pane(year, month, highlight_day); month_stuff = null; if (header_color == "rgb(0, 0, 0)"){ var day_this_month_len=document.getElementsByClassName('day_this_month').length; for (var i=0; i",""); year_selector.value = str.replace("",""); document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = ""; } else if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; } selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_button') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else if (this.id === 'month_button') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else { return; } // if (div.className === 'hidden_div') { // div.className = 'visible_div'; // calendar.style.display = "none"; // } else { // div.className = 'hidden_div'; // calendar.style.display = ""; // } div.style.left = x + 'px'; div.style.top = y + height + 'px'; update_year_month_ui(); //updateUi(); } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true, 0); var general_datetime_list = document.getElementById('general_datetime_list'); var datetime_container = document.getElementById('datetime_container'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } if(NeedChangeCurrentTime) { datetime_container.children[1].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday + ' '+lunar_month_name + lunar_day_name; NeedChangeCurrentTime = 0; } /* general_datetime_list.children[0].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = lunar_month_name + lunar_day_name;*/ //general_datetime_list.children[0].innerHTML = ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; // general_datetime_list.children[1].innerHTML = ganzhi_month + '月 ' + ganzhi_day + '日'; updateTime(); if(NeedUpdateYijiArea) { general_datetime_list.children[0].innerHTML = ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; update_yiji_area(); } NeedUpdateYijiArea = true; month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false, 0); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false, 0); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year + '年'; month_selector.value = month + '月'; highlight_day = day; create_page(year, month); month_stuff = null; } ukui-panel/plugin-calendar/html/arm64.html0000644000175000017500000000563213633355350017414 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see
  1. 2015-02-04 星期三
  2. 4
  3. 十一月十四
  4. 甲午年【马年】
  5. 丙子月 庚辰日
迁徙 嫁娶
祭祀 安葬
开光 破土
祈福 作梁
ukui-panel/plugin-calendar/html/ukui.html0000644000175000017500000001520313640356061017431 0ustar fengfeng

12:42:53

2020年1月1日 星期三 腊月初七

2020年3月
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  1. 甲午年【马年】丙子月 庚辰日
宜忌
ukui-panel/plugin-calendar/html/index-es.js0000644000175000017500000004136113633355350017646 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see div_range.year.x_max || x < div_range.year.x_min || y > div_range.year.y_max || y < div_range.year.y_min) { year_div.className = 'hidden_div'; } } if (month_div.className === 'visible_div') { if (x > div_range.month.x_max || x < div_range.month.x_min || y > div_range.month.y_max || y < div_range.month.y_min ) { month_div.className = 'hidden_div'; } } /* if (holiday_div.className === 'visible_div') { if (x > div_range.holiday.x_max || x < div_range.holiday.x_min || y > div_range.holiday.y_max || y < div_range.holiday.y_min ) { holiday_div.className = 'hidden_div'; } }*/ }); for (var index = year_range['low']; index <= year_range['high']; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); // new year implies new month year_list.appendChild(li); if (index === year) { year_selector.value = index; } } for (var index = 1; index <= 12; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); month_list.appendChild(li); if (index === month + 1) { month_selector.value = index; } } var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low']; month_selector.value = month_offset % 12 === 0 ? 1 : month_offset % 12 + 1; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } /* var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); }*/ // var holiday_button = document.getElementById('holiday_button'); // holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear(); month_selector.value = today.getMonth() + 1; highlight_day = today.getDate(); create_page(today.getFullYear(), today.getMonth() + 1); }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if (index < month_stuff['firstDay'] || index >= month_stuff['firstDay'] + month_stuff['monthDays']) { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; // worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; // worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + ''; if (worktime && current_cell.className !== 'day_other_month') { // current_cell.appendChild(worktime); } } } update_right_pane(year, month, highlight_day); month_stuff = null; } function new_month_selected() { if (this.parentNode.id === 'year_list') { year_selector.value = this.innerHTML; document.getElementById('year_div').className = 'hidden_div'; } else if (this.parentNode.id === 'month_list') { month_selector.value = this.innerHTML; document.getElementById('month_div').className = 'hidden_div'; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_selector') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; } else if (this.id === 'month_selector') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; } /* else if (this.id === 'holiday_button') { div = document.getElementById('holiday_div'); div.style.width = '64px'; div.style.height = '100px'; div_range.holiday.x_min = x; div_range.holiday.x_max = x + width; div_range.holiday.y_min = y; div_range.holiday.y_max = y + height; }*/else { return; } if (div.className === 'hidden_div') { div.className = 'visible_div'; } else { div.className = 'hidden_div'; } div.style.left = x + 'px'; div.style.top = y + height + 'px'; } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true); var general_datetime_list = document.getElementById('general_datetime_list'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } general_datetime_list.children[0].innerHTML = month_str + '-' + day_str + '-' + year + ' ' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = ' '; general_datetime_list.children[3].innerHTML = ' '; general_datetime_list.children[4].innerHTML = ' '; //update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ /*function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year; month_selector.value = month + 'Month'; highlight_day = day; create_page(year, month); month_stuff = null; }*/ ukui-panel/plugin-calendar/html/ukui-solar-cn.html0000644000175000017500000001001713640356061021143 0ustar fengfeng

12:42:53

2020年1月1日

2020年3月
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ukui-panel/plugin-calendar/html/ukui-solar-en-mon.html0000644000175000017500000001001513643551442021735 0ustar fengfeng

12:42:53

2020-01-01

2020.3
Mon Tue Wed Thur Fri Sat Sun
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ukui-panel/plugin-calendar/html/index-solar-en-mon.js0000644000175000017500000010217513643551442021550 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0) { scrollUp_count--; } else { scrollUp_count = 2; } } for(var index = 0; index <16; index++) { // li.children[0].children[index].innerHTML = '
'; //li.children[0].children[index].innerHTML = '
'+ list[index]+ '月'; li.children[0].children[index].innerHTML =''+ list[index] + ''; // li.children[0].children[index].innerHTML = list[index]+ '月'; // document.getElementsByTagName('span').style="float:left;width:250px;background:#6C3;"; if(index >= bind_click_position) { if(scrollUp_count%3 ===2) { if(bind_click_count < 8) { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; } continue; } if(bind_click_count < 12) // max bind _count of month click is no more than 12 { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; } } else { li.children[0].children[index].style.color = "#FFFFFF33"; } } } function update_year_month_ui() { var li = document.getElementById('year_div'); for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var curretYear = year + index; li.children[0].children[index].innerHTML= ''+curretYear +'' ; //li.children[0].children[index].innerHTML= '
'+curretYear+ '年'; // if(index === 0) // { // li.children[0].children[index].style.backgroundColor = "#2b87a8"; // } li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // year_list.appendChild(li); // if (index === year) { // year_selector.value = index + '年'; // } } li = document.getElementById('month_div'); for (var index = 0; index < 16; index++) { li.children[0].children[index].removeEventListener('click', new_month_selected); li.children[0].children[index].style.color = "#FFFFFFFF"; if(index >=12) { var newIndex = index -12 + 1; li.children[0].children[index].style.color = "#FFFFFF33"; //li.children[0].children[index].innerHTML = '
' + new_index + '月'; li.children[0].children[index].innerHTML= ''+newIndex +'' ; //li.children[0].children[index].innerHTML = "1月"; } else { var newIndex = index + 1; //li.children[0].children[index].innerHTML ='
' + newIndex+ '月'; li.children[0].children[index].innerHTML =''+ newIndex + '' ; } if(index < 12) { li.children[0].children[index].addEventListener('click', new_month_selected); } // month_list.appendChild(li); if (index === month + 1) { month_selector.value = index; } } } function updateUi() { year_selector.value = year; update_year_month_ui(); // var li = document.getElementById('year_div'); // for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML= year + index + '年'; // li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // // year_list.appendChild(li); // // if (index === year) { // // year_selector.value = index + '年'; // // } // } // li = document.getElementById('month_div'); // for (var index = 0; index < 16; index++) { // if(index >=12) // { // var new_index = index -12; // li.children[0].children[index].innerHTML = new_index +1+ '月'; // } // else // { // li.children[0].children[index].innerHTML = index +1+ '月'; // } // li.children[0].children[index].addEventListener('click', new_month_selected); // // month_list.appendChild(li); // if (index === month + 1) { // month_selector.value = index + '月'; // } // } } function scroll_div(event) { var e = event||window.event; if(e.wheelDelta > 0) { if(this.id === 'year_div') { year = year - 4; } else if(this.id === 'month_div') { scrollUp_count++; update_month_ui(0); return; } } else { if(this.id === 'year_div') { year = year + 4; } else if(this.id === 'month_div') { scrollDown_count++; update_month_ui(1); return; } } updateUi(); } function update_yiji_area() { "use strict"; var year = parseInt(year_selector.value, 10); var month = parseInt(month_selector.value, 10); var hl_table = document.getElementById('hl_table'); var current_row; var current_cell; if (year !== parseInt(hl_script.id, 10)) { load_hl_script(year); return; } if (typeof HuangLi['y' + year] === 'undefined') { for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if (row === 1) { current_cell.innerHTML = ''; } else { current_cell.innerHTML = ''; } } } } var day = highlight_day; var month_str = month.toString(); var day_str = day.toString(); if (month <= 9) { month_str = '0' + month; } if (day <= 9) { day_str = '0' + day; } var yi_str = HuangLi['y' + year]['d' + month_str + day_str]['y']; var ji_str = HuangLi['y' + year]['d' + month_str + day_str]['j']; var hl_yi_data = yi_str.split('.'); var hl_ji_data = ji_str.split('.'); for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if(0 == row ) { if(hl_yi_data[column-1]) { current_cell.innerHTML = hl_yi_data[column-1]; } else { current_cell.innerHTML = ''; } } else { if(hl_ji_data[column-1]) { current_cell.innerHTML = hl_ji_data[column-1]; } else { current_cell.innerHTML =''; } } } } } function load_hl_script(year) { "use strict"; if (hl_script) { document.body.removeChild(hl_script); hl_script = null; } hl_script = document.createElement("SCRIPT"); hl_script.type = "text/javascript"; hl_script.src = "hl/hl" + year + '.js'; hl_script.id = year; hl_script.onload = function() { update_yiji_area(); }; document.body.appendChild(hl_script); } window.onload = function () { "use strict"; load_hl_script(today.getFullYear()); // var year_list = document.getElementById('year_list'); // var month_list = document.getElementById('month_list'); year = today.getFullYear(); month = today.getMonth(); var real_month = month + 1; selected_date_div = document.getElementById('selected_date_div'); year_selector = document.createElement('year_selector'); month_selector = document.createElement('month_selector'); year_selector.value = year; month_selector.value = real_month; selected_date_div.innerHTML = year_selector.value +'.'+month_selector.value; // year_selector = document.getElementById('year_selector'); // // year_selector.addEventListener('click', popup_div); // month_selector = document.getElementById('month_selector'); // month_selector.addEventListener('click', popup_div); //end // alert("begin"); year_button = document.getElementById('year_button'); year_button.addEventListener('click', popup_div); // alert("end"); month_button= document.getElementById('month_button'); month_button.addEventListener('click', popup_div); document.getElementById('year_div').addEventListener('mousewheel',scroll_div); document.getElementById('month_div').addEventListener('mousewheel',scroll_div); document.addEventListener('click', function(event) { }); updateUi(); var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); //page the year ui if(document.getElementById('year_div').className ==='visible_div') { var li = document.getElementById('year_div'); if(this.id === 'go_prev_month') { year = year -16; year_selector.value = year; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
' + curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else if(this.id === 'go_next_month') { year = year + 16; year_selector.value = year; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
'+ curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } return; } else if(document.getElementById('month_div').className ==='visible_div')//page the month ui { if(this.id === 'go_prev_month') { year --; year_selector.value = year; selected_date_div.innerHTML = year_selector.value + '.' +month_selector.value; } else if(this.id === 'go_next_month') { year++; year_selector.value = year; selected_date_div.innerHTML = year_selector.value + '.' + month_selector.value; } return; } // var year = parseInt(year_selector.value); // var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low']; month_selector.value = month_offset % 12 === 0 ? 1 : month_offset % 12 + 1; selected_date_div.innerHTML = year_selector.value + '.' +month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); } //var holiday_button = document.getElementById('holiday_button'); //holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear(); month_selector.value = today.getMonth() + 1; selected_date_div.innerHTML = year_selector.value + '.' + month_selector.value; highlight_day = today.getDate(); convertToNormal(); year = today.getFullYear(); month = today.getMonth(); create_page(today.getFullYear(), today.getMonth() + 1); update_year_month_ui(); var header_id=document.getElementById("header"); var header_color=header_id.style.background; var x=document.getElementsByClassName("day_today"); var i; if (header_color == "rgb(0, 0, 0)"){ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = "#3593b5"; } } else{ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = header_color; } } }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true,1); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if ((index < (month_stuff['firstDay'] -1) && month_stuff['firstDay'] != 0)//每周从周一开始,当月第一天不是星期天,上个月的日期 ||(index < 6 && month_stuff['firstDay'] === 0)//第一天是星期天 || (month_stuff['firstDay']===0 && index >= (month_stuff['monthDays'] + 6))//第一天是星期天下月的日期 ||( month_stuff['firstDay'] != 0 && index >= month_stuff['firstDay'] + month_stuff['monthDays']-1)) //第一天不是星期天下月日期 { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; worktime.innerHTML = ' '; } else if (month_stuff['monthData'][index]['worktime'] === 1) { worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; worktime.innerHTML = ' '; } else { } /*myworktime.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + lunar_day + '';*/ // if (worktime && current_cell.className !== 'day_other_month') { // //current_cell.appendChild(worktime); // //
// // document.getElementById('aa').innerHTML = worktime.innerHTML; // current_cell.innerHTML = worktime.innerHTML+ // // '
'+ // ' ' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // // current_cell.innerHTML = '123' // // +'
' + '456'+ // // '
' +'789'; // } // else // { // current_cell.innerHTML = '' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' } } update_right_pane(year, month, highlight_day); month_stuff = null; if (header_color == "rgb(0, 0, 0)"){ var day_this_month_len=document.getElementsByClassName('day_this_month').length; for (var i=0; i",""); year_selector.value = str.replace("",""); document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = ""; } else if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; } selected_date_div.innerHTML = year_selector.value + '.' + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_button') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else if (this.id === 'month_button') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else { return; } // if (div.className === 'hidden_div') { // div.className = 'visible_div'; // calendar.style.display = "none"; // } else { // div.className = 'hidden_div'; // calendar.style.display = ""; // } div.style.left = x + 'px'; div.style.top = y + height + 'px'; update_year_month_ui(); //updateUi(); } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true, 1); var general_datetime_list = document.getElementById('general_datetime_list'); var datetime_container = document.getElementById('datetime_container'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; console.log(highlight_index); var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } if(NeedChangeCurrentTime) { datetime_container.children[1].innerHTML = year + '-' + month_str + '-' + day_str + ' ' + weekday /* + ' '+lunar_month_name + lunar_day_name*/; NeedChangeCurrentTime = 0; } /* general_datetime_list.children[0].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = lunar_month_name + lunar_day_name;*/ //general_datetime_list.children[0].innerHTML = ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; // general_datetime_list.children[1].innerHTML = ganzhi_month + '月 ' + ganzhi_day + '日'; updateTime(); update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false, 1); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false, 1); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year; month_selector.value = month; highlight_day = day; create_page(year, month); month_stuff = null; } ukui-panel/plugin-calendar/html/ukui-en.css0000644000175000017500000002362313643571462017671 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see
DOM LUN MAR MIE JUE VIE SAB
  1. 2015-02-04 星期三
  2. 4
  3. 十一月十四
  4. 甲午年【马年】
  5. 丙子月 庚辰日
ukui-panel/plugin-calendar/html/index-mon.js0000644000175000017500000012240413643571462020033 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0) { scrollUp_count--; } else { scrollUp_count = 2; } } for(var index = 0; index <16; index++) { // li.children[0].children[index].innerHTML = '
'; //li.children[0].children[index].innerHTML = '
'+ list[index]+ '月'; li.children[0].children[index].innerHTML =''+ list[index]+ '月' + ''; // li.children[0].children[index].innerHTML = list[index]+ '月'; // document.getElementsByTagName('span').style="float:left;width:250px;background:#6C3;"; if(index >= bind_click_position) { if(scrollUp_count%3 ===2) { if(bind_click_count < 8) { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; } continue; } if(bind_click_count < 12) // max bind _count of month click is no more than 12 { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; } } else { li.children[0].children[index].style.color = "#FFFFFF33"; } } } function update_year_month_ui() { var li = document.getElementById('year_div'); for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var curretYear = year + index; li.children[0].children[index].innerHTML= ''+curretYear+ '年' +'' ; //li.children[0].children[index].innerHTML= '
'+curretYear+ '年'; // if(index === 0) // { // li.children[0].children[index].style.backgroundColor = "#2b87a8"; // } li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // year_list.appendChild(li); // if (index === year) { // year_selector.value = index + '年'; // } } li = document.getElementById('month_div'); for (var index = 0; index < 16; index++) { li.children[0].children[index].removeEventListener('click', new_month_selected); li.children[0].children[index].style.color = "#FFFFFFFF"; if(index >=12) { var newIndex = index -12 + 1; li.children[0].children[index].style.color = "#FFFFFF33"; //li.children[0].children[index].innerHTML = '
' + new_index + '月'; li.children[0].children[index].innerHTML= ''+newIndex + '月' +'' ; //li.children[0].children[index].innerHTML = "1月"; } else { var newIndex = index + 1; //li.children[0].children[index].innerHTML ='
' + newIndex+ '月'; li.children[0].children[index].innerHTML =''+ newIndex+ '月' + '' ; } if(index < 12) { li.children[0].children[index].addEventListener('click', new_month_selected); } // month_list.appendChild(li); if (index === month + 1) { month_selector.value = index + '月'; } } } function updateUi() { year_selector.value = year + '年'; update_year_month_ui(); // var li = document.getElementById('year_div'); // for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML= year + index + '年'; // li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // // year_list.appendChild(li); // // if (index === year) { // // year_selector.value = index + '年'; // // } // } // li = document.getElementById('month_div'); // for (var index = 0; index < 16; index++) { // if(index >=12) // { // var new_index = index -12; // li.children[0].children[index].innerHTML = new_index +1+ '月'; // } // else // { // li.children[0].children[index].innerHTML = index +1+ '月'; // } // li.children[0].children[index].addEventListener('click', new_month_selected); // // month_list.appendChild(li); // if (index === month + 1) { // month_selector.value = index + '月'; // } // } } function scroll_div(event) { var e = event||window.event; if(e.wheelDelta > 0) { if(this.id === 'year_div') { year = year - 4; } else if(this.id === 'month_div') { scrollUp_count++; update_month_ui(0); return; } } else { if(this.id === 'year_div') { year = year + 4; } else if(this.id === 'month_div') { scrollDown_count++; update_month_ui(1); return; } } updateUi(); } function update_yiji_area() { "use strict"; var year = parseInt(year_selector.value, 10); var month = parseInt(month_selector.value, 10); var hl_table = document.getElementById('hl_table'); var current_row; var current_cell; if (year !== parseInt(hl_script.id, 10)) { load_hl_script(year); return; } if (typeof HuangLi['y' + year] === 'undefined') { for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if (row === 1) { current_cell.innerHTML = '无数据'; } else { current_cell.innerHTML = ''; } } } } var day = highlight_day; var month_str = month.toString(); var day_str = day.toString(); if (month <= 9) { month_str = '0' + month; } if (day <= 9) { day_str = '0' + day; } var yi_str = HuangLi['y' + year]['d' + month_str + day_str]['y']; var ji_str = HuangLi['y' + year]['d' + month_str + day_str]['j']; var hl_yi_data = yi_str.split('.'); var hl_ji_data = ji_str.split('.'); for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if(0 == row ) { if(hl_yi_data[column-1]) { current_cell.innerHTML = hl_yi_data[column-1]; } else { current_cell.innerHTML = ''; } } else { if(hl_ji_data[column-1]) { current_cell.innerHTML = hl_ji_data[column-1]; } else { current_cell.innerHTML =''; } } } } } function load_hl_script(year) { "use strict"; if (hl_script) { document.body.removeChild(hl_script); hl_script = null; } hl_script = document.createElement("SCRIPT"); hl_script.type = "text/javascript"; hl_script.src = "hl/hl" + year + '.js'; hl_script.id = year; hl_script.onload = function() { update_yiji_area(); }; document.body.appendChild(hl_script); } window.onload = function () { var checkbox = document.getElementById('advice_checkbox'); if (localStorage.getItem('hl_table') == "display"){ checkbox.setAttribute("checked", true); hl_table.setAttribute("style", "visibility:display"); //var zodiac_icon = document.getElementById('zodiac_icon'); //zodiac_icon.setAttribute("style", "display:none"); } checkbox.onclick = function(){ console.log("checkbox triggerd"); if(this.checked){ var hl_table = document.getElementById('hl_table'); hl_table.setAttribute("style", "visibility:display"); //var zodiac_icon = document.getElementById('zodiac_icon'); //zodiac_icon.setAttribute("style", "display:none"); localStorage.setItem('hl_table', "display"); } else{ var hl_table = document.getElementById('hl_table'); hl_table.setAttribute("style", "visibility:hidden"); // var zodiac_icon = document.getElementById('zodiac_icon'); // zodiac_icon.setAttribute("style", "display:block"); //zodiac_icon.setAttribute("style", "padding-top: 33px"); localStorage.setItem('hl_table', "hidden"); } } "use strict"; load_hl_script(today.getFullYear()); // var year_list = document.getElementById('year_list'); // var month_list = document.getElementById('month_list'); year = today.getFullYear(); month = today.getMonth(); var real_month = month + 1; selected_date_div = document.getElementById('selected_date_div'); year_selector = document.createElement('year_selector'); month_selector = document.createElement('month_selector'); year_selector.value = year + '年'; month_selector.value = real_month +'月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; // year_selector = document.getElementById('year_selector'); // // year_selector.addEventListener('click', popup_div); // month_selector = document.getElementById('month_selector'); // month_selector.addEventListener('click', popup_div); //end // alert("begin"); year_button = document.getElementById('year_button'); year_button.addEventListener('click', popup_div); // alert("end"); month_button= document.getElementById('month_button'); month_button.addEventListener('click', popup_div); document.getElementById('year_div').addEventListener('mousewheel',scroll_div); document.getElementById('month_div').addEventListener('mousewheel',scroll_div); // year_button = document.getElementById('year_button'); // year_button.addEventListener('click', popup_div); // month_button = document.getElementById('month_button'); // month_button.addEventListener('click', popup_div); // document.addEventListener('mousewheel', function(event) // { // //alert("sroll??"); // }) document.addEventListener('click', function(event) { // var year_div = document.getElementById('year_div'); // var month_div = document.getElementById('month_div'); // var holiday_div = document.getElementById('holiday_div'); // var x = event.clientX; // var y = event.clientY; // if (year_div.className === 'visible_div') { // if (x > div_range.year.x_max || x < div_range.year.x_min || // y > div_range.year.y_max || y < div_range.year.y_min) { // year_div.className = 'hidden_div'; // } // } // if (month_div.className === 'visible_div') { // if (x > div_range.month.x_max || x < div_range.month.x_min || // y > div_range.month.y_max || y < div_range.month.y_min ) { // month_div.className = 'hidden_div'; // } // } // if (holiday_div.className === 'visible_div') { // if (x > div_range.holiday.x_max || x < div_range.holiday.x_min || // y > div_range.holiday.y_max || y < div_range.holiday.y_min ) { // holiday_div.className = 'hidden_div'; // } // } // var header_id=document.getElementById("header"); // var header_color=header_id.style.background; // var x=document.getElementsByClassName("day_highlight"); // if (header_color == "rgb(0, 0, 0)"){ // for (i = 0; i < x.length; i++) { // x[i].style.backgroundColor = "#2b87a8"; // } // var day_highlight_len=document.getElementsByClassName('day_highlight').length; // for (var i=0; i'; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else if(this.id === 'go_next_month') { year = year + 16; year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
'+ curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '月' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } return; } else if(document.getElementById('month_div').className ==='visible_div')//page the month ui { if(this.id === 'go_prev_month') { year --; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } else if(this.id === 'go_next_month') { year++; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } return; } // var year = parseInt(year_selector.value); // var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low'] + '年'; month_selector.value = month_offset % 12 === 0 ? 1 +'月': month_offset % 12 + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; NeedUpdateYijiArea = false; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); NeedUpdateYijiArea = true; }); } var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); } //var holiday_button = document.getElementById('holiday_button'); //holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear() + '年'; month_selector.value = today.getMonth() + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; highlight_day = today.getDate(); convertToNormal(); year = today.getFullYear(); month = today.getMonth(); create_page(today.getFullYear(), today.getMonth() + 1); update_year_month_ui(); var header_id=document.getElementById("header"); var header_color=header_id.style.background; var x=document.getElementsByClassName("day_today"); var i; if (header_color == "rgb(0, 0, 0)"){ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = "#3593b5"; } } else{ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = header_color; } } }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true,1); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { if(this.children[0].innerHTML === "") { highlight_day = parseInt(this.children[1].innerHTML); } else { highlight_day = parseInt(this.children[0].innerHTML); } if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } // var header_id=document.getElementById("header"); // var header_color=header_id.style.background; // if (header_color == "rgb(0, 0, 0)"){ // var x=document.getElementsByClassName("day_highlight"); // for (i = 0; i < x.length; i++) { // x[i].style.backgroundColor = "#151a1e"; // } // } // else{ // var x=document.getElementsByClassName("day_highlight"); // for (i = 0; i < x.length; i++) { // x[i].style.backgroundColor = "#ffffff"; // } // } // if((year == today.getFullYear()) && (month == today.getMonth())) // { // var x=document.getElementsByClassName("day_today"); // for (i = 0; i < x.length; i++) { // // x[i].style.backgroundColor = "#3593b5"; // x[i].style.backgroundColor = "#3d6be5"; // } // } // x=document.getElementsByClassName("day_today"); // for (i = 0; i < x.length; i++) { // // x[i].style.backgroundColor = "#3593b5"; // x[i].style.backgroundColor = "#3d6be5"; // } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if ((index < (month_stuff['firstDay'] -1) && month_stuff['firstDay'] != 0)//每周从周一开始,当月第一天不是星期天,上个月的日期 ||(index < 6 && month_stuff['firstDay'] === 0)//第一天是星期天 || (month_stuff['firstDay']===0 && index >= (month_stuff['monthDays'] + 6))//第一天是星期天下月的日期 ||( month_stuff['firstDay'] != 0 && index >= month_stuff['firstDay'] + month_stuff['monthDays']-1)) //第一天不是星期天下月日期 { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (((month_stuff['firstDay'] != 0)&&(index === highlight_day + month_stuff['firstDay'] - 1 -1)) ||((month_stuff['firstDay'] === 0)&&(index === highlight_day + 5)) ) { current_cell.className = 'day_highlight'; } else if (column === 5 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + lunar_day + ''; if (worktime && current_cell.className !== 'day_other_month') { current_cell.appendChild(worktime); } // if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); // worktime.className = 'worktime2'; // worktime.innerHTML = ' '; // } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); // worktime.className = 'worktime1'; // worktime.innerHTML = ' '; // } else { // } // /*myworktime.innerHTML = '' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // '';*/ // if (worktime && current_cell.className !== 'day_other_month') { // //current_cell.appendChild(worktime); // //
// // document.getElementById('aa').innerHTML = worktime.innerHTML; // current_cell.innerHTML = worktime.innerHTML+ // // '
'+ // ' ' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // // current_cell.innerHTML = '123' // // +'
' + '456'+ // // '
' +'789'; // } // else // { // current_cell.innerHTML = '' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } } } update_right_pane(year, month, highlight_day); month_stuff = null; if (header_color == "rgb(0, 0, 0)"){ var day_this_month_len=document.getElementsByClassName('day_this_month').length; for (var i=0; i",""); year_selector.value = str.replace("",""); document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = ""; } else if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; } selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_button') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else if (this.id === 'month_button') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else { return; } // if (div.className === 'hidden_div') { // div.className = 'visible_div'; // calendar.style.display = "none"; // } else { // div.className = 'hidden_div'; // calendar.style.display = ""; // } div.style.left = x + 'px'; div.style.top = y + height + 'px'; update_year_month_ui(); //updateUi(); } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true, 1); var general_datetime_list = document.getElementById('general_datetime_list'); var datetime_container = document.getElementById('datetime_container'); // var highlight_index = month_stuff['firstDay'] + day - 1; var highlight_index = null; if(month_stuff['firstDay'] === 0)//index of this data is six { highlight_index = day -1 + 6; } else { highlight_index = month_stuff['firstDay'] -1 + day - 1;//firstDay's index is firstDay - 1 } var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } if(NeedChangeCurrentTime) { datetime_container.children[1].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday + ' '+lunar_month_name + lunar_day_name; NeedChangeCurrentTime = 0; } /* general_datetime_list.children[0].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = lunar_month_name + lunar_day_name;*/ //general_datetime_list.children[0].innerHTML = ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; // general_datetime_list.children[1].innerHTML = ganzhi_month + '月 ' + ganzhi_day + '日'; updateTime(); if(NeedUpdateYijiArea) { general_datetime_list.children[0].innerHTML = ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; update_yiji_area(); } NeedUpdateYijiArea = true; month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false, 1); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false, 1); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year + '年'; month_selector.value = month + '月'; highlight_day = day; create_page(year, month); month_stuff = null; } ukui-panel/plugin-calendar/html/index-solar-cn-mon.js0000644000175000017500000010237113642614010021532 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0) { scrollUp_count--; } else { scrollUp_count = 2; } } for(var index = 0; index <16; index++) { // li.children[0].children[index].innerHTML = '
'; //li.children[0].children[index].innerHTML = '
'+ list[index]+ '月'; li.children[0].children[index].innerHTML =''+ list[index]+ '月' + ''; // li.children[0].children[index].innerHTML = list[index]+ '月'; // document.getElementsByTagName('span').style="float:left;width:250px;background:#6C3;"; if(index >= bind_click_position) { if(scrollUp_count%3 ===2) { if(bind_click_count < 8) { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; } continue; } if(bind_click_count < 12) // max bind _count of month click is no more than 12 { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; } } else { li.children[0].children[index].style.color = "#FFFFFF33"; } } } function update_year_month_ui() { var li = document.getElementById('year_div'); for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var curretYear = year + index; li.children[0].children[index].innerHTML= ''+curretYear+ '年' +'' ; //li.children[0].children[index].innerHTML= '
'+curretYear+ '年'; // if(index === 0) // { // li.children[0].children[index].style.backgroundColor = "#2b87a8"; // } li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // year_list.appendChild(li); // if (index === year) { // year_selector.value = index + '年'; // } } li = document.getElementById('month_div'); for (var index = 0; index < 16; index++) { li.children[0].children[index].removeEventListener('click', new_month_selected); li.children[0].children[index].style.color = "#FFFFFFFF"; if(index >=12) { var newIndex = index -12 + 1; li.children[0].children[index].style.color = "#FFFFFF33"; //li.children[0].children[index].innerHTML = '
' + new_index + '月'; li.children[0].children[index].innerHTML= ''+newIndex + '月' +'' ; //li.children[0].children[index].innerHTML = "1月"; } else { var newIndex = index + 1; //li.children[0].children[index].innerHTML ='
' + newIndex+ '月'; li.children[0].children[index].innerHTML =''+ newIndex+ '月' + '' ; } if(index < 12) { li.children[0].children[index].addEventListener('click', new_month_selected); } // month_list.appendChild(li); if (index === month + 1) { month_selector.value = index + '月'; } } } function updateUi() { year_selector.value = year + '年'; update_year_month_ui(); // var li = document.getElementById('year_div'); // for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML= year + index + '年'; // li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // // year_list.appendChild(li); // // if (index === year) { // // year_selector.value = index + '年'; // // } // } // li = document.getElementById('month_div'); // for (var index = 0; index < 16; index++) { // if(index >=12) // { // var new_index = index -12; // li.children[0].children[index].innerHTML = new_index +1+ '月'; // } // else // { // li.children[0].children[index].innerHTML = index +1+ '月'; // } // li.children[0].children[index].addEventListener('click', new_month_selected); // // month_list.appendChild(li); // if (index === month + 1) { // month_selector.value = index + '月'; // } // } } function scroll_div(event) { var e = event||window.event; if(e.wheelDelta > 0) { if(this.id === 'year_div') { year = year - 4; } else if(this.id === 'month_div') { scrollUp_count++; update_month_ui(0); return; } } else { if(this.id === 'year_div') { year = year + 4; } else if(this.id === 'month_div') { scrollDown_count++; update_month_ui(1); return; } } updateUi(); } function update_yiji_area() { "use strict"; var year = parseInt(year_selector.value, 10); var month = parseInt(month_selector.value, 10); var hl_table = document.getElementById('hl_table'); var current_row; var current_cell; if (year !== parseInt(hl_script.id, 10)) { load_hl_script(year); return; } if (typeof HuangLi['y' + year] === 'undefined') { for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if (row === 1) { current_cell.innerHTML = '无数据'; } else { current_cell.innerHTML = ''; } } } } var day = highlight_day; var month_str = month.toString(); var day_str = day.toString(); if (month <= 9) { month_str = '0' + month; } if (day <= 9) { day_str = '0' + day; } var yi_str = HuangLi['y' + year]['d' + month_str + day_str]['y']; var ji_str = HuangLi['y' + year]['d' + month_str + day_str]['j']; var hl_yi_data = yi_str.split('.'); var hl_ji_data = ji_str.split('.'); for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if(0 == row ) { if(hl_yi_data[column-1]) { current_cell.innerHTML = hl_yi_data[column-1]; } else { current_cell.innerHTML = ''; } } else { if(hl_ji_data[column-1]) { current_cell.innerHTML = hl_ji_data[column-1]; } else { current_cell.innerHTML =''; } } } } } function load_hl_script(year) { "use strict"; if (hl_script) { document.body.removeChild(hl_script); hl_script = null; } hl_script = document.createElement("SCRIPT"); hl_script.type = "text/javascript"; hl_script.src = "hl/hl" + year + '.js'; hl_script.id = year; hl_script.onload = function() { update_yiji_area(); }; document.body.appendChild(hl_script); } window.onload = function () { "use strict"; load_hl_script(today.getFullYear()); // var year_list = document.getElementById('year_list'); // var month_list = document.getElementById('month_list'); year = today.getFullYear(); month = today.getMonth(); var real_month = month + 1; selected_date_div = document.getElementById('selected_date_div'); year_selector = document.createElement('year_selector'); month_selector = document.createElement('month_selector'); year_selector.value = year + '年'; month_selector.value = real_month +'月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; // year_selector = document.getElementById('year_selector'); // // year_selector.addEventListener('click', popup_div); // month_selector = document.getElementById('month_selector'); // month_selector.addEventListener('click', popup_div); //end // alert("begin"); year_button = document.getElementById('year_button'); year_button.addEventListener('click', popup_div); // alert("end"); month_button= document.getElementById('month_button'); month_button.addEventListener('click', popup_div); document.getElementById('year_div').addEventListener('mousewheel',scroll_div); document.getElementById('month_div').addEventListener('mousewheel',scroll_div); document.addEventListener('click', function(event) { }); updateUi(); var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); //page the year ui if(document.getElementById('year_div').className ==='visible_div') { var li = document.getElementById('year_div'); if(this.id === 'go_prev_month') { year = year -16; year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
' + curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '月' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else if(this.id === 'go_next_month') { year = year + 16; year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
'+ curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '月' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } return; } else if(document.getElementById('month_div').className ==='visible_div')//page the month ui { if(this.id === 'go_prev_month') { year --; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } else if(this.id === 'go_next_month') { year++; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } return; } // var year = parseInt(year_selector.value); // var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low'] + '年'; month_selector.value = month_offset % 12 === 0 ? 1 +'月': month_offset % 12 + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); } //var holiday_button = document.getElementById('holiday_button'); //holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear() + '年'; month_selector.value = today.getMonth() + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; highlight_day = today.getDate(); convertToNormal(); year = today.getFullYear(); month = today.getMonth(); create_page(today.getFullYear(), today.getMonth() + 1); update_year_month_ui(); var header_id=document.getElementById("header"); var header_color=header_id.style.background; var x=document.getElementsByClassName("day_today"); var i; if (header_color == "rgb(0, 0, 0)"){ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = "#3593b5"; } } else{ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = header_color; } } }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true,1); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if ((index < (month_stuff['firstDay'] -1) && month_stuff['firstDay'] != 0)//每周从周一开始,当月第一天不是星期天,上个月的日期 ||(index < 6 && month_stuff['firstDay'] === 0)//第一天是星期天 || (month_stuff['firstDay']===0 && index >= (month_stuff['monthDays'] + 6))//第一天是星期天下月的日期 ||( month_stuff['firstDay'] != 0 && index >= month_stuff['firstDay'] + month_stuff['monthDays']-1)) //第一天不是星期天下月日期 { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; worktime.innerHTML = ' '; } else if (month_stuff['monthData'][index]['worktime'] === 1) { worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; worktime.innerHTML = ' '; } else { } /*myworktime.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + lunar_day + '';*/ // if (worktime && current_cell.className !== 'day_other_month') { // //current_cell.appendChild(worktime); // //
// // document.getElementById('aa').innerHTML = worktime.innerHTML; // current_cell.innerHTML = worktime.innerHTML+ // // '
'+ // ' ' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // // current_cell.innerHTML = '123' // // +'
' + '456'+ // // '
' +'789'; // } // else // { // current_cell.innerHTML = '' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' } } update_right_pane(year, month, highlight_day); month_stuff = null; if (header_color == "rgb(0, 0, 0)"){ var day_this_month_len=document.getElementsByClassName('day_this_month').length; for (var i=0; i",""); year_selector.value = str.replace("",""); document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = ""; } else if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; } selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_button') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else if (this.id === 'month_button') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else { return; } // if (div.className === 'hidden_div') { // div.className = 'visible_div'; // calendar.style.display = "none"; // } else { // div.className = 'hidden_div'; // calendar.style.display = ""; // } div.style.left = x + 'px'; div.style.top = y + height + 'px'; update_year_month_ui(); //updateUi(); } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true, 1); var general_datetime_list = document.getElementById('general_datetime_list'); var datetime_container = document.getElementById('datetime_container'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } if(NeedChangeCurrentTime) { datetime_container.children[1].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday /* + ' '+lunar_month_name + lunar_day_name*/; NeedChangeCurrentTime = 0; } /* general_datetime_list.children[0].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = lunar_month_name + lunar_day_name;*/ //general_datetime_list.children[0].innerHTML = ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; // general_datetime_list.children[1].innerHTML = ganzhi_month + '月 ' + ganzhi_day + '日'; updateTime(); update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false, 1); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false, 1); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year + '年'; month_selector.value = month + '月'; highlight_day = day; create_page(year, month); month_stuff = null; } ukui-panel/plugin-calendar/html/images/0000755000175000017500000000000013640356061017032 5ustar fengfengukui-panel/plugin-calendar/html/images/next.png0000644000175000017500000000230213635352661020521 0ustar fengfengPNG  IHDR00WtEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp !x2IDATx 0qNAEWp wv GW'P PB{/5Mlqͫi~09\9ЌlӜ3=; pY3!fO4+OOH!ba_" 1Px&n3kS|['(o{H"d'1'%U_.Tw!{m4E<,"(bjL6!4xniKhПU2^֐%/ g`` TIENDB`ukui-panel/plugin-calendar/html/images/up_click.png0000644000175000017500000000206613640356061021335 0ustar fengfengPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp $ IDATxb?@&uF.pf[`M`2 jhy(*ur nb $,dZ |T\Giy rh -g,T"GPrBrh>'rBeIv#zE1hxuw@ˋ4>IENDB`ukui-panel/plugin-calendar/html/images/header-bg.png0000644000175000017500000000204313632320722021351 0ustar fengfengPNG  IHDR & tEXtSoftwareAdobe ImageReadyqe<qiTXtXML:com.adobe.xmp ROMHIDATxb1!?aE dt6ETs tn&1(0h*0@pfQIENDB`ukui-panel/plugin-calendar/html/images/shangban.png0000644000175000017500000000312213635352661021325 0ustar fengfengPNG  IHDR$$tEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp Δ[IDATxb|@T] $ԁ 0 @;h@ ژ4X|qjV1DSdgg@9,l/V>3|9U N3<:UQ-U@;مlA2|8\{Iw$!lnx/2|PAy~7_ODϯgG~EHq dPZNebd"1AAT!!2EB.lG??AEHebD C8UE j%AexspafLy}%@ltO0q301D^uG lX&fxP6#>vk$RUF}> $M"j#* }5 |64-&xqE'!&< 6w2T_m'^P@ ^VY pq4:<>L!AVpyu,*XQ`w}P"/{Zix Fx=Ar.Ϣ8!Sz O=_E9? ǀP r PAn`I/IENDB`ukui-panel/plugin-calendar/html/images/zodiac/0000755000175000017500000000000013632320722020277 5ustar fengfengukui-panel/plugin-calendar/html/images/zodiac/blue/0000755000175000017500000000000013632320722021226 5ustar fengfengukui-panel/plugin-calendar/html/images/zodiac/blue/mouse-white.png0000644000175000017500000001574213632320722024213 0ustar fengfengPNG  IHDRh=A_,IDATx| tTUs*aHRI!a ""* h;!ߵu]{Wm{nV۩EPFA0!IBJMT筿P::s?|7_ @e$ Xk $Iz7j ><xހcx( F(0( ki(wm@(3@<,IdF=7 glƿ : ?^9rD{{"3yP x9,HTICK7!,lsJJJ9x5}ژNgLNNȸx!gjgg[Ԯa_haQ@+-0f̘?dddZZZ%h'6YYttL̠UVbb4iZٳ.#۠n?6ű,{&++kEo h|g(`CVV4ep"++ S[[ر/Xa"AzCDBBB #:q}9 !؜;AglƯ}>u675Y  |k8\w١4GA/^@Hel$IƏ7`C6:=u򤷾/.k^}}M?l[F?~mfKFiӣ=j@7L GG-)*b5aН~o9ы۲i (jM̝>uJ=s+eٚF=*ڪyر.]azqG{ׯ}[e|pU&vL^xEQȈH dcB=}iii.n$%%y\,>c҂?VUUe_e)x v$I BM1t_}aKCCã~ 1uu{>o7o͆j 1M] wo~8@oܸ)Zq)Ĵ4}kk IV?AmBB"< 0uj~ϲOPf `!v,؛կ~\xʷ^.x<{yz^E9wu&5)ɩEyj̬ap{?iOLL ;w 'OQ DGEiRyy9S[SSv҅ %#Q`SRRnIɄ[\Y?A#0$B:SY̒TQϟ#x_ 1.?V{zkSGG,By7k2m}zc0%N'׫e~ii;q:s]0w.>UVO w</AO3E h~l6{ೲy)aq[8{KW4͢t߰W5U|O=4N$.;w~Cch4.D+<OD4$ɇIlܸi3WRRly$l6HNNF5Nh0k֬<#6h$iF4-BF\e.ubNvNBtvvbY/;ڍ=Z*&;hڰq岟O8 H7np VUП=sfˌ3<7NDFFzB_~[eF <«g};a8N(3fnmDȑfsϠ5S^^kp Wj[ZZҴZs\r8;''nΜ°<:)?+>>^^ڰM0NC2=<(!ɘ$+IRC3?q1fpQUUErS ㍎qvvt<D8B999HSUoy%# DQKJJnĈCOCC8q+SA!8nAJ_1P(򗋥[`L:Z,0m@"eL1s2c˗.eEy6+JHH`X_c x JU]q`().v<hoΓ<=O?.3L&!~"!xAW,kop0I~+3CWP:I^rj0, 8$zzAm+PQQ.o[f:e@131qkn7$IؘT[[x >t::(5PSSr9]rlln9Li Gk8l7mH zAB=6m[ Y̲gqq}g_oE6K%G֬XSs˲4j饥'$hUU= %߽MWv*: $Ѻq!E?6@!aMڧ{v'Mz i^E1bxAN6 MӖ`YdL\{WܧywL-E1Pesq!bE{5Aq4M>T0 .BSS[$͸zm=Q(htX p_ Àɓ׬VUnY(ꩮFcc#SQRUU\2ˏ3֮ _)sp (ZՖ=Szх~ ̬̐F9..΁LcCÀ(iӈ40,!,V('( ˥۲e`0cf㙗hWQ]5T+`dYIJ?Uj6,衋Xp80gwh4vree 7~kIs'L^}Aw A_pGhӬV+J5tǝK5AE x)׷Ƈ x={Na0hUU{?c$''{%QRPPf<=xw/PEpoՇw`E/(9$PCَuAh%IZRuIQ ,cer ĩ]!k'U~e=)-񹹒_H"}i3.\t9zxbEO$.8R.TUj}W'ÍlroA 4M&0VpvM6 Ny~ҋPSSn.͓҄&c+l]ݬ((/_~Ԥ @GFF]!%1g;/%jFSgZU l}yWeUUG/LĮ䔔e`9oY٥bfqGG=&h2 M G+eYOQu(?u$kkq`>k񨪪;rƍ[` 'O&&=csѱry~ն刢%/?ߘ0gnVVfKMQԇYA=ªg} 6p4 ?$:誩D\+]$rNSўP Znpdddh˓y.@RG0 btO&K-5;<O !Ec3\ݎl=QQQwϚuMåUYA/]zxvY<@b&2`TYzU虬C?(x^\)^ղʢQfZ-Tc/ظ_i?>7r(Aƥ8r;-Y,uرT]O`΅ %nQQ('!L! H/(AdpTGop`$IznV3| cov׻r8EM;P'!Maw8|u1ݶnS<(rQu YQj$QEokڭ}Vۜ;( ~S:=fr(KsrS^ [[ZA<I+7oL3&8l:0d21߂l6ݍxA渃$f[#5?Bs`Q4))i΢Kz=H(΁{jyALllrFF> ^pa= c:ݫv xڛ555kjjAz(jlt :G233BhǐG.gao6Mzp͢(VHQ~M?(/ᦖ |L%I*D>Łғv!;U ˲ŹF!'| J<`Z,DQ\T@!$nܴ)ge,{riQ5,34M#ISQUU(Jj4e9d2ˆQڨ(6&&b}vGxN͟ ߧNWp "nҤ\(;Z^X;hѫ(&ꊤi˚eE) 2a_ܾ=H/PU!Zn[rCCC25Et>7#pZvNNV06}׮6QAPH?([jzTUU!}Me=õmܕ`Զa?dmRP R$Ir<YX;ia*^(Æ{\NẺkP]]j/xU q& i]j Z3(C@fl6D=8ŋ6Y KU:w IENDB`ukui-panel/plugin-calendar/html/images/zodiac/blue/blue-pig.png0000644000175000017500000001657713632320722023460 0ustar fengfengPNG  IHDRiV̮BFIDATxytcY}?O%ےٖw]eri!LzhF@pQ `2@tH@Nw7$f2s&$n6U]hvY!ml[-]*wu}o6ov^~{]v8pxh~|+q1K=lE"4  vtzN4Z ꩪF.Ϝ~-2a9-ýI, {'77w D/Y-\nuVt5}W"=]UUR\4D"aGgE.bb>%G-2la^Ꚛ4 PeKoLZmTԠV+]q8kp/Dٲcn>"l= k:v:)A^JIF#HTP{$bwq9|(999?pH$C\Ntb_tzkVH$zi29]ҽ^L$3tvv9ȣlHG*b2噢afpV)+K16sPyAd2@]{Igغu(@ 6 u&d-;ZȨLLn4|>E M$ueeeTVU099I<K_o/J.ޱXPSS`O~ wc~9rxծ˗~T*:A==#JWTX(f {TWuzmnގbּH,QXX\[[ۜ}LyNx#kA<'ް4l޲03*((Bd}3_vD"~twˎ fo#V$q:C5uuuH[]]C(2 lO/ђ>|{.(B֢.(؝UWPR,Lߗܸ~Hhjڼw(,,4Y-VrA=' ɤy4VdaaegqӦU4 TTV68N6eޮݻyWj1B7vE> I |KRIEe%xs*)YÀxmQYYuO** RwXB$y;]/BTԘ6g;on4:X4FaQEEE f pFbUhZTj*P(W .iMYYj1gҪ*p-'**+M7o9L&~'b?|p?QBJkW?bUUuI(׮^?1~uzzz|g_:|d%׳fq:V$b;} K*!D$I8h|,:at|ȧʪz|X/xfZBx<FFnvtd`0!5\ (^gД JZ̟ /.j1庂BQ"x<=xSOzj1ϔx<ã#_}?yLed6Lw?Ax<Ϋ dRXvbd2I{9D@cSj`0>Ȑ~XJGfI kK@;pJT[%aZJT׋T*EHM}>VD"6py aFS}}@D"N~~q7<|>_Tk$&H"r9呗D13w>N߳]/O'9ydMMMH$ܼh׮\|> ټy13ߛ/D"hF]P@]݆"aEA]ՖXў8ӑjNJgoqgdx;#ra+*e|l-@kjQ(LǏmw_H$eWæFdK2dSc)cqxH$loi3BMeQ8xC,sy~?p x6zU*UUU| BR??sg9HsgόqOU 'ANNb8D<MkjmvdLF8n3Oq;5@~^>@ ,5Rtcii:^[D<ڮt]fzzAvDԍa#ӑ;wB7cO5ot/2J5,.JJK?sGP_&)gކ/MNNh0dzG9 xߺ^5kײ߼R}@k3{>〩j֭ExI&DbP([AP*Τ۰ymo#,q/ Ś Ǐ7⣙9iVQQ}f?ccc\.]/waϝpN:ͥ@ @qc<ʶ3% 5h4%& !e<ܼ}.ܖT"ɸ@ >&Ln^gN&>WTT<6I$Tw'8''--T*5Ν;5Eˎsb1{)--tcSS2ټy˓eoCCvH洤A388 [p83tC4:NoxNoxH̟.D,/]bjʳw O.^errӧNGgGP蕊ʪe^p j4aHp8}L^H$rok4LC*|q9 "G񱏵;w{]!trrr۷X"۷iKk#JeѲMIO']FUD"*!Bʍ?l?ў`0+X5虝 "Lq&Rh4sԔA)2VugֹF8f:Ǭo9c:h8DHGV͎Vn#^|r2[5S[[K8ƙ^`&p0h{67/ZdZ:f{ODbwcӑA"gxxԔ7o0d?rv*.^6fd29d}:hfa|'J+k'H&粉J?WM,1:ꘘw==T*h4V.   m.+c?-qONͱ7###:ywVC<#L^7wò42r-/?FDں:(DcKCCLLLbB&=ԸdM(V*4[ZH [7o9pjN7йl"Bk؈ ϑ ={ȏuzn~$ Rك/)ƍ61,}8k%1=u8ckmMYd8Dį<NjaC[ ؘ}>1d|z(lPňօRL&{<=L&!_Bp7Vb5"C7eZ-y\~mޥӋ$I*A^-//_V0~n4fXfm7o|>hϨiH&ݣe"]vks8LV Siq:<A ӰqjD 0o7{=nR44la#~A@.v)..c3ǹzDNN;Z>-)J#%ں._ZW3tvrf]6p8e.J_Xh4.]]HDڮt-8n$ p|goϞ9 ctypJ7(L~ƍZ2WL=cc+LʀgLf&''wVY>91^,~D"ht,`ƍg< H3tzC07"J%nRلbVsĆB!SgSjR~5::zp9퇉x<Jߖͱ׉D"656R@(jV* SNQ]H+--5gO!iظQ1rv_II)MřI[Ǘ[jD뒒ӎ֝[eoy?[ +Ă |y%NҾeKJKW̥XtV*{ЮwG}:PVV"1HᲲe* A(r/w 5o[a'av1P()-+]ULm`}7]H{Ah߼e뒯]bjåM@~rr1?moiɺ3J"''gǫFRi#imwx!qr>[ |^:I&KG9e j1>}f37/p8 ,)R>I#>M1Μ>EG{ɾ纻o}S^:m5 "HF 4Not$ΎUjHm|$D%3 mt:| %e/`gNtflzo eH&LLLp|'n{t}gtz?,Nox.,V[XTh-+`1 B^/.^j۟ 'Ο4¢sm\z<LNN|7\.ߞPT*C@#G" HHBjD"Dc1b(HϏ;' Tmjl@t$q}3=A559PD"N(ȈuG|ɉLNLT*?xb "3NeH$GVQ^^q X M&g F*\Dj<@3PTz-J$eJ-J L&$-R똆+@')W*+޳ث'&H&?H[V >~1'G U2#ӟVKHgT X,wx<=ljl=e m #pfsN"!8wֵEIm dŬ妭M^Q4?MNN Rp8\H$h4-X/|>[N6|=u0WT Hsu:!tVsI X)-[L/c,3}p:abtR+g=O{zޏ?_Sj1E"{"[M3Ѷ\x׸No8Oj\|)|\Vvo 'caH_}us H$~W@J(`"X><KFSs3uv*&/*@j h ?ӕ>/w`ѸѴ6osK۲LWҰIENDB`ukui-panel/plugin-calendar/html/images/zodiac/black/0000755000175000017500000000000013632320722021353 5ustar fengfengukui-panel/plugin-calendar/html/images/zodiac/black/black-pig.png0000644000175000017500000001675513632320722023730 0ustar fengfengPNG  IHDRiV̮BIDATxyxg?۲|GIΝ4Z: X,>ߵFKu4jH" z׮w2&ϵ|v0oj^R@H|u׸Be/\B~Jlx}fUݾnp!3{'&o9ةs mA$qeF'+娩*ҫD"!-i%mgOJQQV :vO=#oֹ%=OLux]6@ 4՛ ٺX,Ҷ3WZpmVӠzN@fwK8>3:6؄ʓb^:2NR*{jlϝ8s_m߸ܞW3.>f!OC$m2~9lB(w _rU6WG"Ʌt4O$5.5Ӱ}xG=}W;\AQo޼RoD8cKfT((h#HbS 3Y&ST B0c~gf?]n k=d>9-\$ SӜ8s! k7VQV\@ +80LҢ/\iaGdJ"Vtʃv;^HGQ;΅csH)+MF=;2߿kY&C# LÑ^;Px$w udgr{^^O>vUdJ@ DIc.gv/Ik>9r3s?E"霾FZ-Pe*ߜ҇--?O$! }*d2idsjڳn{2}X6k 4$ k8% DB vMpx ,#G8zh4ѨU@ 8Mb1JWG݂hQTwt $ d2)j,c;g*enyILQ"6]n˥۬z+ܝP ?i&&'YrD赚:f^%ln=I}f ;{bqݾܯh5tx RT0,~yǽ!D"{x[_A{43_zV))+.Ia] [~MjLFE4Orhtn2d)ZHͣiDSZVsV^$RROEY Y@v ZP(\x(oi?t: t5n,"126Nvx<؄F B^g9!3=54m9 IR*;UJEbѝfz&ȱSi5 z6LP($ arjk`lϱgڋZ8>1퍓gq:{/ z]bӆJ*ˊ[P6z6(ɂg=R$`hd @x^b" 8K R\wX$y}Cw{Iàrvb|`Px<~KzPHMU9f‘^EyZB!*/-ZFbD|Dsޱ PIE4:7$M =i:oU%D"Q.1:^h=aNEڱ}]#LT;%j7JKѹ.5Ǔg.а} O| g-IA@`Dã+_e6F$N QlݴHxl(XMo_?zp$Be5mi2@WwݽPYFiqAQofb2@QA^ѣKRQVP$ttt膵^[筨5zP@skc^n4xeA;Im n,/ oYxb쩯CQE"Q^ ecug/K?LT \|"߽HO9>1l(WΞ]=dX  t>t:])˛*b@Q$Xiǀ(9;"Joe4 ɀL3q=K.D盚t9r+saRҏF>+ǸvIfy\LkSBqޝ͡j=|hчnLKWMn>8.^nYob8I$ 3ABѱm]̆Bƭ64H$,.YGJ9X,v`h*-z'{?;z]yN"kl2rW\!ljѨ +8Լ~n.FWQkꇓ']j^tZ %'#MڝBRR^Z)eg: ߍT*;FCV!Ng/^)O8N˙ oH#ШL,RiT*F>w=m#4]µҢHnIeō9Ңu5l) 9MiQu\.jvUH\nχ]nCEsFp9bd-^D"7^Šr`ыS Nl⡃{(e({3'St.R4V)t:F!O*ښs0/P]y`*8(93$Y۬9˸h)!F6mGrssŅXY*im$HPSUli@ >X 6CҎ(@c}]?khDFJ$3ss186wx}eRKahd,m޽^ǁG*ˊg/^NjkKZձ~;2?h|ժUKtX p:/-SRQɸ"Sb1GO(H8l"J*|`?cRYVLEi1RyOVrOD(F\nϓv`бZf-^y$*hЗغ`?0p`Έ2 }5/8{' t:Jciq \L}]-e+/) :7T&MF^įG8{6T6JREMZz2ѹpKSrl,}q]z8ouNz5R(P)ǝNnN9,fEHd䕣'M s98 P(>hY-.'\L-GWd.锢p=c@ce{0d6ftlbxLH9.S #唸&s-vHdކo؄k׻P*l߲ NC[G7ݽ^Gǹl8۬ x)bѰmbDȑ#[^[)|d NƠ).ȣ xB1p7$VH21ulXMYq3Y&u[6RU^žmTs*p@A4+RR.?vsTF\(s3"aLqG:!K%b1y99Yncu_|,~S*4'ɤJTJed$'W W6 z. MQA.?[lLkA,#:[4 |9$?B*|,;w H^(-. '; EH++odoVm'nCUy)*巷l^w~3꒞ԭToG] ͭgH?|[)*ȣ0?.-jHC#cOzԊ[7o@7ܞ__۬b`EzEث.\ːL/.adyi —LݣЖ# ')/-;H^: u۽ [( uY:(-.j}Kp; ŢQ3_ȿZOt!H ۏn&.KvֺI++7T*J(mV/PaIwV6@J{>fqe=D"Q‘Hf'yp~PY^BQ~nʗ^7-t3ҋ9Y?Xt;A<,˙ ;<)H:/,6Eӷ @V$`lPy׋^eph[6QT9R*ШUNsIkg&BV*g ,ٷV"(:aZ&6VWj5v.en͔\ 5U6cLpz}75gF.'hYtG6V\g"h./Bʄl+Ji5/~ mGGg|ڊkE*P_W;|`lXjţrH$ʦ &&y=}aE&" qN2GA^n6B(B&;LMH$D\m? SyyRҸR鹜 }LwLV~wNZ;j[ l`2\Hg1cc7ei_\iQ׮wiS;0 ^M۷l265BG2 Xt:WŬVHK.5 RO$۵nXZK.@ 5#Hł}']k9[\ )?:rP _^y6m,ݜ쬐hrBsNse; k?q '4cA$K#w=QڞRmV9B$bH)բEI0 zvP8⸰I0U'Kia]VR|~exksF(P$Y@$e G?@Ѱu`vB۬ g e mؓߔ~>뻼˻38FIENDB`ukui-panel/plugin-calendar/html/images/zodiac/black/mouse-black.png0000644000175000017500000001357713632320722024300 0ustar fengfengPNG  IHDRh=A_,FIDATx\ip[u>o% N)Q%J$K$vjg2qҴiӬM6iIL2L=63M,I$8VlYB2]$A @\@b!9Q @$3w<>{s//DBaH"4ME 8%yNS\`h:V `fid|e((I>O *, 4E/;EǮ6y׾=]p$IREIQՁs2 l H~Y@ߧgB]0n>.q}gIxve%a Lhκ^e$1!Hͺ󸋞s mp -+x:X<-w;g fj4bɩdKzHT c奞=i1Bۺh =C^;79 Ɔ/lOsm$}UUկ\J/SŁf1Jw /Iu8P,Tb89 ;vwQa#= C?(z!+7)#-S37t(y|hΝ>AF} /޸,4=B1xsA@/Dc?xf>YB9>.k$){U](pvk;X,f"l|n<mV^j66ԟ(88Lgzmૢ(~ⵛL1qꆉw Qr;&A_7!B̆mj<Օ,p@u`/ݸ].0LA._gtḋ]PqC~`G)rݢ( &oI9~[m5K`ϷAmM5\h'+JĈCF7=.]=#,v#^#^0L|:-*t+7a9!߭ Ȳ2ac$} ~W@NFK<~\i顣7 lbqsTW^9 ݏ9{l_BBݠJUv^v7fB1!rIpm ^h.<Ů[ BQUUمK׬SlT[EEQxlUepot DIjT5x_we1lVra쾹AUU[6UU?M(}`,/య}mDZ=Y^}oFyW.QJܤDut]HcY.w "d}y.gx{{\: ߒeej_ Ћ^' gOUeщHDacҪ}q=2bxtkBYh]PUw«DaiN{CA!kA(W3y+ aGjd,7f\` :Cs chG~>~#WO@ 0 yyL<[64eJS17'o($y|Zne@GGNЙ2`|Pwx9Ai#8KTBH'79]uLgE8F#CoЎbz&$ cmAH_0lffC1745[K)4c$G;m'@`RjGv󋋜(JGmEbOUCHIC[WPo/NQ_WC8tRRHilF10S +2^(,9}-yͶݸSA&}UT F8Pm~k1-$qv`~g|bry8Xe[U&<:NfUs˧M]? z`9@lĘ/k #Z2 Bx|F g"wIgͦiUUW^\Uar:Ut͖Dqf+2X Ul^o¿ᘬUvt@t L꤅q sCꊩ_yռc BP?N8lM[kLeh4(tL%`$3^Gy[{Zn`PUD\ؠbYz Fch4}{wecΏF9|q$=j%*-UoZ;ֺ2 w_;ی rIl aa=Qo&X'W TuXymdG>:}HYhi9E.LϕH{cEhszf׷#KNIǘ&SI<$5Z3 ZwZ,gk xeޒo50K:F: o޹8cuџF w$vS(eɧ1OO?`( .Ƈi7;mCQw_AO4E3iג 9Ң'/XT,- %fCs/ F]=0=3K 1~8XTd&g;}ʲt@bUUt$sʲ/w?6IQTaďgCOuto P=LztS.,T8\y i(R2c3՘Ϥ S'gLlk]w bt6h̦ iőC~[9\mn,$'#EŠP˒$_@pvnw;R6떶vxJKu9X7S =P(GelQuǦg\-ttYS9wI.]@lmmۂ ~x?,$a?2QMks]HhCr$af/XbV0M)//Z]=EQǎhOT%t"!L(X[GOكO?qP90l;\r*d78z2 GWHJ'DQHlS\vi+O;ϔzYijL۹ ;~\QӉz'&T;Z8P/,_BH/=mOȭ|dqQaQ0]QYV8vMK謸z7z`_gJRZo](z'&:l89 fYCH0gr$T*޼*$6ŜKh Fu|&VŞ`6jq~ԧ>8HfՒ.% ا/,..C1.7J{*dEQ^i3,{&D=Wouqb Жm:ʵZd+ÞbYXlX N_74ee'e]NU D"qo=,2[MuųrDyWF qj86O^e.24n(ꪏb,棂Ō ц ,˰os)6 oa"paIENDB`ukui-panel/plugin-calendar/html/images/select.png0000644000175000017500000000213313640356061021016 0ustar fengfengPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp .IDATx앱 0@[vũ~`⪣_܄$$P(wr$w1&2Iǡ*CǼ1저̒[CgxNp;|,9aGx Wa 7P}0shhkF U@z!Px!Pl XT[IDATx; 0xc$x=Tl6 E !HSICkC#@mQ|LqC+jВ^CEMhGۀu\&DdD$Er\xc\p)%( 8hq IENDB`ukui-panel/plugin-calendar/html/images/down.png0000644000175000017500000000211013640356061020501 0ustar fengfengPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp >IDATx!0J *O1AEˋYHQUǾ50ٓnNvf]% H@1`-9O>Nq`I?: zSc=՟3"a ȕ0[RTU &A3#DNLa/ %>$P[``'3IENDB`ukui-panel/plugin-calendar/html/images/selected.png0000644000175000017500000000223313640356061021330 0ustar fengfengPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp @ IDATx얿 0[:T TD)}ZG.t?CW$iR R.K/eYZ]F8c  GDc?3{P5wpjTl\TG:^lק ~Wǐ{ nӀOBYקmI(!.3HI(|{XiT& eIDATxM 0+ 6 IDATxb?@&uX̲} NX1 ld-īx7+%@l=d8d (I:fg೜4@#-KlH#H\@dYNj6-'@w8%[!;b%SR˱$:"dmB Q:`#2[OcIENDB`ukui-panel/plugin-calendar/html/images/xiuxi.png0000644000175000017500000000275113635352661020721 0ustar fengfengPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp D7YIDATxW;H`$?$HAt\S⠅N.N""N:  "T8v$: (RQԻ?4iM҃Kir}w]"|on<): J zZE!QSI'1:y"Zi05r9 0Tc0żZJ &j|Z87(yPk@Qr9t66Уw ,.JїJzn6aXt} wg{ 33 H .-F?l$ݞsj0Noo`K +p#)Ẇe&rJ*5;_Y%[Ƶ5)۞jɂ0 R?; lu{}ՊF,flf |H<-w..xyȖ/0`[+ޜ~yiޗp "ˠ!Y°cZ =L\^-g+ab/?:8N $ <9%D0r$h Z#h}(J=Jk=/ 0i:=`XIENDB`ukui-panel/plugin-calendar/html/images/up_hover.png0000644000175000017500000000206613640356061021373 0ustar fengfengPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp IDATxb?@&uF.`f"E`2 jhy(*ur nb $,dZ |T\Giy rh -g,T"GPrBrh>'rBeIv#zE1hxuw@4pIENDB`ukui-panel/plugin-calendar/html/images/down_hover.png0000644000175000017500000000211613640356061021712 0ustar fengfengPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp WIDATxb?@&uXr̲CSNX1 ld-īx7+%@l=d8d (I:fg೜4@#-KlH#H\@dYNj6-'@w8%[!;b%SR˱$:"dmB Q:`#2[qIENDB`ukui-panel/plugin-calendar/html/LunarCalendar.js0000644000175000017500000006610513640356061020646 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0 ? between : lunarYearDays.yearDays - Math.abs(between); var monthDays = lunarYearDays.monthDays; var tempDays = 0; var month = 0; for(var i=0;i end){ month = i; tempDays = tempDays-monthDays[i]; break; } } return [year,month,end - tempDays + 1]; }; /** * 根据距离正月初一的天数计算农历日期 * @param {Number} year 公历年,月,日 */ function getLunarByBetween(year,month,day){ var yearData = lunarInfo[year-minYear]; var zenMonth = yearData[1]; var zenDay = yearData[2]; var between = getDaysBetweenSolar(year,zenMonth-1,zenDay,year,month,day); if(between==0){ //正月初一 return [year,0,1]; }else{ var lunarYear = between>0 ? year : year-1; return getLunarDateByBetween(lunarYear,between); } }; /** * 两个公历日期之间的天数 */ function getDaysBetweenSolar(year,month,day,year1,month1,day1){ var date = new Date(year,month,day).getTime(); var date1 = new Date(year1,month1,day1).getTime(); return (date1-date) / 86400000; }; /** * 计算农历日期离正月初一有多少天 * @param {Number} year,month,day 农年,月(0-12,有闰月),日 */ function getDaysBetweenZheng(year,month,day){ var lunarYearDays = getLunarYearDays(year); var monthDays = lunarYearDays.monthDays; var days = 0; for(var i=0;i maxYear)return {error:100, msg:errorCode[100]}; return { year : year, month : month, day : day }; }; /** * 将农历转换为公历 * @param {Number} year,month,day 农历年,月(1-13,有闰月),日 */ function lunarToSolar(_year,_month,_day){ var inputDate = formateDate(_year,_month,_day); if(inputDate.error)return inputDate; var year = inputDate.year; var month = inputDate.month; var day = inputDate.day; var between = getDaysBetweenZheng(year,month,day); //离正月初一的天数 var yearData = lunarInfo[year-minYear]; var zenMonth = yearData[1]; var zenDay = yearData[2]; var offDate = new Date(year,zenMonth-1,zenDay).getTime() + between * 86400000; offDate = new Date(offDate); return { year : offDate.getFullYear(), month : offDate.getMonth()+1, day : offDate.getDate() }; }; /** * 将公历转换为农历 * @param {Number} year,month,day 公历年,月,日 */ function solarToLunar(_year,_month,_day){ var inputDate = formateDate(_year,_month,_day,minYear); if(inputDate.error)return inputDate; var year = inputDate.year; var month = inputDate.month; var day = inputDate.day; cacheUtil.setCurrent(year); //立春日期 var term2 = cacheUtil.get('term2') ? cacheUtil.get('term2') : cacheUtil.set('term2',getTerm(year,2)); //二十四节气 var termList = cacheUtil.get('termList') ? cacheUtil.get('termList') : cacheUtil.set('termList',getYearTerm(year)); var firstTerm = getTerm(year,month*2); //某月第一个节气开始日期 var GanZhiYear = (month>1 || month==1 && day>=term2) ? year+1 : year;//干支所在年份 var GanZhiMonth = day>=firstTerm ? month+1 : month; //干支所在月份(以节气为界) var lunarDate = getLunarByBetween(year,month,day); var lunarLeapMonth = getLunarLeapYear(lunarDate[0]); var lunarMonthName = ''; if(lunarLeapMonth>0 && lunarLeapMonth==lunarDate[1]){ lunarMonthName = '闰'+DATA.monthCn[lunarDate[1]-1]+'月'; }else if(lunarLeapMonth>0 && lunarDate[1]>lunarLeapMonth){ lunarMonthName = DATA.monthCn[lunarDate[1]-1]+'月'; }else{ lunarMonthName = DATA.monthCn[lunarDate[1]]+'月'; } //农历节日判断 var lunarFtv = ''; var lunarMonthDays = getLunarYearDays(lunarDate[0]).monthDays; //除夕 if(lunarDate[1] == lunarMonthDays.length-1 && lunarDate[2]==lunarMonthDays[lunarMonthDays.length-1]){ lunarFtv = lunarFestival['d0100']; }else if(lunarLeapMonth>0 && lunarDate[1]>lunarLeapMonth){ lunarFtv = lunarFestival[formateDayD4(lunarDate[1]-1,lunarDate[2])]; }else{ lunarFtv = lunarFestival[formateDayD4(lunarDate[1],lunarDate[2])]; } var res = { zodiac : getYearZodiac(GanZhiYear), GanZhiYear : getLunarYearName(GanZhiYear), GanZhiMonth : getLunarMonthName(year,GanZhiMonth), GanZhiDay : getLunarDayName(year,month,day), //放假安排:0无特殊安排,1工作,2放假 worktime : worktime['y'+year] && worktime['y'+year][formateDayD4(month,day)] ? worktime['y'+year][formateDayD4(month,day)] : 0, term : termList[formateDayD4(month,day)], lunarYear : lunarDate[0], lunarMonth : lunarDate[1]+1, lunarDay : lunarDate[2], lunarMonthName : lunarMonthName, lunarDayName : DATA.dateCn[lunarDate[2]-1], lunarLeapMonth : lunarLeapMonth, solarFestival : solarFestival[formateDayD4(month,day)], lunarFestival : lunarFtv }; return res; }; /** * 获取指定公历月份的农历数据 * return res{Object} * @param {Number} year,month 公历年,月 * @param {Boolean} fill 是否用上下月数据补齐首尾空缺,首例数据从周日开始 */ function calendar(_year,_month,fill,mode){ var inputDate = formateDate(_year,_month); if(inputDate.error)return inputDate; var year = inputDate.year; var month = inputDate.month; var calendarData = solarCalendar(year,month+1,fill,mode); for(var i=0;i 0)//每周从周一开始,一号是星期一至星期六,补 n-1天 { preMonthData = creatLenArr(preYear,preMonth+1,res.firstDay -1 ,preMonthDays-(res.firstDay-1)+1); } else//每周从周一开始,一号是星期一至星期六 补6天 { preMonthData = creatLenArr(preYear,preMonth+1,res.firstDay + 6 ,preMonthDays-(res.firstDay + 6)+1); } } res.monthData = preMonthData.concat(res.monthData); } if(7*6 - res.monthData.length!=0){ //后补 var nextYear = month+1>11 ? year+1 : year; var nextMonth = month+1>11 ? 0 : month+1; var fillLen = 7*6 - res.monthData.length; nextMonthData = creatLenArr(nextYear,nextMonth+1,fillLen,1); res.monthData = res.monthData.concat(nextMonthData); } } return res; }; /** * 设置放假安排【对外暴露接口】 * @param {Object} workData */ function setWorktime(workData){ extend(worktime,workData); }; var LunarCalendar = { solarToLunar : solarToLunar, lunarToSolar : lunarToSolar, calendar : calendar, solarCalendar : solarCalendar, setWorktime : setWorktime, getSolarMonthDays : getSolarMonthDays }; if (typeof define === 'function'){ define (function (){ return LunarCalendar; }); }else if(typeof exports === 'object'){ module.exports = LunarCalendar; }else{ window.LunarCalendar = LunarCalendar; }; })(); ukui-panel/plugin-calendar/html/ukui-fr.html0000644000175000017500000000561113633355350020042 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see
lun mar mer jeu ven sam dim
  1. 2015-02-04 星期三
  2. 4
  3. 十一月十四
  4. 甲午年【马年】
  5. 丙子月 庚辰日
ukui-panel/plugin-calendar/html/ukui.css0000644000175000017500000002454413643571462017274 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see div_range.year.x_max || x < div_range.year.x_min || y > div_range.year.y_max || y < div_range.year.y_min) { year_div.className = 'hidden_div'; } } if (month_div.className === 'visible_div') { if (x > div_range.month.x_max || x < div_range.month.x_min || y > div_range.month.y_max || y < div_range.month.y_min ) { month_div.className = 'hidden_div'; } } /* if (holiday_div.className === 'visible_div') { if (x > div_range.holiday.x_max || x < div_range.holiday.x_min || y > div_range.holiday.y_max || y < div_range.holiday.y_min ) { holiday_div.className = 'hidden_div'; } }*/ }); for (var index = year_range['low']; index <= year_range['high']; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); // new year implies new month year_list.appendChild(li); if (index === year) { year_selector.value = index; } } for (var index = 1; index <= 12; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); month_list.appendChild(li); if (index === month + 1) { month_selector.value = index; } } var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low']; month_selector.value = month_offset % 12 === 0 ? 1 : month_offset % 12 + 1; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } /* var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); }*/ // var holiday_button = document.getElementById('holiday_button'); // holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear(); month_selector.value = today.getMonth() + 1; highlight_day = today.getDate(); create_page(today.getFullYear(), today.getMonth() + 1); }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if (index < month_stuff['firstDay'] || index >= month_stuff['firstDay'] + month_stuff['monthDays']) { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; // worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; // worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + ''; if (worktime && current_cell.className !== 'day_other_month') { // current_cell.appendChild(worktime); } } } update_right_pane(year, month, highlight_day); month_stuff = null; } function new_month_selected() { if (this.parentNode.id === 'year_list') { year_selector.value = this.innerHTML; document.getElementById('year_div').className = 'hidden_div'; } else if (this.parentNode.id === 'month_list') { month_selector.value = this.innerHTML; document.getElementById('month_div').className = 'hidden_div'; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_selector') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; } else if (this.id === 'month_selector') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; } /* else if (this.id === 'holiday_button') { div = document.getElementById('holiday_div'); div.style.width = '64px'; div.style.height = '100px'; div_range.holiday.x_min = x; div_range.holiday.x_max = x + width; div_range.holiday.y_min = y; div_range.holiday.y_max = y + height; }*/else { return; } if (div.className === 'hidden_div') { div.className = 'visible_div'; } else { div.className = 'hidden_div'; } div.style.left = x + 'px'; div.style.top = y + height + 'px'; } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true); var general_datetime_list = document.getElementById('general_datetime_list'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } general_datetime_list.children[0].innerHTML = month_str + '-' + day_str + '-' + year + ' ' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = ' '; general_datetime_list.children[3].innerHTML = ' '; general_datetime_list.children[4].innerHTML = ' '; //update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ /*function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year; month_selector.value = month + 'Month'; highlight_day = day; create_page(year, month); month_stuff = null; }*/ ukui-panel/plugin-calendar/resources/0000755000175000017500000000000013632320722016627 5ustar fengfengukui-panel/plugin-calendar/resources/calendar.desktop.in0000644000175000017500000000022013632320722022372 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=calendar Comment=calendar plugin. Icon=clock #TRANSLATIONS_DIR=../translations ukui-panel/plugin-calendar/calendar-button-bg.png0000644000175000017500000000172313632320722020776 0ustar fengfengPNG  IHDR22?tEXtSoftwareAdobe ImageReadyqe<!iTXtXML:com.adobe.xmp EHIDATx1 緅 $"""""""""""""""""""""""""""""""""""""7V#a)IENDB`ukui-panel/plugin-calendar/style/0000755000175000017500000000000013633355350015763 5ustar fengfengukui-panel/plugin-calendar/style/indicators.css0000644000175000017500000000245413633355350020641 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include "../panel/iukuipanelplugin.h" namespace Ui { class UkuiWebviewDialog; } class UkuiWebviewDialog : public QDialog { Q_OBJECT public: explicit UkuiWebviewDialog(QWidget *parent = nullptr); ~UkuiWebviewDialog(); void creatwebview(); void showinfo(QString string); QWebView *webview(){return mWebView;} Q_SIGNALS: void deactivated(); private: Ui::UkuiWebviewDialog *ui; QWebView *mWebView; QSize mQsize; protected: virtual bool event(QEvent *event); }; #endif // UKUIWEBVIEWDIALOG_H ukui-panel/plugin-calendar/ukuicalendar.h0000644000175000017500000000764613643625333017462 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012-2013 Razor team * Authors: * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include #include #include #include #include #include "../panel/common/ukuirotatedwidget.h" #include "../panel/iukuipanelplugin.h" #include "ukuiwebviewdialog.h" #include "../panel/popupmenu.h" class QTimer; class CalendarActiveLabel; class UkuiCalendarWebView; class IndicatorCalendar : public QWidget, public IUKUIPanelPlugin { Q_OBJECT public: IndicatorCalendar(const IUKUIPanelPluginStartupInfo &startupInfo); ~IndicatorCalendar(); virtual QWidget *widget() { return mMainWidget; } virtual QString themeId() const { return QLatin1String("Calendar"); } // virtual IUKUIPanelPlugin::Flags flags() const { return PreferRightAlignment | HaveConfigDialog ; } bool isSeparate() const { return true; } void activated(ActivationReason reason); void settingsChanged()override; void realign()override; void initializeCalendar(); void setbackground(); void setTimeShowStyle(); //signals: Q_SIGNALS: void deactivated(); private Q_SLOTS: void timeout(); void wheelScrolled(int); void deletePopup(); void updateTimeText(); void hidewebview(); private: QWidget *mMainWidget; UkuiWebviewDialog *mWebViewDiag; UKUi::RotatedWidget* mRotatedWidget; bool mbActived; bool mbHasCreatedWebView; CalendarActiveLabel *mContent; QTimer *mTimer; int mUpdateInterval; int16_t mViewWidht; int16_t mViewHeight; QStringList mTimeZones; QMap mTimeZoneCustomNames; QString mDefaultTimeZone; QString mActiveTimeZone; QString mFormat; bool mAutoRotate; QLabel *mPopupContent; QDateTime mShownTime; void restartTimer(); void setTimeText(); QString formatDateTime(const QDateTime &datetime, const QString &timeZoneName); void updatePopupContent(); bool formatHasTimeZone(QString format); QString preformat(const QDateTime &dateTime,const QString &format, const QTimeZone &timeZone); bool mbIsNeedUpdate; QGSettings *gsettings; QString hourSystemMode; }; class CalendarActiveLabel : public QLabel { Q_OBJECT public: explicit CalendarActiveLabel(IUKUIPanelPlugin *plugin,QWidget * = NULL); Q_SIGNALS: void wheelScrolled(int); void leftMouseButtonClicked(); void middleMouseButtonClicked(); protected: void wheelEvent(QWheelEvent *); void mouseReleaseEvent(QMouseEvent* event); virtual void contextMenuEvent(QContextMenuEvent *event); private Q_SLOTS: void setControlTime(); //void setUpPanel(); private: IUKUIPanelPlugin * mPlugin; }; class UKUICalendarPluginLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new IndicatorCalendar(startupInfo); } }; ukui-panel/plugin-calendar/ukuicalendar.cpp0000644000175000017500000011036613643625333020007 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012-2013 Razor team * Authors: * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuicalendar.h" #include #include #include #include #include #include #include #include #include #include #include "../panel/pluginsettings.h" #include #include #include #include #include #include #define CALENDAR_HEIGHT (40) #define CALENDAR_WIDTH (104) #define WEBVIEW_WIDTH (454) #define WEBVIEW_MAX_HEIGHT (704) #define WEBVIEW_MIN_HEIGHT (600) #define HOUR_SYSTEM_CONTROL "org.ukui.control-center.panel.plugins" #define HOUR_SYSTEM_24_Horizontal "hh:mm ddd yyyy/MM/dd" #define HOUR_SYSTEM_24_Vertical "hh:mm ddd MM/dd" #define HOUR_SYSTEM_12_Horizontal "Ahh:mm ddd yyyy/MM/dd" #define HOUR_SYSTEM_12_Vertical "Ahh:mm ddd MM/dd" #define HOUR_SYSTEM_KEY "hoursystem" IndicatorCalendar::IndicatorCalendar(const IUKUIPanelPluginStartupInfo &startupInfo): QWidget(), IUKUIPanelPlugin(startupInfo), mTimer(new QTimer(this)), mUpdateInterval(1), mAutoRotate(true), mbActived(false), mbIsNeedUpdate(false), mbHasCreatedWebView(false), mViewWidht(WEBVIEW_WIDTH), mViewHeight(0), mPopupContent(NULL), mWebViewDiag(NULL) { mMainWidget = new QWidget(); mContent = new CalendarActiveLabel(this); mWebViewDiag = new UkuiWebviewDialog; mRotatedWidget = new UKUi::RotatedWidget(*mContent, mMainWidget); mRotatedWidget->setTransferWheelEvent(true); QVBoxLayout *borderLayout = new QVBoxLayout(mMainWidget); borderLayout->setContentsMargins(0, 0, 0, 0); borderLayout->setSpacing(0); borderLayout->addWidget(mRotatedWidget, 0, Qt::AlignCenter); mContent->setObjectName(QLatin1String("WorldClockContent")); mContent->setAlignment(Qt::AlignCenter); settingsChanged(); initializeCalendar(); mTimer->setTimerType(Qt::PreciseTimer); connect(mTimer, SIGNAL(timeout()), SLOT(timeout())); connect(mContent, SIGNAL(wheelScrolled(int)), SLOT(wheelScrolled(int))); connect(mWebViewDiag, SIGNAL(deactivated()), SLOT(hidewebview())); const QByteArray id(HOUR_SYSTEM_CONTROL); if(QGSettings::isSchemaInstalled(id)) { gsettings = new QGSettings(id); connect(gsettings, &QGSettings::changed, this, [=] (const QString &key) { if (key == HOUR_SYSTEM_KEY) { if(gsettings->keys().contains("hoursystem")) { hourSystemMode=gsettings->get("hoursystem").toString(); } else hourSystemMode=24; } else if(key == "calendar") { mbHasCreatedWebView = false; initializeCalendar(); } else if(key == "firstday") { qDebug()<<"key == firstday"; mbHasCreatedWebView = false; initializeCalendar(); } }); } setTimeShowStyle(); mContent->setStyleSheet( //正常状态样式 "QLabel{" /*"background-color:rgba(100,225,100,80%);"//背景色(也可以设置图片)*/ "border-width:0px;" //边框宽度像素 "border-radius:6px;" //边框圆角半径像素 "color:rgba(255,255,255,100%);" //字体颜色 "padding:0px;" //填衬 "textalignment:aligncenter" //文本居中 "}" //鼠标悬停样式 "QLabel:hover{" "background-color:rgba(190,216,239,20%);" "}" //鼠标按下样式 "QLabel:pressed{" "background-color:rgba(190,216,239,12%);" "}" ); mContent->setWordWrap(true); } IndicatorCalendar::~IndicatorCalendar() { if(mMainWidget != NULL) { mMainWidget->deleteLater(); } if(mWebViewDiag != NULL) { mWebViewDiag->deleteLater(); } if(mRotatedWidget != NULL) { mRotatedWidget->deleteLater(); } if(mContent != NULL) { mContent->deleteLater(); } if(mPopupContent != NULL) { mPopupContent->deleteLater(); } } void IndicatorCalendar::timeout() { if (QDateTime{}.time().msec() > 500) restartTimer(); updateTimeText(); } void IndicatorCalendar::updateTimeText() { QDateTime now = QDateTime::currentDateTime(); QString timeZoneName = mActiveTimeZone; if (timeZoneName == QLatin1String("local")) timeZoneName = QString::fromLatin1(QTimeZone::systemTimeZoneId()); QTimeZone timeZone(timeZoneName.toLatin1()); QDateTime tzNow = now.toTimeZone(timeZone); bool isUpToDate(true); if (!mShownTime.isValid()) // first time or forced update { isUpToDate = false; if (mUpdateInterval < 60000) mShownTime = tzNow.addSecs(-tzNow.time().msec()); // s else if (mUpdateInterval < 3600000) mShownTime = tzNow.addSecs(-tzNow.time().second()); // m else mShownTime = tzNow.addSecs(-tzNow.time().minute() * 60 - tzNow.time().second()); // h } else { qint64 diff = mShownTime.secsTo(tzNow); if (mUpdateInterval < 60000) { if (diff < 0 || diff >= 1) { isUpToDate = false; mShownTime = tzNow.addSecs(-tzNow.time().msec()); } } else if (mUpdateInterval < 3600000) { if (diff < 0 || diff >= 60) { isUpToDate = false; mShownTime = tzNow.addSecs(-tzNow.time().second()); } } else if (diff < 0 || diff >= 3600) { isUpToDate = false; mShownTime = tzNow.addSecs(-tzNow.time().minute() * 60 - tzNow.time().second()); } } // if (!isUpToDate || mbIsNeedUpdate) // { const QSize old_size = mContent->sizeHint(); QString str; const QByteArray id(HOUR_SYSTEM_CONTROL); if(QGSettings::isSchemaInstalled(id)) { gsettings = new QGSettings(id); QStringList keys = gsettings->keys(); if(keys.contains("hoursystem")){ hourSystemMode=gsettings->get("hoursystem").toString(); } if(!gsettings) { qDebug()<<"gsettings get error :"; return; } if(!QString::compare("24",hourSystemMode)) { if(panel()->isHorizontal()) { str=tzNow.toString(HOUR_SYSTEM_24_Horizontal); // str=tzNow.toString(HOUR_SYSTEM_24_Horizontal); } else { str=tzNow.toString(HOUR_SYSTEM_24_Vertical); } } else { if(panel()->isHorizontal()) { str=tzNow.toString(HOUR_SYSTEM_12_Horizontal); } else { str = tzNow.toString(HOUR_SYSTEM_12_Vertical); str.replace("AM","AM "); str.replace("PM","PM "); } } // if(QLocale::system().name() == "zh_CN") // { // str.replace("-","/"); // str.replace("星期","周"); // str.remove("/上午"); // str.remove("/下午"); // mContent->setText(str); // } // else // { // mContent->setText(tzNow.toString("Ahh:mm ddd yyyy/MM/dd")); // } mContent->setText(str); if (old_size != mContent->sizeHint()) { mRotatedWidget->adjustContentSize(); } mRotatedWidget->update(); updatePopupContent(); mbIsNeedUpdate = false; } } void IndicatorCalendar::setTimeText() { mShownTime = QDateTime(); // force an update updateTimeText(); } void IndicatorCalendar::restartTimer() { mTimer->stop(); // check the time every second even if the clock doesn't show seconds // because otherwise, the shown time might be vey wrong after resume mTimer->setInterval(1000); int delay = static_cast(1000 - (static_cast(QTime::currentTime().msecsSinceStartOfDay()) % 1000)); QTimer::singleShot(delay, Qt::PreciseTimer, this, &IndicatorCalendar::updateTimeText); QTimer::singleShot(delay, Qt::PreciseTimer, mTimer, SLOT(start())); } void IndicatorCalendar::settingsChanged() { PluginSettings *_settings = settings(); QString oldFormat = mFormat; mTimeZones.clear(); QList > array = _settings->readArray(QLatin1String("timeZones")); for (const auto &map : array) { QString timeZoneName = map.value(QLatin1String("timeZone"), QString()).toString(); mTimeZones.append(timeZoneName); mTimeZoneCustomNames[timeZoneName] = map.value(QLatin1String("customName"), QString()).toString(); } if (mTimeZones.isEmpty()) mTimeZones.append(QLatin1String("local")); mDefaultTimeZone = _settings->value(QLatin1String("defaultTimeZone"), QString()).toString(); if (mDefaultTimeZone.isEmpty()) mDefaultTimeZone = mTimeZones[0]; mActiveTimeZone = mDefaultTimeZone; bool longTimeFormatSelected = false; QString formatType = _settings->value(QLatin1String("formatType"), QString()).toString(); QString dateFormatType = _settings->value(QLatin1String("dateFormatType"), QString()).toString(); bool advancedManual = _settings->value(QLatin1String("useAdvancedManualFormat"), false).toBool(); // backward compatibility if (formatType == QLatin1String("custom")) { formatType = QLatin1String("short-timeonly"); dateFormatType = QLatin1String("short"); advancedManual = true; } else if (formatType == QLatin1String("short")) { formatType = QLatin1String("short-timeonly"); dateFormatType = QLatin1String("short"); advancedManual = false; } else if ((formatType == QLatin1String("full")) || (formatType == QLatin1String("long")) || (formatType == QLatin1String("medium"))) { formatType = QLatin1String("long-timeonly"); dateFormatType = QLatin1String("long"); advancedManual = false; } if (formatType == QLatin1String("long-timeonly")) longTimeFormatSelected = true; bool timeShowSeconds = _settings->value(QLatin1String("timeShowSeconds"), false).toBool(); bool timePadHour = _settings->value(QLatin1String("timePadHour"), false).toBool(); bool timeAMPM = _settings->value(QLatin1String("timeAMPM"), false).toBool(); // timezone bool showTimezone = _settings->value(QLatin1String("showTimezone"), false).toBool() && !longTimeFormatSelected; QString timezonePosition = _settings->value(QLatin1String("timezonePosition"), QString()).toString(); QString timezoneFormatType = _settings->value(QLatin1String("timezoneFormatType"), QString()).toString(); // date bool showDate = _settings->value(QLatin1String("showDate"), false).toBool(); QString datePosition = _settings->value(QLatin1String("datePosition"), QString()).toString(); bool dateShowYear = _settings->value(QLatin1String("dateShowYear"), false).toBool(); bool dateShowDoW = _settings->value(QLatin1String("dateShowDoW"), false).toBool(); bool datePadDay = _settings->value(QLatin1String("datePadDay"), false).toBool(); bool dateLongNames = _settings->value(QLatin1String("dateLongNames"), false).toBool(); // advanced QString customFormat = _settings->value(QLatin1String("customFormat"), tr("''HH:mm:ss'
'ddd, d MMM yyyy'
'TT'
'")).toString(); if (advancedManual) mFormat = customFormat; else { QLocale locale = QLocale(QLocale::AnyLanguage, QLocale().country()); if (formatType == QLatin1String("short-timeonly")) mFormat = locale.timeFormat(QLocale::ShortFormat); else if (formatType == QLatin1String("long-timeonly")) mFormat = locale.timeFormat(QLocale::LongFormat); else // if (formatType == QLatin1String("custom-timeonly")) mFormat = QString(QLatin1String("%1:mm%2%3")).arg(timePadHour ? QLatin1String("hh") : QLatin1String("h")).arg(timeShowSeconds ? QLatin1String(":ss") : QLatin1String("")).arg(timeAMPM ? QLatin1String(" A") : QLatin1String("")); if (showTimezone) { QString timezonePortion; if (timezoneFormatType == QLatin1String("short")) timezonePortion = QLatin1String("TTTT"); else if (timezoneFormatType == QLatin1String("long")) timezonePortion = QLatin1String("TTTTT"); else if (timezoneFormatType == QLatin1String("offset")) timezonePortion = QLatin1String("T"); else if (timezoneFormatType == QLatin1String("abbreviation")) timezonePortion = QLatin1String("TTT"); else if (timezoneFormatType == QLatin1String("iana")) timezonePortion = QLatin1String("TT"); else // if (timezoneFormatType == QLatin1String("custom")) timezonePortion = QLatin1String("TTTTTT"); if (timezonePosition == QLatin1String("below")) mFormat = mFormat + QLatin1String("'
'") + timezonePortion; else if (timezonePosition == QLatin1String("above")) mFormat = timezonePortion + QLatin1String("'
'") + mFormat; else if (timezonePosition == QLatin1String("before")) mFormat = timezonePortion + QLatin1String(" ") + mFormat; else // if (timezonePosition == QLatin1String("after")) mFormat = mFormat + QLatin1String(" ") + timezonePortion; } QString datePortion; if (dateFormatType == QLatin1String("short")) datePortion = locale.dateFormat(QLocale::ShortFormat); else if (dateFormatType == QLatin1String("long")) datePortion = locale.dateFormat(QLocale::LongFormat); else if (dateFormatType == QLatin1String("iso")) datePortion = QLatin1String("yyyy-MM-dd"); else // if (dateFormatType == QLatin1String("custom")) { QString datePortionOrder; QString dateLocale = locale.dateFormat(QLocale::ShortFormat).toLower(); int yearIndex = dateLocale.indexOf("y"); int monthIndex = dateLocale.indexOf("m"); int dayIndex = dateLocale.indexOf("d"); if (yearIndex < dayIndex) // Big-endian (year, month, day) (yyyy MMMM dd, dddd) -> in some Asia countires like China or Japan datePortionOrder = QLatin1String("%1%2%3 %4%5%6"); else if (monthIndex < dayIndex) // Middle-endian (month, day, year) (dddd, MMMM dd yyyy) -> USA datePortionOrder = QLatin1String("%6%5%3 %4%2%1"); else // Little-endian (day, month, year) (dddd, dd MMMM yyyy) -> most of Europe datePortionOrder = QLatin1String("%6%5%4 %3%2%1"); datePortion = datePortionOrder.arg(dateShowYear ? QLatin1String("yyyy") : QLatin1String("")).arg(dateShowYear ? QLatin1String(" ") : QLatin1String("")).arg(dateLongNames ? QLatin1String("MMMM") : QLatin1String("MMM")).arg(datePadDay ? QLatin1String("dd") : QLatin1String("d")).arg(dateShowDoW ? QLatin1String(", ") : QLatin1String("")).arg(dateShowDoW ? (dateLongNames ? QLatin1String("dddd") : QLatin1String("ddd")) : QLatin1String("")); } //mFormat = datePortion + QLatin1String(" ") + mFormat;//date show before time mFormat = mFormat + QLatin1String(" ") + datePortion;//date show before time } if ((oldFormat != mFormat)) { int update_interval; QString format = mFormat; format.replace(QRegExp(QLatin1String("'[^']*'")), QString()); //don't support updating on milisecond basis -> big performance hit if (format.contains(QLatin1String("s"))) update_interval = 1000; else if (format.contains(QLatin1String("m"))) update_interval = 60000; else update_interval = 3600000; if (update_interval != mUpdateInterval) { mUpdateInterval = update_interval; restartTimer(); } } bool autoRotate = settings()->value(QLatin1String("autoRotate"), true).toBool(); if (autoRotate != mAutoRotate) { mAutoRotate = autoRotate; realign(); } setTimeText(); } void IndicatorCalendar::wheelScrolled(int delta) { if (mTimeZones.count() > 1) { mActiveTimeZone = mTimeZones[(mTimeZones.indexOf(mActiveTimeZone) + ((delta > 0) ? -1 : 1) + mTimeZones.size()) % mTimeZones.size()]; setTimeText(); } } /*when widget is loading need initialize here*/ void IndicatorCalendar::initializeCalendar() { QByteArray id(HOUR_SYSTEM_CONTROL); CalendarShowMode showCalendar = defaultMode; QString lunarOrsolar; QString firstDay; if(QGSettings::isSchemaInstalled(id)) { // if(gsettings) // { // gsettings->deleteLater(); // } // gsettings = new QGSettings(id); if(!gsettings) { qDebug()<<"get gsetting error!!!"; return; } if(gsettings->keys().contains("calendar")) { lunarOrsolar= gsettings->get("calendar").toString(); } if(gsettings->keys().contains("firstday")) { firstDay= gsettings->get("firstday").toString(); } qDebug()<<"QLocale::system().name():"<creatwebview(showCalendar); mbHasCreatedWebView = true; } } } void IndicatorCalendar::activated(ActivationReason reason) { if(mWebViewDiag != NULL ) { // QString htmlFilePath = QLatin1String(PACKAGE_DATA_DIR); // htmlFilePath = QLatin1String("file://") + htmlFilePath + QLatin1String("/plugin-calendar/html/ukui.html"); mWebViewDiag->setGeometry(calculatePopupWindowPos(QSize(mViewWidht,mViewHeight))); mWebViewDiag->show(); setbackground(); if(!mbActived) { mWebViewDiag->setHidden(false); mbActived = true; } else { mWebViewDiag->setHidden(true); mWebViewDiag->webview()->reload(); mbActived = false; } } } void IndicatorCalendar::deletePopup() { mPopupContent = NULL; } void IndicatorCalendar::hidewebview() { mWebViewDiag->setHidden(true); mbActived = false; mWebViewDiag->webview()->reload(); } QString IndicatorCalendar::formatDateTime(const QDateTime &datetime, const QString &timeZoneName) { QTimeZone timeZone(timeZoneName.toLatin1()); QDateTime tzNow = datetime.toTimeZone(timeZone); return tzNow.toString(preformat(tzNow,mFormat, timeZone)); } void IndicatorCalendar::updatePopupContent() { if (mPopupContent) { QDateTime now = QDateTime::currentDateTime(); QStringList allTimeZones; bool hasTimeZone = formatHasTimeZone(mFormat); for (QString timeZoneName : qAsConst(mTimeZones)) { if (timeZoneName == QLatin1String("local")) timeZoneName = QString::fromLatin1(QTimeZone::systemTimeZoneId()); QString formatted = formatDateTime(now, timeZoneName); if (!hasTimeZone) formatted += QLatin1String("
") + QString::fromLatin1(QTimeZone(timeZoneName.toLatin1()).id()); allTimeZones.append(formatted); } mPopupContent->setText(allTimeZones.join(QLatin1String("
"))); } } bool IndicatorCalendar::formatHasTimeZone(QString format) { format.replace(QRegExp(QLatin1String("'[^']*'")), QString()); return format.toLower().contains(QLatin1String("t")); } QString IndicatorCalendar::preformat(const QDateTime &dateTime,const QString &format, const QTimeZone &timeZone ) { QString result = format; int from = 0; for (;;) { int apos = result.indexOf(QLatin1Char('\''), from); int tz = result.indexOf(QLatin1Char('T'), from); if ((apos != -1) && (tz != -1)) { if (apos > tz) apos = -1; else tz = -1; } if (apos != -1) { from = apos + 1; apos = result.indexOf(QLatin1Char('\''), from); if (apos == -1) // misformat break; from = apos + 1; } else if (tz != -1) { int length = 1; for (; result[tz + length] == QLatin1Char('T'); ++length); if (length > 6) length = 6; QString replacement; switch (length) { case 1: replacement = timeZone.displayName(dateTime, QTimeZone::OffsetName); if (replacement.startsWith(QLatin1String("UTC"))) replacement = replacement.mid(3); qDebug()<<"case 1 replacement = "<webview()->page()->mainFrame()->evaluateJavaScript(str); } CalendarActiveLabel::CalendarActiveLabel(IUKUIPanelPlugin *plugin, QWidget *parent) : QLabel(parent), mPlugin(plugin) { } void CalendarActiveLabel::wheelEvent(QWheelEvent *event) { Q_EMIT wheelScrolled(event->delta()); QLabel::wheelEvent(event); } void CalendarActiveLabel::mouseReleaseEvent(QMouseEvent* event) { switch (event->button()) { case Qt::LeftButton: Q_EMIT leftMouseButtonClicked(); break; case Qt::MidButton: Q_EMIT middleMouseButtonClicked(); break; default:; } QLabel::mouseReleaseEvent(event); } void CalendarActiveLabel::contextMenuEvent(QContextMenuEvent *event) { PopupMenu *menuCalender=new PopupMenu(this); menuCalender->setAttribute(Qt::WA_DeleteOnClose); menuCalender->addAction(QIcon::fromTheme("document-page-setup"), tr("Time and Date Setting"), this, SLOT(setControlTime()) ); /* menuCalender->addAction(QIcon::fromTheme("document-page-setup"), tr("Config panel"), this, SLOT(setUpPanel()) ); */ menuCalender->setGeometry(mPlugin->panel()->calculatePopupWindowPos(mapToGlobal(event->pos()), menuCalender->sizeHint())); menuCalender->show(); } void CalendarActiveLabel::setControlTime() { system("ukui-control-center"); } /* void CalendarActiveLabel::setUpPanel() { system("ukui-control-center -d"); } */ ukui-panel/plugin-calendar/ukuiwebviewdialog.ui0000644000175000017500000000055213632320722020704 0ustar fengfeng UkuiWebviewDialog 0 0 400 300 Dialog ukui-panel/plugin-calendar/CMakeLists.txt0000644000175000017500000000140513635352661017367 0ustar fengfeng set(PLUGIN "calendar") set(HEADERS ukuicalendar.h ukuiwebviewdialog.h ) set(SOURCES ukuicalendar.cpp ukuiwebviewdialog.cpp ) set(UIS ukuiwebviewdialog.ui ) find_package(Qt5WebKit) find_package(Qt5WebKitWidgets) find_package(PkgConfig) pkg_check_modules(Gsetting REQUIRED gsettings-qt) pkg_check_modules(CALENDAR_DEPS REQUIRED glib-2.0) include_directories(${CALENDAR_DEPS_INCLUDE_DIRS}) include_directories(${Gsetting_INCLUDE_DIRS}) ADD_DEFINITIONS(-DQT_NO_KEYWORDS) link_libraries(libQt5WebKitWidgets.so.5 libQt5WebKit.so.5 glib-2.0.so) install(DIRECTORY html/ DESTINATION ${PACKAGE_DATA_DIR}/plugin-calendar/html) install(DIRECTORY style/ DESTINATION ${PACKAGE_DATA_DIR}/plugin-calendar/style) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel/plugin-showdesktop/0000755000175000017500000000000013633072617015426 5ustar fengfengukui-panel/plugin-showdesktop/resources/0000755000175000017500000000000013632320722017430 5ustar fengfengukui-panel/plugin-showdesktop/resources/showdesktop.desktop.in0000644000175000017500000000026413632320722024004 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Show desktop Comment=Minimize all windows and show the desktop Icon=user-desktop #TRANSLATIONS_DIR=../translations ukui-panel/plugin-showdesktop/CMakeLists.txt0000644000175000017500000000025113632320722020154 0ustar fengfengset(PLUGIN "showdesktop") set(HEADERS showdesktop.h ) set(SOURCES showdesktop.cpp ) set(LIBRARIES ${LIBRARIES} Qt5Xdg ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel/plugin-showdesktop/showdesktop.cpp0000644000175000017500000000662513632320722020505 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include #include //#include #include "xdgicon.h" //#include #include "../panel/common/ukuinotification.h" #include #include #include "showdesktop.h" #include "../panel/pluginsettings.h" #define DEFAULT_SHORTCUT "Control+Alt+D" #define DESKTOP_HEIGHT (12) #define DESKTOP_WIDTH (40) ShowDesktop::ShowDesktop(const IUKUIPanelPluginStartupInfo &startupInfo) : QObject(), IUKUIPanelPlugin(startupInfo) { QAction * act = new QAction(XdgIcon::fromTheme("ukui-icon-theme-one"), tr(""), this); connect(act, SIGNAL(triggered()), this, SLOT(toggleShowingDesktop())); mButton.setDefaultAction(act); mButton.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); mButton.setAutoRaise(true); realign(); } void ShowDesktop::realign() { if(panel()->isHorizontal()) { mButton.setFixedSize(DESKTOP_HEIGHT,panel()->panelSize()); mButton.setStyleSheet( //正常状态样式 "QToolButton{" "background-color:rgba(190,216,239,10%);" //背景色(也可以设置图片) "qproperty-iconSize:40px 40px;" "border-style:outset;" //边框样式(inset/outset) "border-width:0px;" //边框宽度像素 "border-radius:0px;" //边框圆角半径像素 "border-color:rgba(255,255,255,30);" //边框颜色 "font:SimSun 14px;" //字体,字体大小 "color:rgba(0,0,0,100);" //字体颜色 "padding:0px;" //填衬 "border-bottom-style:solid" "}" //鼠标悬停样式 "QToolButton:hover{" "background-color:rgba(190,216,239,20%);" "}" //鼠标按下样式 "QToolButton:pressed{" "background-color:rgba(190,216,239,12%);" "}" ); } else { mButton.setFixedSize(DESKTOP_WIDTH,DESKTOP_HEIGHT); } } void ShowDesktop::toggleShowingDesktop() { KWindowSystem::setShowingDesktop(!KWindowSystem::showingDesktop()); } #undef DEFAULT_SHORTCUT ukui-panel/plugin-showdesktop/showdesktop.h0000644000175000017500000000346313632320722020147 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef SHOWDESKTOP_H #define SHOWDESKTOP_H #include "../panel/iukuipanelplugin.h" #include class ShowDesktop : public QObject, public IUKUIPanelPlugin { Q_OBJECT public: ShowDesktop(const IUKUIPanelPluginStartupInfo &startupInfo); virtual QWidget *widget() { return &mButton; } virtual QString themeId() const { return "ShowDesktop"; } void realign()override; private slots: void toggleShowingDesktop(); private: QToolButton mButton; }; class ShowDesktopLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new ShowDesktop(startupInfo); } }; #endif ukui-panel/plugin-startmenu/0000755000175000017500000000000013643551442015075 5ustar fengfengukui-panel/plugin-startmenu/img/0000755000175000017500000000000013643633716015656 5ustar fengfengukui-panel/plugin-startmenu/img/startmenu.svg0000644000175000017500000001347013632320722020412 0ustar fengfeng ukui-panel/plugin-startmenu/img/quicklaunch_zh_CN.qm0000644000175000017500000000102213632320722021564 0ustar fengfeng Drop ErrorUKUIQuickLaunchyR^u(z ^VhkdDrop application icons hereUKUIQuickLaunch0eN/URL '%1' feelՈ]LQeR0_T/R9File/URL '%1' cannot be embedded into QuickLaunch for nowUKUIQuickLaunchukui-panel/plugin-startmenu/img/taskview.svg0000644000175000017500000000130213632320722020214 0ustar fengfeng ukui-panel/plugin-startmenu/img/ukui-panel_zh_CN.qm0000644000175000017500000000267113632320722021342 0ustar fengfengy:hLb Show Desktop UKUIPanel |~vщVhShow System Monitor UKUIPanel f>y:NRV Show Taskview UKUIPanelMneNConfiguration filemainukui-panel/plugin-startmenu/resources/0000755000175000017500000000000013632320722017100 5ustar fengfengukui-panel/plugin-startmenu/resources/startmenu.desktop.in0000644000175000017500000000023413632320722023121 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Start Menu Comment=Get the start menu under the cursor. For web developers. Icon=start-menu ukui-panel/plugin-startmenu/startmenu.cpp0000644000175000017500000001031413643551442017622 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include "../panel/customstyle.h" UKUIStartMenuPlugin::UKUIStartMenuPlugin(const IUKUIPanelPluginStartupInfo &startupInfo): QObject(), IUKUIPanelPlugin(startupInfo), mWidget(new UKUIStartMenuButton(this)) { } UKUIStartMenuPlugin::~UKUIStartMenuPlugin() { delete mWidget; } QWidget *UKUIStartMenuPlugin::widget() { return mWidget; } void UKUIStartMenuPlugin::realign() { mWidget->realign(); } UKUIStartMenuButton::UKUIStartMenuButton( IUKUIPanelPlugin *plugin, QWidget* parent ): QToolButton(parent), mPlugin(plugin) { this->setIcon(QIcon("/usr/share/ukui-panel/panel/img/startmenu.svg")); this->setStyle(new CustomStyle()); } UKUIStartMenuButton::~UKUIStartMenuButton() { } void UKUIStartMenuButton::realign() { if (mPlugin->panel()->isHorizontal()) this->setFixedSize(mPlugin->panel()->panelSize(),mPlugin->panel()->panelSize()); else this->setFixedSize(mPlugin->panel()->panelSize(),mPlugin->panel()->panelSize()); this->setIconSize(QSize(mPlugin->panel()->iconSize(),mPlugin->panel()->iconSize())); } void UKUIStartMenuButton::mousePressEvent(QMouseEvent* event) { const Qt::MouseButton b = event->button(); if (Qt::LeftButton == b) { if(QFileInfo::exists(QString("/usr/bin/ukui-menu"))) { QProcess *process =new QProcess(this); process->startDetached("/usr/bin/ukui-menu"); } else{qDebug()<<"not find /usr/bin/ukui-start-menu"<setAttribute(Qt::WA_DeleteOnClose); rightPressMenu->addAction(XdgIcon::fromTheme(QLatin1String("system-lock-screen")), tr("Lock Screen"), this, SLOT(ScreenServer()) ); rightPressMenu->addAction(XdgIcon::fromTheme(QLatin1String("stock-people")), tr("Switch User"), this, SLOT(SessionSwitch()) ); rightPressMenu->addAction(XdgIcon::fromTheme(QLatin1String("system-logout")), tr("LogOut"), this, SLOT(SessionLogout()) ); rightPressMenu->addAction(XdgIcon::fromTheme(QLatin1String("system-restart")), tr("Restart"), this, SLOT(SessionReboot()) ); rightPressMenu->addAction(XdgIcon::fromTheme(QLatin1String("exit")), tr("Power Off"), this, SLOT(SessionShutdown()) ); rightPressMenu->setGeometry(mPlugin->panel()->calculatePopupWindowPos(mapToGlobal(event->pos()), rightPressMenu->sizeHint())); rightPressMenu->show(); } void UKUIStartMenuButton::ScreenServer() { system("ukui-screensaver-command -l"); } void UKUIStartMenuButton::SessionSwitch() { QProcess::startDetached(QString("ukui-session-tools --switchuser")); } void UKUIStartMenuButton::SessionLogout() { system("ukui-session-tools --logout"); } void UKUIStartMenuButton::SessionReboot() { system("ukui-session-tools --reboot"); } void UKUIStartMenuButton::SessionShutdown() { system("ukui-session-tools --shutdown"); } ukui-panel/plugin-startmenu/CMakeLists.txt0000644000175000017500000000070313632320722017626 0ustar fengfengset(PLUGIN "startmenu") set(HEADERS startmenu.h ) set(SOURCES startmenu.cpp ) set(UIS ) set(LIBRARIES Qt5Xdg ) install(FILES img/startmenu.svg img/taskview.svg DESTINATION "${PACKAGE_DATA_DIR}/plugin-startmenu/img" COMPONENT Runtime ) set(UKUI_TRANSLATIONS_DAT "/usr/local/share/") file(GLOB UKUI_TRANSLATIONS_SOURCE ${UKUI_TRANSLATIONS_DAT}ukui/translations/ukui-panel/ukui-panel_zh_CN.qm ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel/plugin-startmenu/startmenu.h0000644000175000017500000000514413643551442017274 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include "../panel/plugin.h" #include "../panel/ukuipanel.h" #include "../panel/config/configpanelwidget.h" #include <../panel/popupmenu.h> #include "../panel/iukuipanelplugin.h" #include #include class UKUIStartMenuButton; class UKUIStartMenuPlugin: public QObject, public IUKUIPanelPlugin { Q_OBJECT public: explicit UKUIStartMenuPlugin(const IUKUIPanelPluginStartupInfo &startupInfo); ~UKUIStartMenuPlugin(); virtual QWidget *widget(); virtual QString themeId() const { return "StartMenu"; } virtual Flags flags() const { return NeedsHandle; } void realign(); bool isSeparate() const { return true; } private: UKUIStartMenuButton *mWidget; }; class StartMenuLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *mPlugin; IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new UKUIStartMenuPlugin(startupInfo); } }; class UKUIStartMenuButton:public QToolButton { Q_OBJECT public: UKUIStartMenuButton(IUKUIPanelPlugin *plugin, QWidget* parent = 0); ~UKUIStartMenuButton(); void realign(); protected: void contextMenuEvent(QContextMenuEvent *event); void mousePressEvent(QMouseEvent* event); private: QMenu *rightPressMenu; IUKUIPanelPlugin * mPlugin; private slots: void ScreenServer(); void SessionSwitch(); void SessionLogout(); void SessionReboot(); void SessionShutdown(); }; #endif ukui-panel/CMakeLists.txt0000644000175000017500000002203513640356061014316 0ustar fengfengcmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) # CMP0000: Call the cmake_minimum_required() command at the beginning of the top-level # CMakeLists.txt file even before calling the project() command. # The cmake_minimum_required(VERSION) command implicitly invokes the cmake_policy(VERSION) # command to specify that the current project code is written for the given range of CMake # versions. project(ukui-panel) option(UPDATE_TRANSLATIONS "Update source translation translations/*.ts files" OFF) option(WITH_SCREENSAVER_FALLBACK "Include support for converting the deprecated 'screensaver' plugin to 'quicklaunch'. This requires the ukui-leave (ukui-session) to be installed in runtime." OFF) # plugin-mainmenu option(USE_MENU_CACHE "Use menu-cached (no noticable penalty even on a 2004 single core pentium if not used)" OFF) # additional cmake files set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) macro(setByDefault VAR_NAME VAR_VALUE) if(NOT DEFINED ${VAR_NAME}) set (${VAR_NAME} ${VAR_VALUE}) endif(NOT DEFINED ${VAR_NAME}) endmacro() include(GNUInstallDirs) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) set(REQUIRED_QT_VERSION "5.7.1") set(KF5_MINIMUM_VERSION "5.36.0") set(UKUI_MINIMUM_VERSION "0.14.1") set(QTXDG_MINIMUM_VERSION "3.3.1") set(QT_MINIMUM_VERSION "5.7.1") find_package(Qt5DBus ${REQUIRED_QT_VERSION} REQUIRED) find_package(Qt5LinguistTools ${REQUIRED_QT_VERSION} REQUIRED) find_package(Qt5Widgets ${REQUIRED_QT_VERSION} REQUIRED) find_package(Qt5X11Extras ${REQUIRED_QT_VERSION} REQUIRED) find_package(Qt5Xml ${REQUIRED_QT_VERSION} REQUIRED) find_package(KF5WindowSystem ${KF5_MINIMUM_VERSION} REQUIRED) #find_package(ukui ${UKUI_MINIMUM_VERSION} REQUIRED) #find_package(ukui-globalkeys ${UKUI_MINIMUM_VERSION} REQUIRED) #find_package(ukui-globalkeys-ui ${UKUI_MINIMUM_VERSION} REQUIRED) find_package(Qt5 ${QT_MINIMUM_VERSION} CONFIG REQUIRED Widgets DBus X11Extras LinguistTools) find_package(Qt5Xdg ${QTXDG_MINIMUM_VERSION} REQUIRED) find_package(X11 REQUIRED) find_package(Qt5LinguistTools) # Patch Version set(UKUI_VERSION 3.0) set(UKUI_PANEL_PATCH_VERSION 0) set(UKUI_MAJOR_VERSION 3) set(UKUI_MINOR_VERSION 0) set(UKUI_TRANSLATIONS_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/ukui/translations/") set(UKUI_PANEL_VERSION ${UKUI_MAJOR_VERSION}.${UKUI_MINOR_VERSION}.${UKUI_PANEL_PATCH_VERSION}) add_definitions("-DUKUI_PANEL_VERSION=\"${UKUI_PANEL_VERSION}\"") include(./cmake/ukui-build-tools/modules/UKUiPreventInSourceBuilds.cmake) #include(./cmake/ukui-build-tools/modules/UKUiTranslate.cmake) # All UKUiCompilerSettings except CMAKE_MODULE_LINKER_FLAGS work just fine # So we reset only these Flags after loading UKUiCompilerSettings # ukui-build-tools: # set(CMAKE_MODULE_LINKER_FLAGS "-Wl,--no-undefined ${SYMBOLIC_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}") message(STATUS "==OLD== CMAKE_MODULE_LINKER_FLAGS: ${CMAKE_MODULE_LINKER_FLAGS}") set( OLD_CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") #include(UKUiCompilerSettings NO_POLICY_SCOPE) set(CMAKE_MODULE_LINKER_FLAGS "${OLD_CMAKE_MODULE_LINKER_FLAGS} ${SYMBOLIC_FLAGS}") # Warning: This must be before add_subdirectory(panel). Move with caution. set(PLUGIN_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/ukui-panel") add_definitions( -DPLUGIN_DIR=\"${PLUGIN_DIR}\" ) #Add PACKAGE_DATA_DIR set(PACKAGE_DATA_DIR "/usr/share/ukui-panel") add_definitions( -DPACKAGE_DATA_DIR=\"${PACKAGE_DATA_DIR}\" ) message(STATUS "CMAKE Module linker flags: ${CMAKE_MODULE_LINKER_FLAGS}") message(STATUS "Panel plugins location: ${PLUGIN_DIR}") ######################################################################### # Plugin system # You can enable/disable building of the plugin using cmake options. # cmake -DWORLDCLOCK_PLUGIN=Yes .. # Enable worldclock plugin # cmake -DWORLDCLOCK_PLUGIN=No .. # Disable worldclock plugin include("cmake/BuildPlugin.cmake") #include(./cmake/ukui-build-tools/modules/UKUiTranslateDesktop.cmake) include(./cmake/ukui-build-tools/modules/UKUiTranslateDesktop.cmake) #include(./cmake/ukui-build-tools/modules/UKUiTranslationLoader.cmake) include(./cmake/ukui-build-tools/modules/UKUiTranslationLoader.cmake) set(ENABLED_PLUGINS) # list of enabled plugins set(STATIC_PLUGINS) # list of statically linked plugins #setByDefault(DESKTOPSWITCH_PLUGIN Yes) if(DESKTOPSWITCH_PLUGIN) list(APPEND STATIC_PLUGINS "desktopswitch") add_definitions(-DWITH_DESKTOPSWITCH_PLUGIN) list(APPEND ENABLED_PLUGINS "Desktop Switcher") add_subdirectory(plugin-desktopswitch) endif() #setByDefault(MOUNT_PLUGIN Yes) if(MOUNT_PLUGIN) list(APPEND ENABLED_PLUGINS "Mount") add_subdirectory(plugin-mount) endif(MOUNT_PLUGIN) setByDefault(QUICKLAUNCH_PLUGIN Yes) if(QUICKLAUNCH_PLUGIN) list(APPEND STATIC_PLUGINS "quicklaunch") add_definitions(-DWITH_QUICKLAUNCH_PLUGIN) list(APPEND ENABLED_PLUGINS "Quicklaunch") add_subdirectory(plugin-quicklaunch) endif() setByDefault(SHOWDESKTOP_PLUGIN Yes) if(SHOWDESKTOP_PLUGIN) list(APPEND STATIC_PLUGINS "showdesktop") add_definitions(-DWITH_SHOWDESKTOP_PLUGIN) list(APPEND ENABLED_PLUGINS "Show Desktop") add_subdirectory(plugin-showdesktop) endif() setByDefault(TASKBAR_PLUGIN Yes) if(TASKBAR_PLUGIN) list(APPEND STATIC_PLUGINS "taskbar") add_definitions(-DWITH_TASKBAR_PLUGIN) list(APPEND ENABLED_PLUGINS "Taskbar") add_subdirectory(plugin-taskbar) endif() add_subdirectory(ukui-flash-disk) setByDefault(TRAY_PLUGIN Yes) if(TRAY_PLUGIN) list(APPEND STATIC_PLUGINS "tray") add_definitions(-DWITH_TRAY_PLUGIN) list(APPEND ENABLED_PLUGINS "System Tray") add_subdirectory(plugin-tray) endif() #setByDefault(VOLUME_PLUGIN Yes) setByDefault(VOLUME_USE_PULSEAUDIO Yes) setByDefault(VOLUME_USE_ALSA Yes) if(VOLUME_PLUGIN) if (VOLUME_USE_PULSEAUDIO) find_package(PulseAudio) if (NOT PULSEAUDIO_FOUND) message(FATAL_ERROR "PulseAudio not found, but required (VOLUME_USE_PULSEAUDIO) for Volume plugin!") endif () endif(VOLUME_USE_PULSEAUDIO) if(VOLUME_USE_ALSA) find_package(ALSA) if (NOT ALSA_FOUND) message(FATAL_ERROR "ALSA not found, but required (VOLUME_USE_ALSA) for Volume plugin!") endif () endif() list(APPEND ENABLED_PLUGINS "Volume") message(STATUS "") message(STATUS "Volume plugin will be built") message(STATUS " ALSA: ${ALSA_FOUND}") message(STATUS " PulseAudio: ${PULSEAUDIO_FOUND}") message(STATUS "") add_subdirectory(plugin-volume) endif() setByDefault(SPACER_PLUGIN Yes) if(SPACER_PLUGIN) list(APPEND STATIC_PLUGINS "spacer") add_definitions(-DWITH_SPACER_PLUGIN) list(APPEND ENABLED_PLUGINS "Spacer") add_subdirectory(plugin-spacer) endif() setByDefault(CALENDAR_PLUGIN Yes) if(CALENDAR_PLUGIN) # list(APPEND STATIC_PLUGINS "calendar") # add_definitions(-DWITH_CALENDAR_PLUGIN) list(APPEND ENABLED_PLUGINS "calendar") add_subdirectory(plugin-calendar) endif(CALENDAR_PLUGIN) setByDefault(STARTMENU_PLUGIN Yes) if(STARTMENU_PLUGIN) # list(APPEND STATIC_PLUGINS "startmenu") # add_definitions(-DWITH_STARTMENU_PLUGIN) list(APPEND ENABLED_PLUGINS "startmenu") add_subdirectory(plugin-startmenu) endif(STARTMENU_PLUGIN) setByDefault(NIGHTMODE_PLUGIN Yes) if(NIGHTMODE_PLUGIN) list(APPEND ENABLED_PLUGINS "nightmode") add_subdirectory(plugin-nightmode) endif(NIGHTMODE_PLUGIN) setByDefault(TASKVIEW_PLUGIN Yes) if(TASKVIEW_PLUGIN) # list(APPEND STATIC_PLUGINS "taskview") # add_definitions(-DWITH_TASKVIEW_PLUGIN) list(APPEND ENABLED_PLUGINS "taskview") add_subdirectory(plugin-taskview) endif(TASKVIEW_PLUGIN) setByDefault(SEGMENTATION_PLUGIN Yes) if(SEGMENTATION_PLUGIN) # list(APPEND STATIC_PLUGINS "segmentation") # add_definitions(-DWITH_SEGMENTATION_PLUGIN) list(APPEND ENABLED_PLUGINS "segmentation") add_subdirectory(plugin-segmentation) endif(SEGMENTATION_PLUGIN) ######################################################################### message(STATUS "**************** The following plugins will be built ****************") foreach (PLUGIN_STR ${ENABLED_PLUGINS}) message(STATUS " ${PLUGIN_STR}") endforeach() message(STATUS "*********************************************************************") add_subdirectory(panel) file(GLOB_RECURSE QRC_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.qrc) # i18n set(UKUI_TRANSLATIONS_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/ukui/) add_definitions( -DUKUI_TRANSLATIONS_DIR="${UKUI_TRANSLATIONS_DIR}" ) if (NOT DEFINED UPDATE_TRANSLATIONS) set(UPDATE_TRANSLATIONS "No") endif() # To create a new ts file: lupdate -recursive . -target-language zh_CN -ts panel/resources/ukui-panel_zh_CN.ts file(GLOB TS_FILES "${CMAKE_CURRENT_SOURCE_DIR}/panel/resources/*.ts") # cmake -DUPDATE_TRANSLATIONS=yes if (UPDATE_TRANSLATIONS) qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES}) else() qt5_add_translation(QM_FILES ${TS_FILES}) endif() add_custom_target(translations ALL DEPENDS ${QM_FILES}) install(FILES ${QM_FILES} DESTINATION ${UKUI_TRANSLATIONS_DIR}) ukui-panel/ukui-flash-disk/0000755000175000017500000000000013643625333014560 5ustar fengfengukui-panel/ukui-flash-disk/qclickwidget.h0000644000175000017500000000277213640356246017414 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include class MainWindow; class QClickWidget : public QWidget { Q_OBJECT public: explicit QClickWidget(QWidget *parent = nullptr,bool is_eject = true, QString name=NULL, qlonglong capacity=NULL, QString path=NULL); ~QClickWidget(); public Q_SLOTS: void mouseClicked(); protected: void mousePressEvent(QMouseEvent *ev); void mouseReleaseEvent(QMouseEvent *ev); void paintEvent(QPaintEvent *); private: bool m_is_eject; QString m_name; qlonglong m_capacity; QString m_path; MainWindow *m_mainwindow; QPoint mousePos; Q_SIGNALS: void clicked(); }; #endif ukui-panel/ukui-flash-disk/mainwindow.h0000644000175000017500000000333313640356246017110 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include "qclickwidget.h" #include "UnionVariable.h" #include "ejectInterface.h" #include #include namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); void setsystemTray(QSystemTrayIcon *_systray); private: Ui::MainWindow *ui; QVBoxLayout *vboxlayout; QLabel *no_device_label; QPushButton *eject_image_button; void newarea(QString name, qlonglong capacity, QString path,int linestatus); void moveBottomRight(); QString size_human(qlonglong capacity); QSystemTrayIcon *m_systray; QIcon iconSystray; //void initUi(); public Q_SLOTS: void iconActivated(QSystemTrayIcon::ActivationReason reason); int getPanelPosition(QString str); int getPanelHeight(QString str); Q_SIGNALS: void clicked(); }; #endif ukui-panel/ukui-flash-disk/UnionVariable.cpp0000644000175000017500000000201213640356246020016 0ustar fengfeng /* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see > mountsList; QList > *findList() { return &mountsList; } static QList> volumesList; QList > *findVolumeList() { return &volumesList; } ukui-panel/ukui-flash-disk/mainwindow.ui0000644000175000017500000000074613635352661017304 0ustar fengfeng MainWindow 0 0 370 232 MainWindow ukui-panel/ukui-flash-disk/disk-resources/0000755000175000017500000000000013635352661017524 5ustar fengfengukui-panel/ukui-flash-disk/disk-resources/ukui-flash-disk.desktop0000644000175000017500000000030513635352661024115 0ustar fengfeng[Desktop Entry] Name=ukui flash disk comment=Ukui Flash Disk Comment[zh_CN]=u盘管理工具 Exec=ukui-flash-disk Terminal=false Type=Application Icon=panel X-UKUI-AutoRestart=true OnlyShowIn=UKUI ukui-panel/ukui-flash-disk/disk-resources/ukui-flash-disk.pro0000644000175000017500000000102513635352661023244 0ustar fengfengQT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = ukui-flash-disk TEMPLATE = app PKGCONFIG +=gio-2.0 peony #LIBS +=-lgio-2.0 -lglib-2.0 CONFIG += c++11 link_pkgconfig no_keywords debug DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ main.cpp \ mainwindow.cpp \ UnionVariable.cpp \ qclickwidget.cpp # Removablemount.cpp HEADERS += \ UnionVariable.h \ mainwindow.h \ qclickwidget.h # Removablemount.h FORMS += mainwindow.ui ukui-panel/ukui-flash-disk/disk-resources/ukui-flash-disk_zh_CN.ts0000644000175000017500000000113313635352661024153 0ustar fengfeng ejectInterface usb has been unplugged safely U盘已安全拔出 MainWindow usb management tool U盘管理工具 ukui-panel/ukui-flash-disk/disk-resources/ukui-flash-disk_zh_CN.qm0000644000175000017500000000026613635352661024150 0ustar fengfeng i Uv{t]Qwusb management tool MainWindowUv][QhbQusb has been unplugged safelyejectInterfaceukui-panel/ukui-flash-disk/ejectInterface.h0000644000175000017500000000302313642640775017650 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE namespace Ui { class ejectInterface; } QT_END_NAMESPACE class ejectInterface : public QWidget { Q_OBJECT public: ejectInterface(QWidget *parent,QString name); ~ejectInterface(); private: QLabel *eject_image_label; QLabel *show_text_label; QLabel *mount_name_label; QHBoxLayout *ejectinterface_h_BoxLayout; QHBoxLayout *mountname_h_BoxLayout; QVBoxLayout *main_V_BoxLayput; QTimer *interfaceHideTime; private Q_SLOTS: void on_interface_hide(); protected: void paintEvent(QPaintEvent *event); }; #endif ukui-panel/ukui-flash-disk/ui_mainwindow.h0000644000175000017500000000260313635352661017605 0ustar fengfeng/******************************************************************************** ** Form generated from reading UI file 'mainwindow.ui' ** ** Created by: Qt User Interface Compiler version 5.12.5 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ #ifndef UI_MAINWINDOW_H #define UI_MAINWINDOW_H #include #include #include #include QT_BEGIN_NAMESPACE class Ui_MainWindow { public: QWidget *centralWidget; void setupUi(QMainWindow *MainWindow) { if (MainWindow->objectName().isEmpty()) MainWindow->setObjectName(QString::fromUtf8("MainWindow")); MainWindow->resize(400, 300); centralWidget = new QWidget(MainWindow); centralWidget->setObjectName(QString::fromUtf8("centralWidget")); MainWindow->setCentralWidget(centralWidget); retranslateUi(MainWindow); QMetaObject::connectSlotsByName(MainWindow); } // setupUi void retranslateUi(QMainWindow *MainWindow) { MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", nullptr)); } // retranslateUi }; namespace Ui { class MainWindow: public Ui_MainWindow {}; } // namespace Ui QT_END_NAMESPACE #endif // UI_MAINWINDOW_H ukui-panel/ukui-flash-disk/clickLabel.cpp0000644000175000017500000000236313640356061017311 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see button() == Qt::LeftButton) Q_EMIT clicked(); QLabel::mousePressEvent(event); } //void ClickLabel::paintEvent(QPaintEvent *event){ //// Q_UNUSED(event) //// QStyleOption opt; //// opt.init(this); //// QPainter p(this); //// style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); //} ukui-panel/ukui-flash-disk/ukui-flash-disk.desktop0000644000175000017500000000030513632320722021141 0ustar fengfeng[Desktop Entry] Name=ukui flash disk comment=Ukui Flash Disk Comment[zh_CN]=u盘管理工具 Exec=ukui-flash-disk Terminal=false Type=Application Icon=panel X-UKUI-AutoRestart=true OnlyShowIn=UKUI ukui-panel/ukui-flash-disk/ukui-flash-disk.qrc0000644000175000017500000000050213635352661020266 0ustar fengfeng ukui-flash-disk.qss picture/tip-32.svg picture/media-eject-symbolic.svg picture/drive-removable-media.svg picture/drive-removable-media-usb.png ukui-panel/ukui-flash-disk/clickLabel.h0000644000175000017500000000221613640356061016753 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include class ClickLabel : public QLabel { Q_OBJECT public: explicit ClickLabel(const QString &text, QWidget *parent = 0); ~ClickLabel(); protected: void mousePressEvent(QMouseEvent * event); //virtual void paintEvent(QPaintEvent * event); Q_SIGNALS: void clicked(); }; #endif // CLICKLABEL_H ukui-panel/ukui-flash-disk/qclickwidget.cpp0000644000175000017500000000343713640356246017746 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see topLevelWidget()->hide(); } void QClickWidget::mousePressEvent(QMouseEvent *ev) { mousePos = QPoint(ev->x(), ev->y()); } void QClickWidget::mouseReleaseEvent(QMouseEvent *ev) { if(mousePos == QPoint(ev->x(), ev->y())) Q_EMIT clicked(); } void QClickWidget::paintEvent(QPaintEvent *) { //解决QClickWidget类设置样式不生效的问题 QStyleOption opt; opt.init(this); QPainter p(this); p.setBrush(QColor(0x00,0x00,0x00)); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } ukui-panel/ukui-flash-disk/UnionVariable.h0000644000175000017500000000164513640356246017476 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include QList> *findList(); QList> *findVolumeList(); #endif ukui-panel/ukui-flash-disk/CMakeLists.txt0000644000175000017500000000234213640356246017322 0ustar fengfengcmake_minimum_required(VERSION 3.1.0) project(ukui-flash-disk) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) if(CMAKE_VERSION VERSION_LESS "3.7.0") set(CMAKE_INCLUDE_CURRENT_DIR ON) endif() find_package(Qt5 COMPONENTS Widgets REQUIRED) find_package(Qt5DBus REQUIRED) find_package(PkgConfig REQUIRED) pkg_check_modules(PEONY REQUIRED peony) message(${PEONY_INCLUDE_DIRS}) message(${PEONY_LIBRARIES}) include_directories(${PEONY_INCLUDE_DIRS}) add_executable(ukui-flash-disk ukui-flash-disk.qrc disk-resources/ukui-flash-disk_zh_CN.ts main.cpp mainwindow.cpp qclickwidget.cpp UnionVariable.cpp UnionVariable.h ejectInterface.cpp ejectInterface.h mainwindow.ui mainwindow.h qclickwidget.h ) add_definitions(-DQT_NO_KEYWORDS) target_link_libraries(${PROJECT_NAME} Qt5::Widgets Qt5::DBus ${PEONY_LIBRARIES}) install(TARGETS ukui-flash-disk DESTINATION bin) install(FILES disk-resources/ukui-flash-disk.desktop DESTINATION "/etc/xdg/autostart/" COMPONENT Runtime ) install(FILES ukui-flash-disk.qrc disk-resources/ukui-flash-disk_zh_CN.qm DESTINATION "/usr/share/ukui/ukui-panel/" COMPONENT Runtime ) ukui-panel/ukui-flash-disk/ejectInterface.cpp0000644000175000017500000001100213642640775020177 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see setPixmap(pixmap); } show_text_label = new QLabel; if(show_text_label) { show_text_label->setText(tr("usb has been unplugged safely")); QPalette pe; pe.setColor(QPalette::WindowText,Qt::white); show_text_label->setPalette(pe); } ejectinterface_h_BoxLayout = new QHBoxLayout(); if(ejectinterface_h_BoxLayout) { ejectinterface_h_BoxLayout->addStretch(); ejectinterface_h_BoxLayout->addWidget(eject_image_label); ejectinterface_h_BoxLayout->addWidget(show_text_label); ejectinterface_h_BoxLayout->addStretch(); } mountname_h_BoxLayout = new QHBoxLayout(); mount_name_label = new QLabel(); if(mount_name_label) { mount_name_label->setText(mount_name); } mountname_h_BoxLayout->addStretch(); mountname_h_BoxLayout->addWidget(mount_name_label); mountname_h_BoxLayout->addStretch(); main_V_BoxLayput = new QVBoxLayout; main_V_BoxLayput->addLayout(ejectinterface_h_BoxLayout); main_V_BoxLayput->addLayout(mountname_h_BoxLayout); this->resize(210,86); this->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup); this->setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 QPainterPath path; auto rect = this->rect(); rect.adjust(0,0,-0,-0); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); this->setStyleSheet("QWidget{" "background:rgba(19,19,20,1);" "border:1px solid rgba(255, 255, 255, 0.05);" "border-radius:6px;" "box-shadow:0px 2px 6px 0px rgba(0, 0, 0, 0.2);" "border-radius:6px" "}"); eject_image_label->setStyleSheet( //正常状态样式 "QLabel{" "color:rgba(255,255,255,1);" "line-height:24px;" "opacity:1;" "border:none;" "}" ); show_text_label->setStyleSheet( //正常状态样式 "QLabel{" "font-size:16px;" "font-family:NotoSansCJKsc-Regular;" "font-weight:400;" "color:rgba(255,255,255,1);" "line-height:24px;" "opacity:1;" "border:none;" "}"); mount_name_label->setStyleSheet( //正常状态样式 "QLabel{" "width:93px;" "height:15px;" "font-size:14px;" "font-family:NotoSansCJKsc-Regular;" "font-weight:400;" "color:rgba(255,255,255,0.35);" "line-height:28px;" "opacity:0.35;" "border:none;" "}"); this->setLayout(main_V_BoxLayput); interfaceHideTime = new QTimer(this); interfaceHideTime->setTimerType(Qt::PreciseTimer); connect(interfaceHideTime, SIGNAL(timeout()), this, SLOT(on_interface_hide())); interfaceHideTime->start(1000); } ejectInterface::~ejectInterface() { } //If the fillet does not take effect void ejectInterface::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(event); } void ejectInterface::on_interface_hide() { this->hide(); } ukui-panel/ukui-flash-disk/picture/0000755000175000017500000000000013635352661016235 5ustar fengfengukui-panel/ukui-flash-disk/picture/tip-32.svg0000644000175000017500000000305213635352661017774 0ustar fengfeng ukui-panel/ukui-flash-disk/picture/drive-removable-media.svg0000755000175000017500000000306213635352661023122 0ustar fengfeng ukui-panel/ukui-flash-disk/picture/media-eject-symbolic.svg0000644000175000017500000000116413635352661022746 0ustar fengfeng ukui-panel/ukui-flash-disk/picture/drive-removable-media-usb.png0000644000175000017500000000060213635352661023670 0ustar fengfengPNG  IHDRĴl; pHYs  ~4IDAT8c?:)lXψ.Dal-) g``f0~%ɻ043IS /[C`??#@h G??0ɻ2|q1v=p=p%`hr%5 g}" L0R e `b# ^+(A4Kkm0WXHL}L2GbTI\ ޾894ϠWA-,,P22200000 wYS [UIENDB`ukui-panel/ukui-flash-disk/main.cpp0000644000175000017500000000463013640356246016214 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include "UnionVariable.h" #include "mainwindow.h" int main(int argc, char *argv[]) { QStringList homePath = QStandardPaths::standardLocations(QStandardPaths::HomeLocation); QString lockPath = homePath.at(0) + "/.config/ukui-flash-disk-lock"; int fd = open(lockPath.toUtf8().data(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (fd < 0) { exit(1); } if (lockf(fd, F_TLOCK, 0)) { syslog(LOG_ERR, "Can't lock single file, ukui-flash-disk is already running!"); qDebug()<<"Can't lock single file, ukui-flash-disk is already running!"; exit(0); } QIcon::setThemeName("ukui-icon-theme-default"); QDBusConnection connection = QDBusConnection::sessionBus(); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication a(argc, argv); a.setQuitOnLastWindowClosed(false); //进程不隐式退出 //load translation file QString locale = QLocale::system().name(); QTranslator translator; if (locale == "zh_CN") { if (translator.load("/usr/share/ukui/ukui-panel/ukui-flash-disk_zh_CN.qm")) { a.installTranslator(&translator); } else { qDebug() << "Load translations file" << locale << "failed!"; } } //load qss QFile qss(":ukui-flash-disk.qss"); bool ok = qss.open(QFile::ReadOnly); if (!ok) qDebug() << "加载失败"; qApp->setStyleSheet(qss.readAll()); qss.close(); MainWindow w; return a.exec(); } ukui-panel/ukui-flash-disk/mainwindow.cpp0000644000175000017500000006022313643625333017443 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { // ejectInterface *ForEject = new ejectInterface(nullptr,"dgsgsdfg"); // ForEject->show(); ui->setupUi(this); //框架的样式设置 QPainterPath path; auto rect = this->rect(); rect.adjust(0,0,-0,-0); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); this->setStyleSheet("QWidget{border:none;border-radius:6px;}"); this->setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 ui->centralWidget->setStyleSheet( "#centralWidget{" "width:280px;" "height:192px;" "background:rgba(19,19,20,0.95);" "border:1px solid rgba(255, 255, 255, 0.05);" "opacity:0.75;" "border-radius:6px;" "box-shadow:0px 2px 6px 0px rgba(0, 0, 0, 0.2);" "}" ); iconSystray = QIcon::fromTheme("drive-removable-media"); vboxlayout = new QVBoxLayout(); ui->centralWidget->setLayout(vboxlayout); this->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup); this->setWindowOpacity(0.95); this->resize( QSize( 280, 192 )); m_systray = new QSystemTrayIcon; //w.show(); //m_systray->setIcon(QIcon("/usr/share/icons/ukui-icon-theme-default/22x22/devices/drive-removable-media.png")); m_systray->setIcon(iconSystray); m_systray->setToolTip(tr("usb management tool")); connect(m_systray, &QSystemTrayIcon::activated, this, &MainWindow::iconActivated); auto g_volume_monitor = g_volume_monitor_get(); // about the mounts GList *current_mount_list = g_volume_monitor_get_mounts(g_volume_monitor); GList *current_device = current_mount_list; while (current_device) { GMount *gmount = G_MOUNT(current_device->data); std::shared_ptr mount = std::make_shared(gmount); qDebug()<name()<<"append to list"; if(g_mount_can_eject(mount->getGMount())) { *findList()<next; } //about the volumes GList *current_volume_list = g_volume_monitor_get_volumes(g_volume_monitor); GList *current_volume_device = current_volume_list; while(current_volume_device) { GVolume *gvolume = G_VOLUME(current_volume_device->data); std::shared_ptr volume = std::make_shared(gvolume); qDebug()<name()<<"append to list"; if(g_volume_can_eject(volume->getGVolume()) || g_drive_can_eject(g_volume_get_drive(volume->getGVolume())) || g_drive_can_stop(g_volume_get_drive(volume->getGVolume()))) { *findVolumeList()<next; qDebug()<<"current_volume_lists"<size(); } for (auto cacheVolume : *findVolumeList()) { if(g_volume_can_eject(cacheVolume->getGVolume()) || g_drive_can_eject(g_volume_get_drive(cacheVolume->getGVolume())) || g_drive_can_stop(g_volume_get_drive(cacheVolume->getGVolume()))) { qDebug()<<"wwj,wozhendeshi,wuyule"; g_volume_mount(cacheVolume->getGVolume(), G_MOUNT_MOUNT_NONE, nullptr, nullptr, nullptr, nullptr); } } //about the drives auto manager = Peony::VolumeManager::getInstance(); //volumeAdded一般在设备插入时触发 manager->connect(manager, &Peony::VolumeManager::volumeAdded, [](const std::shared_ptr &volume) { qDebug() << "volume" << volume->name() << "added"; g_volume_mount(volume->getGVolume(), G_MOUNT_MOUNT_NONE, nullptr, nullptr, nullptr, nullptr); }); manager->connect(manager, &Peony::VolumeManager::volumeRemoved, [](const std::shared_ptr &volume) { qDebug()<< "volume" << volume->name() << "removed"; }); //注意mountAdded必须要挂载之后才会触发 manager->connect(manager, &Peony::VolumeManager::mountAdded, [&](const std::shared_ptr &mount) { qDebug()<<"mount"<name()<<"added"; if(g_mount_can_eject(mount->getGMount()) || g_drive_can_stop(g_volume_get_drive(g_mount_get_volume(mount->getGMount()))) ) { *findList()<size(); m_systray->show(); }); manager->connect(manager, &Peony::VolumeManager::mountRemoved, [&](const std::shared_ptr &mount) { qDebug()<<"mount"<name()<<"removed"; for (auto cachedMount : *findList()) { if (cachedMount->name() == mount->name()) { findList()->removeOne(cachedMount); ejectInterface *ForEject = new ejectInterface(nullptr,cachedMount->name()); int screenNum = QGuiApplication::screens().count(); int panelHeight = getPanelHeight("PanelHeight"); int position =0; position = getPanelPosition("PanelPosion"); int screen = 0; QRect rect; int localX ,availableWidth,totalWidth; int localY,availableHeight,totalHeight; qDebug() << "任务栏位置"<< position; if (screenNum > 1) { if (position == 3) //on the right { screen = screenNum - 1; //Available screen width and height availableWidth =QGuiApplication::screens().at(screen)->geometry().x() + QGuiApplication::screens().at(screen)->size().width()-panelHeight; availableHeight = QGuiApplication::screens().at(screen)->availableGeometry().height(); //total width totalWidth = QGuiApplication::screens().at(0)->size().width() + QGuiApplication::screens().at(screen)->size().width(); totalHeight = QGuiApplication::screens().at(screen)->size().height(); } else if(position ==0 || position ==1) //above or bellow { availableHeight = QGuiApplication::screens().at(0)->size().height() - panelHeight; availableWidth = QGuiApplication::screens().at(0)->size().width(); totalHeight = QGuiApplication::screens().at(0)->size().height(); totalWidth = QGuiApplication::screens().at(0)->size().width(); } else { availableHeight = QGuiApplication::screens().at(0)->availableGeometry().height(); availableWidth = QGuiApplication::screens().at(0)->availableGeometry().width(); totalHeight = QGuiApplication::screens().at(0)->size().height(); totalWidth = QGuiApplication::screens().at(0)->size().width(); } } else { availableHeight = QGuiApplication::screens().at(0)->availableGeometry().height(); availableWidth = QGuiApplication::screens().at(0)->availableGeometry().width(); totalHeight = QGuiApplication::screens().at(0)->size().height(); totalWidth = QGuiApplication::screens().at(0)->size().width(); } //show the location of the systemtray rect = m_systray->geometry(); localX = rect.x() - (ForEject->width()/2 - rect.size().width()/2) ; localY = availableHeight - ForEject->height(); //modify location if (position == 0) { //下 if (availableWidth - rect.x() - rect.width()/2 < ForEject->width() / 2) ForEject->setGeometry(availableWidth-ForEject->width(),availableHeight-ForEject->height()-3,ForEject->width(),ForEject->height()); else ForEject->setGeometry(localX-16,availableHeight-ForEject->height()-3,ForEject->width(),ForEject->height()); } else if (position == 1) { //上 if (availableWidth - rect.x() - rect.width()/2 < ForEject->width() / 2) ForEject->setGeometry(availableWidth-ForEject->width(),totalHeight-availableHeight+3,ForEject->width(),ForEject->height()); else ForEject->setGeometry(localX-16,totalHeight-availableHeight+3,ForEject->width(),ForEject->height()); } else if (position == 2) { if (availableHeight - rect.y() - rect.height()/2 > ForEject->height() /2) ForEject->setGeometry(panelHeight + 3,rect.y() + (rect.width() /2) -(ForEject->height()/2) ,ForEject->width(),ForEject->height()); else ForEject->setGeometry(panelHeight+3,localY,ForEject->width(),ForEject->height());//左 } else if (position == 3) { localX = availableWidth - ForEject->width(); if (availableHeight - rect.y() - rect.height()/2 > ForEject->height() /2) { ForEject->setGeometry(availableWidth - ForEject->width() -3,rect.y() + (rect.height() /2) -(ForEject->height()/2),ForEject->width(),ForEject->height()); } else ForEject->setGeometry(localX-3,localY,ForEject->width(),ForEject->height()); } qDebug()<<"wohaoxiangni,haoxiangni,quebunengziyi"; ForEject->show(); if(findList()->size() == 0) { m_systray->hide(); } } } }); // manager->connect(manager, &Peony::VolumeManager::volumeRemoved, [&](const std::shared_ptr &volume) // { // qDebug()<<"volume"<name()<<"removed"; // for (auto cacheVolume : *findVolumeList()) // { // if(cacheVolume->name() == volume->name()) // { // findVolumeList()->removeOne(cacheVolume); // if(findVolumeList() == 0) // { // m_systray->hide(); // } // } // } // }); if(findList()->size() >= 1) { m_systray->show(); } qDebug()<size()<<"rensaddedheng ru meng "; } MainWindow::~MainWindow() { delete ui; } void MainWindow::setsystemTray(QSystemTrayIcon *_systray) { m_systray = _systray; } void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) { int num = 0; if ( this->vboxlayout != NULL ) { QLayoutItem* item; while ((item = this->vboxlayout->takeAt(0)) != NULL) { delete item->widget(); delete item; } } switch (reason) { case QSystemTrayIcon::Trigger: case QSystemTrayIcon::Context: if (this->isHidden()) { for (auto cacheMount : *findList()) { QString UDiskPath = g_file_get_path(g_mount_get_root(cacheMount->getGMount())); if (UDiskPath.contains("media") && g_mount_can_eject(cacheMount->getGMount()) || g_drive_can_stop(g_volume_get_drive(g_mount_get_volume(cacheMount->getGMount())))) { num++; this->setFixedSize(250, 98*num); QByteArray date = UDiskPath.toLocal8Bit(); char *p_Change = date.data(); GFile *file = g_file_new_for_path(p_Change); GFileInfo *info = g_file_query_filesystem_info(file,"*",nullptr,nullptr); quint64 total = g_file_info_get_attribute_uint64(info,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE); if(num == 1) { qDebug() << "name: " << cacheMount->name(); newarea(cacheMount->name(), total, UDiskPath, 1); } else { newarea(cacheMount->name(), total, UDiskPath, 2); } connect(eject_image_button, &QPushButton::clicked,[=]() { g_mount_eject_with_operation(cacheMount->getGMount(), G_MOUNT_UNMOUNT_NONE, nullptr, nullptr, nullptr, nullptr); this->hide(); QLayoutItem* item; while ((item = this->vboxlayout->takeAt(0)) != NULL) { delete item->widget(); delete item; } }); } if(num != 0) { this->showNormal(); moveBottomRight(); } } } else { this->hide(); } break; default: break; } } void MainWindow::newarea(QString name, qlonglong capacity, QString path, int linestatus) { QString str_capacity = size_human(capacity); QClickWidget *open_widget; open_widget = new QClickWidget (NULL,false,name,capacity,path); //打开设备的界面布局 open the device's interface layout QLabel *open_label; //QString str_capacity = size_human(capacity); QVBoxLayout *open_vboxlayout = new QVBoxLayout; QHBoxLayout *open_hboxlayout = new QHBoxLayout; QHBoxLayout *open_showcapacity_hboxlayout = new QHBoxLayout; //add eject image eject_image_button= new QPushButton(); QIcon eject_icon(":picture/media-eject-symbolic.svg"); eject_image_button->setIcon(eject_icon); eject_image_button->setFlat(true); // open_image_button->setDisabled(true); QLabel *image_show_label = new QLabel(); QPixmap pixmap(":picture/drive-removable-media-usb.png"); image_show_label->setPixmap(pixmap); QLabel *placeLabel = new QLabel(); if(name.isEmpty()) { open_label = new QLabel("打开 "+str_capacity+"卷"); } else { open_label = new QLabel(name); } open_label->setDisabled(true); QVBoxLayout *imagepartionshow_vboxlayout = new QVBoxLayout(); QLabel *open_capacity = new QLabel(this); qDebug()<setText(str_capacity+" (磁盘容量)"); open_capacity->setAlignment(Qt::AlignCenter); open_capacity->setDisabled(true); //add layout imagepartionshow_vboxlayout->addSpacing(8); imagepartionshow_vboxlayout->addWidget(image_show_label); open_hboxlayout->addLayout(imagepartionshow_vboxlayout); open_hboxlayout->addStretch(); open_hboxlayout->addWidget(open_label); open_hboxlayout->addStretch(); open_hboxlayout->addWidget(eject_image_button); open_vboxlayout->addLayout(open_hboxlayout); open_showcapacity_hboxlayout->addWidget(open_capacity); open_vboxlayout->addLayout(open_showcapacity_hboxlayout); //dividing line QWidget *line = new QWidget; line->setFixedHeight(1); line->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); if (linestatus == 2) { this->vboxlayout->addWidget(line); } open_widget->setLayout(open_vboxlayout); this->vboxlayout->addWidget(open_widget); line->setStyleSheet( "QWidget{" "background-color: rgba(255,255,255,0.2);" "width:280px;" "height:1px;" "}" ); open_label->setStyleSheet( //正常状态样式 "QLabel{" "width:167px;" "height:15px;" "font-size:16px;" "font-family:Microsoft YaHei;" "font-weight:400;" "color:rgba(255,255,255,1);" "line-height:28px;" "opacity:0.91;" "}"); open_capacity->setStyleSheet( "QLabel{" "width:111px;" "height:14px;" "font-size:14px;" "font-family:Microsoft YaHei;" "font-weight:400;" "color:rgba(255,255,255,0.35);" "line-height:28px;" "opacity:0.35;" "}" ); open_widget->setStyleSheet( //正常状态样式 "QClickWidget{" "height:79px;" "}" "QClickWidget:hover{" "background-color:rgba(255,255,255,30);" "}" ); } QString MainWindow::size_human(qlonglong capacity) { // float capacity = this->size(); QStringList list; list << "KB" << "MB" << "GB" << "TB"; QStringListIterator i(list); QString unit("bytes"); while(capacity >= 1024.0 && i.hasNext()) { unit = i.next(); capacity /= 1024.0; } qDebug() << "capacity==============" << capacity << unit; QString str_capacity=QString(" %1%2").arg(capacity).arg(unit); return str_capacity; // return QString().setNum(capacity,'f',2)+" "+unit; } void MainWindow::moveBottomRight() { ////////////////////////////////////////get the loacation of the mouse /*QPoint globalCursorPos = QCursor::pos(); QRect availableGeometry = qApp->primaryScreen()->availableGeometry(); QRect screenGeometry = qApp->primaryScreen()->geometry(); QDesktopWidget* pDesktopWidget = QApplication::desktop(); QRect screenRect = pDesktopWidget->screenGeometry();//area of the screen if (screenRect.height() != availableGeometry.height()) { this->move(globalCursorPos.x()-125, availableGeometry.height() - this->height()); } else { this->move(globalCursorPos.x()-125, availableGeometry.height() - this->height() - 40); }*/ //////////////////////////////////////origin code base on the location of the mouse int screenNum = QGuiApplication::screens().count(); int panelHeight = getPanelHeight("PanelHeight"); int position =0; position = getPanelPosition("PanelPosion"); int screen = 0; QRect rect; int localX ,availableWidth,totalWidth; int localY,availableHeight,totalHeight; qDebug() << "任务栏位置"<< position; if (screenNum > 1) { if (position == 3) //on the right { screen = screenNum - 1; //Available screen width and height availableWidth =QGuiApplication::screens().at(screen)->geometry().x() + QGuiApplication::screens().at(screen)->size().width()-panelHeight; availableHeight = QGuiApplication::screens().at(screen)->availableGeometry().height(); //total width totalWidth = QGuiApplication::screens().at(0)->size().width() + QGuiApplication::screens().at(screen)->size().width(); totalHeight = QGuiApplication::screens().at(screen)->size().height(); } else if(position ==0 || position ==1) //above or bellow { availableHeight = QGuiApplication::screens().at(0)->size().height() - panelHeight; availableWidth = QGuiApplication::screens().at(0)->size().width(); totalHeight = QGuiApplication::screens().at(0)->size().height(); totalWidth = QGuiApplication::screens().at(0)->size().width(); } else { availableHeight = QGuiApplication::screens().at(0)->availableGeometry().height(); availableWidth = QGuiApplication::screens().at(0)->availableGeometry().width(); totalHeight = QGuiApplication::screens().at(0)->size().height(); totalWidth = QGuiApplication::screens().at(0)->size().width(); } } else { availableHeight = QGuiApplication::screens().at(0)->availableGeometry().height(); availableWidth = QGuiApplication::screens().at(0)->availableGeometry().width(); totalHeight = QGuiApplication::screens().at(0)->size().height(); totalWidth = QGuiApplication::screens().at(0)->size().width(); } //show the location of the systemtray rect = m_systray->geometry(); localX = rect.x() - (this->width()/2 - rect.size().width()/2) ; localY = availableHeight - this->height(); //modify location if (position == 0) { //下 if (availableWidth - rect.x() - rect.width()/2 < this->width() / 2) this->setGeometry(availableWidth-this->width(),availableHeight-this->height()-3,this->width(),this->height()); else this->setGeometry(localX,availableHeight-this->height()-3,this->width(),this->height()); } else if (position == 1) { //上 if (availableWidth - rect.x() - rect.width()/2 < this->width() / 2) this->setGeometry(availableWidth-this->width(),totalHeight-availableHeight+3,this->width(),this->height()); else this->setGeometry(localX,totalHeight-availableHeight+3,this->width(),this->height()); } else if (position == 2) { if (availableHeight - rect.y() - rect.height()/2 > this->height() /2) this->setGeometry(panelHeight + 3,rect.y() + (rect.width() /2) -(this->height()/2) ,this->width(),this->height()); else this->setGeometry(panelHeight+3,localY,this->width(),this->height());//左 } else if (position == 3) { localX = availableWidth - this->width(); if (availableHeight - rect.y() - rect.height()/2 > this->height() /2) this->setGeometry(availableWidth - this->width() -3,rect.y() + (rect.width() /2) -(this->height()/2),this->width(),this->height()); else this->setGeometry(localX-3,localY,this->width(),this->height()); } } /* use dbus to get the location of the panel */ int MainWindow::getPanelPosition(QString str) { QDBusInterface interface( "com.ukui.panel.desktop", "/", "com.ukui.panel.desktop", QDBusConnection::sessionBus() ); QDBusReply reply = interface.call("GetPanelPosition", str); return reply; } /* use the dbus to get the height of the panel */ int MainWindow::getPanelHeight(QString str) { QDBusInterface interface( "com.ukui.panel.desktop", "/", "com.ukui.panel.desktop", QDBusConnection::sessionBus() ); QDBusReply reply = interface.call("GetPanelSize", str); return reply; } ukui-panel/ukui-flash-disk/ukui-flash-disk.qss0000644000175000017500000000050113640356246020305 0ustar fengfengQToolTip{ height: 98px; width: 38px; padding-left: 4px; padding-right: 4x; padding-top: 0px; padding-bottom: 0px; border-style: solid; font-size:14px; color:rgba(255,255,255,1); background:rgba(26,26,26,0.7); border:1px solid rgba(255, 255, 255, 0.2); border-radius:6px; } ukui-panel/README.md0000644000175000017500000000014413632320722013026 0ustar fengfeng# ukui-panel ### How to build ukui-panel? mkdir build cd build cmake .. make sudo make install ukui-panel/panel/0000755000175000017500000000000013643551442012656 5ustar fengfengukui-panel/panel/ukuipanel.cpp0000644000175000017500000014672213643551442015373 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuipanel.h" #include "ukuipanellimits.h" #include "iukuipanelplugin.h" #include "ukuipanelapplication.h" #include "ukuipanellayout.h" #include "config/configpaneldialog.h" #include "popupmenu.h" #include "plugin.h" #include "panelpluginsmodel.h" #include "windownotifier.h" #include "common/ukuiplugininfo.h" #include #include #include #include #include #include #include #include #include #include #include #include #include //#include //#include #include // Turn on this to show the time required to load each plugin during startup // #define DEBUG_PLUGIN_LOADTIME #ifdef DEBUG_PLUGIN_LOADTIME #include #endif // Config keys and groups #define CFG_KEY_SCREENNUM "desktop" #define CFG_KEY_POSITION "position" #define CFG_KEY_PANELSIZE "panelSize" #define CFG_KEY_ICONSIZE "iconSize" #define CFG_KEY_LINECNT "lineCount" #define CFG_KEY_LENGTH "width" #define CFG_KEY_PERCENT "width-percent" #define CFG_KEY_ALIGNMENT "alignment" #define CFG_KEY_FONTCOLOR "font-color" #define CFG_KEY_BACKGROUNDCOLOR "background-color" #define CFG_KEY_BACKGROUNDIMAGE "background-image" #define CFG_KEY_OPACITY "opacity" #define CFG_KEY_RESERVESPACE "reserve-space" #define CFG_KEY_PLUGINS "plugins" #define CFG_KEY_HIDABLE "hidable" #define CFG_KEY_VISIBLE_MARGIN "visible-margin" #define CFG_KEY_ANIMATION "animation-duration" #define CFG_KEY_SHOW_DELAY "show-delay" #define CFG_KEY_LOCKPANEL "lockPanel" #define GSETTINGS_SCHEMA_SCREENSAVER "org.mate.interface" #define KEY_MODE "gtk-theme" #define PANEL_SIZE_LARGE 92 #define PANEL_SIZE_MEDIUM 70 #define PANEL_SIZE_SMALL 46 #define ICON_SIZE_LARGE 64 #define ICON_SIZE_MEDIUM 48 #define ICON_SIZE_SMALL 32 #define PANEL_SETTINGS "org.ukui.panel.settings" #define PANEL_SIZE_KEY "panelsize" #define ICON_SIZE_KEY "iconsize" #define PANEL_POSITION_KEY "panelposition" /************************************************ Returns the Position by the string. String is one of "Top", "Left", "Bottom", "Right", string is not case sensitive. If the string is not correct, returns defaultValue. ************************************************/ IUKUIPanel::Position UKUIPanel::strToPosition(const QString& str, IUKUIPanel::Position defaultValue) { if (str.toUpper() == "TOP") return UKUIPanel::PositionTop; if (str.toUpper() == "LEFT") return UKUIPanel::PositionLeft; if (str.toUpper() == "RIGHT") return UKUIPanel::PositionRight; if (str.toUpper() == "BOTTOM") return UKUIPanel::PositionBottom; return defaultValue; } /************************************************ Return string representation of the position ************************************************/ QString UKUIPanel::positionToStr(IUKUIPanel::Position position) { switch (position) { case UKUIPanel::PositionTop: return QString("Top"); case UKUIPanel::PositionLeft: return QString("Left"); case UKUIPanel::PositionRight: return QString("Right"); case UKUIPanel::PositionBottom: return QString("Bottom"); } return QString(); } /************************************************ ************************************************/ UKUIPanel::UKUIPanel(const QString &configGroup, UKUi::Settings *settings, QWidget *parent) : QFrame(parent), mSettings(settings), mConfigGroup(configGroup), mPlugins{nullptr}, mStandaloneWindows{new WindowNotifier}, mPanelSize(0), mIconSize(0), mLineCount(0), mLength(0), mAlignment(AlignmentLeft), mPosition(IUKUIPanel::PositionBottom), mScreenNum(0), //whatever (avoid conditional on uninitialized value) mActualScreenNum(0), mHidable(false), mVisibleMargin(true), mHidden(false), mAnimationTime(0), mReserveSpace(true), mAnimation(nullptr), mLockPanel(false) { //You can find information about the flags and widget attributes in your //Qt documentation or at https://doc.qt.io/qt-5/qt.html //Qt::FramelessWindowHint = Produces a borderless window. The user cannot //move or resize a borderless window via the window system. On X11, ... //Qt::WindowStaysOnTopHint = Informs the window system that the window //should stay on top of all other windows. Note that on ... Qt::WindowFlags flags = Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint; // NOTE: by PCMan: // In Qt 4, the window is not activated if it has Qt::WA_X11NetWmWindowTypeDock. // Since Qt 5, the default behaviour is changed. A window is always activated on mouse click. // Please see the source code of Qt5: src/plugins/platforms/xcb/qxcbwindow.cpp. // void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) // This new behaviour caused ukui bug #161 - Cannot minimize windows from panel 1 when two task managers are open // Besides, this breaks minimizing or restoring windows when clicking on the taskbar buttons. // To workaround this regression bug, we need to add this window flag here. // However, since the panel gets no keyboard focus, this may decrease accessibility since // it's not possible to use the panel with keyboards. We need to find a better solution later. flags |= Qt::WindowDoesNotAcceptFocus; setWindowFlags(flags); //Adds _NET_WM_WINDOW_TYPE_DOCK to the window's _NET_WM_WINDOW_TYPE X11 window property. See https://standards.freedesktop.org/wm-spec/ for more details. setAttribute(Qt::WA_X11NetWmWindowTypeDock); //Enables tooltips for inactive windows. setAttribute(Qt::WA_AlwaysShowToolTips); //Indicates that the widget should have a translucent background, i.e., any non-opaque regions of the widgets will be translucent because the widget will have an alpha channel. Setting this ... setAttribute(Qt::WA_TranslucentBackground); //Allows data from drag and drop operations to be dropped onto the widget (see QWidget::setAcceptDrops()). setAttribute(Qt::WA_AcceptDrops); setWindowTitle("UKUI Panel"); setObjectName(QString("UKUIPanel %1").arg(configGroup)); //UKUIPanel (inherits QFrame) -> lav (QGridLayout) -> UKUIPanelWidget (QFrame) -> UKUIPanelLayout UKUIPanelWidget = new QFrame(this); UKUIPanelWidget->setObjectName("BackgroundWidget"); QGridLayout* lav = new QGridLayout(); lav->setContentsMargins(0, 0, 0, 0); setLayout(lav); this->layout()->addWidget(UKUIPanelWidget); mLayout = new UKUIPanelLayout(UKUIPanelWidget); connect(mLayout, &UKUIPanelLayout::pluginMoved, this, &UKUIPanel::pluginMoved); UKUIPanelWidget->setLayout(mLayout); mLayout->setLineCount(mLineCount); mDelaySave.setSingleShot(true); mDelaySave.setInterval(SETTINGS_SAVE_DELAY); connect(&mDelaySave, SIGNAL(timeout()), this, SLOT(saveSettings())); mHideTimer.setSingleShot(true); mHideTimer.setInterval(PANEL_HIDE_DELAY); connect(&mHideTimer, SIGNAL(timeout()), this, SLOT(hidePanelWork())); mShowDelayTimer.setSingleShot(true); mShowDelayTimer.setInterval(PANEL_SHOW_DELAY); connect(&mShowDelayTimer, &QTimer::timeout, [this] { showPanel(mAnimationTime > 0); }); connect(QApplication::desktop(), &QDesktopWidget::resized, this, &UKUIPanel::ensureVisible); connect(QApplication::desktop(), &QDesktopWidget::screenCountChanged, this, &UKUIPanel::ensureVisible); // connecting to QDesktopWidget::workAreaResized shouldn't be necessary, // as we've already connceted to QDesktopWidget::resized, but it actually // is. Read mode on https://github.com/ukui/ukui-panel/pull/310 connect(QApplication::desktop(), &QDesktopWidget::workAreaResized, this, &UKUIPanel::ensureVisible); connect(UKUi::Settings::globalSettings(), SIGNAL(settingsChanged()), this, SLOT(update())); connect(ukuiApp, SIGNAL(themeChanged()), this, SLOT(realign())); connect(mStandaloneWindows.data(), &WindowNotifier::firstShown, [this] { showPanel(true); }); connect(mStandaloneWindows.data(), &WindowNotifier::lastHidden, this, &UKUIPanel::hidePanel); readSettings(); ensureVisible(); loadPlugins(); show(); // show it the first time, despite setting if (mHidable) { showPanel(false); QTimer::singleShot(PANEL_HIDE_FIRST_TIME, this, SLOT(hidePanel())); } UKUIPanelApplication *a = reinterpret_cast(qApp); connect(a, &UKUIPanelApplication::primaryScreenChanged, this, &UKUIPanel::setPanelGeometry); const QByteArray id(PANEL_SETTINGS); gsettings = new QGSettings(id); } /************************************************ ************************************************/ void UKUIPanel::readSettings() { // Read settings ...................................... mSettings->beginGroup(mConfigGroup); // Let Hidability be the first thing we read // so that every call to realign() is without side-effect mHidable = mSettings->value(CFG_KEY_HIDABLE, mHidable).toBool(); mHidden = mHidable; mVisibleMargin = mSettings->value(CFG_KEY_VISIBLE_MARGIN, mVisibleMargin).toBool(); mAnimationTime = mSettings->value(CFG_KEY_ANIMATION, mAnimationTime).toInt(); mShowDelayTimer.setInterval(mSettings->value(CFG_KEY_SHOW_DELAY, mShowDelayTimer.interval()).toInt()); // By default we are using size & count from theme. setPanelSize(mSettings->value(CFG_KEY_PANELSIZE, PANEL_DEFAULT_SIZE).toInt(), false); setIconSize(mSettings->value(CFG_KEY_ICONSIZE, PANEL_DEFAULT_ICON_SIZE).toInt(), false); setLineCount(mSettings->value(CFG_KEY_LINECNT, PANEL_DEFAULT_LINE_COUNT).toInt(), false); setLength(mSettings->value(CFG_KEY_LENGTH, 100).toInt(), mSettings->value(CFG_KEY_PERCENT, true).toBool(), false); mScreenNum = mSettings->value(CFG_KEY_SCREENNUM, QApplication::desktop()->primaryScreen()).toInt(); setPosition(mScreenNum, strToPosition(mSettings->value(CFG_KEY_POSITION).toString(), PositionBottom), false); setAlignment(Alignment(mSettings->value(CFG_KEY_ALIGNMENT, mAlignment).toInt()), false); QColor color = mSettings->value(CFG_KEY_FONTCOLOR, "").value(); if (color.isValid()) setFontColor(color, true); setOpacity(mSettings->value(CFG_KEY_OPACITY, 100).toInt(), true); mReserveSpace = mSettings->value(CFG_KEY_RESERVESPACE, true).toBool(); color = mSettings->value(CFG_KEY_BACKGROUNDCOLOR, "").value(); if (color.isValid()) setBackgroundColor(color, true); QString image = mSettings->value(CFG_KEY_BACKGROUNDIMAGE, "").toString(); if (!image.isEmpty()) setBackgroundImage(image, false); mLockPanel = mSettings->value(CFG_KEY_LOCKPANEL, false).toBool(); mSettings->endGroup(); } /************************************************ ************************************************/ void UKUIPanel::saveSettings(bool later) { mDelaySave.stop(); if (later) { mDelaySave.start(); return; } mSettings->beginGroup(mConfigGroup); //Note: save/load of plugin names is completely handled by mPlugins object //mSettings->setValue(CFG_KEY_PLUGINS, mPlugins->pluginNames()); mSettings->setValue(CFG_KEY_PANELSIZE, mPanelSize); mSettings->setValue(CFG_KEY_ICONSIZE, mIconSize); mSettings->setValue(CFG_KEY_LINECNT, mLineCount); mSettings->setValue(CFG_KEY_LENGTH, mLength); mSettings->setValue(CFG_KEY_PERCENT, mLengthInPercents); mSettings->setValue(CFG_KEY_SCREENNUM, mScreenNum); mSettings->setValue(CFG_KEY_POSITION, positionToStr(mPosition)); mSettings->setValue(CFG_KEY_ALIGNMENT, mAlignment); mSettings->setValue(CFG_KEY_FONTCOLOR, mFontColor.isValid() ? mFontColor : QColor()); mSettings->setValue(CFG_KEY_BACKGROUNDCOLOR, mBackgroundColor.isValid() ? mBackgroundColor : QColor()); mSettings->setValue(CFG_KEY_BACKGROUNDIMAGE, QFileInfo(mBackgroundImage).exists() ? mBackgroundImage : QString()); mSettings->setValue(CFG_KEY_OPACITY, mOpacity); mSettings->setValue(CFG_KEY_RESERVESPACE, mReserveSpace); mSettings->setValue(CFG_KEY_HIDABLE, mHidable); mSettings->setValue(CFG_KEY_VISIBLE_MARGIN, mVisibleMargin); mSettings->setValue(CFG_KEY_ANIMATION, mAnimationTime); mSettings->setValue(CFG_KEY_SHOW_DELAY, mShowDelayTimer.interval()); mSettings->setValue(CFG_KEY_LOCKPANEL, mLockPanel); mSettings->endGroup(); } /************************************************ ************************************************/ void UKUIPanel::ensureVisible() { if (!canPlacedOn(mScreenNum, mPosition)) setPosition(findAvailableScreen(mPosition), mPosition, false); else mActualScreenNum = mScreenNum; // the screen size might be changed realign(); } /************************************************ ************************************************/ UKUIPanel::~UKUIPanel() { mLayout->setEnabled(false); delete mAnimation; delete mConfigDialog.data(); // do not save settings because of "user deleted panel" functionality saveSettings(); } /************************************************ ************************************************/ void UKUIPanel::show() { QWidget::show(); KWindowSystem::setOnDesktop(effectiveWinId(), NET::OnAllDesktops); } /************************************************ ************************************************/ QStringList pluginDesktopDirs() { QStringList dirs; dirs << QString(getenv("UKUI_PANEL_PLUGINS_DIR")).split(':', QString::SkipEmptyParts); dirs << QString("%1/%2").arg(XdgDirs::dataHome(), "/ukui/ukui-panel"); dirs << PLUGIN_DESKTOPS_DIR; return dirs; } /************************************************ ************************************************/ void UKUIPanel::loadPlugins() { QString names_key(mConfigGroup); names_key += '/'; names_key += QLatin1String(CFG_KEY_PLUGINS); mPlugins.reset(new PanelPluginsModel(this, names_key, pluginDesktopDirs())); connect(mPlugins.data(), &PanelPluginsModel::pluginAdded, mLayout, &UKUIPanelLayout::addPlugin); connect(mPlugins.data(), &PanelPluginsModel::pluginMovedUp, mLayout, &UKUIPanelLayout::moveUpPlugin); //reemit signals connect(mPlugins.data(), &PanelPluginsModel::pluginAdded, this, &UKUIPanel::pluginAdded); connect(mPlugins.data(), &PanelPluginsModel::pluginRemoved, this, &UKUIPanel::pluginRemoved); const auto plugins = mPlugins->plugins(); for (auto const & plugin : plugins) { mLayout->addPlugin(plugin); connect(plugin, &Plugin::dragLeft, [this] { mShowDelayTimer.stop(); hidePanel(); }); } } /************************************************ ************************************************/ int UKUIPanel::getReserveDimension() { return mHidable ? PANEL_HIDE_SIZE : qMax(PANEL_MINIMUM_SIZE, mPanelSize); } /* The setting frame of the old panel does not follow the main screen but can be displayed on any screen but the current desktop environment of ukui is set to follow the main screen All default parameters desktop()->screenGeometry are 0 */ void UKUIPanel::setPanelGeometry(bool animate) { const QRect currentScreen = QApplication::desktop()->screenGeometry(0); QRect rect; if (isHorizontal()) { // Horiz panel *************************** rect.setHeight(qMax(PANEL_MINIMUM_SIZE, mPanelSize)); if (mLengthInPercents) rect.setWidth(currentScreen.width() * mLength / 100.0); else { if (mLength <= 0) rect.setWidth(currentScreen.width() + mLength); else rect.setWidth(mLength); } rect.setWidth(qMax(rect.size().width(), mLayout->minimumSize().width())); // Horiz ...................... switch (mAlignment) { case UKUIPanel::AlignmentLeft: rect.moveLeft(currentScreen.left()); break; case UKUIPanel::AlignmentCenter: rect.moveCenter(currentScreen.center()); break; case UKUIPanel::AlignmentRight: rect.moveRight(currentScreen.right()); break; } // Vert ....................... if (mPosition == IUKUIPanel::PositionTop) { if (mHidden) rect.moveBottom(currentScreen.top() + PANEL_HIDE_SIZE - 1); else rect.moveTop(currentScreen.top()); } else { if (mHidden) rect.moveTop(currentScreen.bottom() - PANEL_HIDE_SIZE + 1); else rect.moveBottom(currentScreen.bottom()); } } else { // Vert panel *************************** rect.setWidth(qMax(PANEL_MINIMUM_SIZE, mPanelSize)); if (mLengthInPercents) rect.setHeight(currentScreen.height() * mLength / 100.0); else { if (mLength <= 0) rect.setHeight(currentScreen.height() + mLength); else rect.setHeight(mLength); } rect.setHeight(qMax(rect.size().height(), mLayout->minimumSize().height())); // Vert ....................... switch (mAlignment) { case UKUIPanel::AlignmentLeft: rect.moveTop(currentScreen.top()); break; case UKUIPanel::AlignmentCenter: rect.moveCenter(currentScreen.center()); break; case UKUIPanel::AlignmentRight: rect.moveBottom(currentScreen.bottom()); break; } // Horiz ...................... if (mPosition == IUKUIPanel::PositionLeft) { if (mHidden) rect.moveRight(currentScreen.left() + PANEL_HIDE_SIZE - 1); else rect.moveLeft(currentScreen.left()); } else { if (mHidden) rect.moveLeft(currentScreen.right() - PANEL_HIDE_SIZE + 1); else rect.moveRight(currentScreen.right()); } } if (rect != geometry()) { setFixedSize(rect.size()); if (animate) { if (mAnimation == nullptr) { mAnimation = new QPropertyAnimation(this, "geometry"); mAnimation->setEasingCurve(QEasingCurve::Linear); //Note: for hiding, the margins are set after animation is finished connect(mAnimation, &QAbstractAnimation::finished, [this] { if (mHidden) setMargins(); }); } mAnimation->setDuration(mAnimationTime); mAnimation->setStartValue(geometry()); mAnimation->setEndValue(rect); //Note: for showing-up, the margins are removed instantly if (!mHidden) setMargins(); mAnimation->start(); } else { setMargins(); setGeometry(rect); } } } void UKUIPanel::setMargins() { if (mHidden) { if (isHorizontal()) { if (mPosition == IUKUIPanel::PositionTop) mLayout->setContentsMargins(0, 0, 0, PANEL_HIDE_SIZE); else mLayout->setContentsMargins(0, PANEL_HIDE_SIZE, 0, 0); } else { if (mPosition == IUKUIPanel::PositionLeft) mLayout->setContentsMargins(0, 0, PANEL_HIDE_SIZE, 0); else mLayout->setContentsMargins(PANEL_HIDE_SIZE, 0, 0, 0); } if (!mVisibleMargin) setWindowOpacity(0.0); } else { mLayout->setContentsMargins(0, 0, 0, 0); if (!mVisibleMargin) setWindowOpacity(1.0); } } void UKUIPanel::realign() { QStringList sheet; // QGSettings *gsettings; // gsettings= new QGSettings("org.mate.interface", "", this); // QString mode; // mode=gsettings->get("gtk-theme").toString(); // qDebug()<<"ukui-theme:"<geometry(); const QRect rect = geometry(); // NOTE: https://standards.freedesktop.org/wm-spec/wm-spec-latest.html // Quote from the EWMH spec: " Note that the strut is relative to the screen edge, and not the edge of the xinerama monitor." // So, we use the geometry of the whole screen to calculate the strut rather than using the geometry of individual monitors. // Though the spec only mention Xinerama and did not mention XRandR, the rule should still be applied. // At least openbox is implemented like this. switch (mPosition) { case UKUIPanel::PositionTop: KWindowSystem::setExtendedStrut(wid, /* Left */ 0, 0, 0, /* Right */ 0, 0, 0, /* Top */ rect.top() + getReserveDimension(), rect.left(), rect.right(), /* Bottom */ 0, 0, 0 ); break; case UKUIPanel::PositionBottom: KWindowSystem::setExtendedStrut(wid, /* Left */ 0, 0, 0, /* Right */ 0, 0, 0, /* Top */ 0, 0, 0, /* Bottom */ wholeScreen.bottom() - rect.bottom() + getReserveDimension(), rect.left(), rect.right() ); break; case UKUIPanel::PositionLeft: KWindowSystem::setExtendedStrut(wid, /* Left */ rect.left() + getReserveDimension(), rect.top(), rect.bottom(), /* Right */ 0, 0, 0, /* Top */ 0, 0, 0, /* Bottom */ 0, 0, 0 ); break; case UKUIPanel::PositionRight: KWindowSystem::setExtendedStrut(wid, /* Left */ 0, 0, 0, /* Right */ wholeScreen.right() - rect.right() + getReserveDimension(), rect.top(), rect.bottom(), /* Top */ 0, 0, 0, /* Bottom */ 0, 0, 0 ); break; } } else { KWindowSystem::setExtendedStrut(wid, /* Left */ 0, 0, 0, /* Right */ 0, 0, 0, /* Top */ 0, 0, 0, /* Bottom */ 0, 0, 0 ); } } /************************************************ The panel can't be placed on boundary of two displays. This function checks if the panel can be placed on the display @screenNum on @position. ************************************************/ bool UKUIPanel::canPlacedOn(int screenNum, UKUIPanel::Position position) { QDesktopWidget* dw = QApplication::desktop(); switch (position) { case UKUIPanel::PositionTop: for (int i = 0; i < dw->screenCount(); ++i) if (dw->screenGeometry(i).bottom() < dw->screenGeometry(screenNum).top()) return false; return true; case UKUIPanel::PositionBottom: for (int i = 0; i < dw->screenCount(); ++i) if (dw->screenGeometry(i).top() > dw->screenGeometry(screenNum).bottom()) return false; return true; case UKUIPanel::PositionLeft: for (int i = 0; i < dw->screenCount(); ++i) if (dw->screenGeometry(i).right() < dw->screenGeometry(screenNum).left()) return false; return true; case UKUIPanel::PositionRight: for (int i = 0; i < dw->screenCount(); ++i) if (dw->screenGeometry(i).left() > dw->screenGeometry(screenNum).right()) return false; return true; } return false; } /************************************************ ************************************************/ int UKUIPanel::findAvailableScreen(UKUIPanel::Position position) { int current = mScreenNum; for (int i = current; i < QApplication::desktop()->screenCount(); ++i) if (canPlacedOn(i, position)) return i; for (int i = 0; i < current; ++i) if (canPlacedOn(i, position)) return i; return 0; } /************************************************ ************************************************/ void UKUIPanel::showConfigDialog() { // if (mConfigDialog.isNull()) // mConfigDialog = new ConfigPanelDialog(this, nullptr /*make it top level window*/); // mConfigDialog->showConfigPanelPage(); // mStandaloneWindows->observeWindow(mConfigDialog.data()); // mConfigDialog->show(); // mConfigDialog->raise(); // mConfigDialog->activateWindow(); // WId wid = mConfigDialog->windowHandle()->winId(); // KWindowSystem::activateWindow(wid); // KWindowSystem::setOnDesktop(wid, KWindowSystem::currentDesktop()); mConfigDialog = new ConfigPanelDialog(this, nullptr); mConfigDialog->show(); //mConfigWidget->positionChanged(); } /************************************************ ************************************************/ void UKUIPanel::showAddPluginDialog() { if (mConfigDialog.isNull()) mConfigDialog = new ConfigPanelDialog(this, nullptr /*make it top level window*/); mConfigDialog->showConfigPluginsPage(); mStandaloneWindows->observeWindow(mConfigDialog.data()); mConfigDialog->show(); mConfigDialog->raise(); mConfigDialog->activateWindow(); WId wid = mConfigDialog->windowHandle()->winId(); KWindowSystem::activateWindow(wid); KWindowSystem::setOnDesktop(wid, KWindowSystem::currentDesktop()); } /************************************************ ************************************************/ void UKUIPanel::setPanelStyle() { } void UKUIPanel::systeMonitor() { // system("mate-system-monitor"); if(QFileInfo::exists(QString("/usr/bin/mate-system-monitor"))) { QProcess *process =new QProcess(this); process->startDetached("/usr/bin/mate-system-monitor"); } else{qDebug()<<"not find /usr/bin/mate-system-monitor"< #include void UKUIPanel::showDesktop() { KWindowSystem::setShowingDesktop(!KWindowSystem::showingDesktop()); } void UKUIPanel::showTaskView() { system("ukui-window-switch --show-workspace"); } void UKUIPanel::updateStyleSheet() { // sheet << QString("Plugin > QAbstractButton, UKUiTray { qproperty-iconSize: %1px %1px; }").arg(mIconSize); // sheet << QString("Plugin > * > QAbstractButton, TrayIcon { qproperty-iconSize: %1px %1px; }").arg(mIconSize); // if (mFontColor.isValid()) // sheet << QString("Plugin * { color: " + mFontColor.name() + "; }"); // QString object = UKUIPanelWidget->objectName(); // if (mBackgroundColor.isValid()) // { // QString color = QString("%1, %2, %3, %4") // .arg(mBackgroundColor.red()) // .arg(mBackgroundColor.green()) // .arg(mBackgroundColor.blue()) // .arg((float) mOpacity / 100); //// sheet << QString("UKUIPanel #BackgroundWidget { background-color: rgba(" + color + "); }"); // } // sheet << QString("UKUIPanel #BackgroundWidget { background-color: rgba(8,10,12,90%); }"); // GSettings *settings = NULL; // QString str; // char *path; // char color_hex[10]; // path = g_strdup_printf ("%s/","/org/mate/desktop/interface"); // settings = g_settings_new_with_path ("org.mate.interface",path); // if(!strcmp(g_settings_get_string(settings, "gtk-theme"),"ukui-white")) // { // qDebug()<<"ukui-white"; // } } /************************************************ ************************************************/ void UKUIPanel::setPanelSize(int value, bool save) { if (mPanelSize != value) { mPanelSize = value; realign(); if (save) saveSettings(true); } } /************************************************ ************************************************/ void UKUIPanel::setIconSize(int value, bool save) { if (mIconSize != value) { mIconSize = value; updateStyleSheet(); mLayout->setLineSize(mIconSize); if (save) saveSettings(true); realign(); } } /************************************************ ************************************************/ void UKUIPanel::setLineCount(int value, bool save) { if (mLineCount != value) { mLineCount = value; mLayout->setEnabled(false); mLayout->setLineCount(mLineCount); mLayout->setEnabled(true); if (save) saveSettings(true); realign(); } } /************************************************ ************************************************/ void UKUIPanel::setLength(int length, bool inPercents, bool save) { if (mLength == length && mLengthInPercents == inPercents) return; mLength = length; mLengthInPercents = inPercents; if (save) saveSettings(true); realign(); } /************************************************ ************************************************/ void UKUIPanel::setPosition(int screen, IUKUIPanel::Position position, bool save) { if (mScreenNum == screen && mPosition == position) return; mActualScreenNum = screen; mPosition = position; mLayout->setPosition(mPosition); if (save) { mScreenNum = screen; saveSettings(true); } // Qt 5 adds a new class QScreen and add API for setting the screen of a QWindow. // so we had better use it. However, without this, our program should still work // as long as XRandR is used. Since XRandR combined all screens into a large virtual desktop // every screen and their virtual siblings are actually on the same virtual desktop. // So things still work if we don't set the screen correctly, but this is not the case // for other backends, such as the upcoming wayland support. Hence it's better to set it. if(windowHandle()) { // QScreen* newScreen = qApp->screens().at(screen); // QScreen* oldScreen = windowHandle()->screen(); // const bool shouldRecreate = windowHandle()->handle() && !(oldScreen && oldScreen->virtualSiblings().contains(newScreen)); // Q_ASSERT(shouldRecreate == false); // NOTE: When you move a window to another screen, Qt 5 might recreate the window as needed // But luckily, this never happen in XRandR, so Qt bug #40681 is not triggered here. // (The only exception is when the old screen is destroyed, Qt always re-create the window and // this corner case triggers #40681.) // When using other kind of multihead settings, such as Xinerama, this might be different and // unless Qt developers can fix their bug, we have no way to workaround that. windowHandle()->setScreen(qApp->screens().at(screen)); } realign(); } /************************************************ * ************************************************/ void UKUIPanel::setAlignment(Alignment value, bool save) { if (mAlignment == value) return; mAlignment = value; if (save) saveSettings(true); realign(); } /************************************************ * ************************************************/ void UKUIPanel::setFontColor(QColor color, bool save) { mFontColor = color; updateStyleSheet(); if (save) saveSettings(true); } /************************************************ ************************************************/ void UKUIPanel::setBackgroundColor(QColor color, bool save) { mBackgroundColor = color; updateStyleSheet(); if (save) saveSettings(true); } /************************************************ ************************************************/ void UKUIPanel::setBackgroundImage(QString path, bool save) { mBackgroundImage = path; updateStyleSheet(); if (save) saveSettings(true); } /************************************************ * ************************************************/ void UKUIPanel::setOpacity(int opacity, bool save) { mOpacity = opacity; updateStyleSheet(); if (save) saveSettings(true); } /************************************************ * ************************************************/ void UKUIPanel::setReserveSpace(bool reserveSpace, bool save) { if (mReserveSpace == reserveSpace) return; mReserveSpace = reserveSpace; if (save) saveSettings(true); updateWmStrut(); } /************************************************ ************************************************/ QRect UKUIPanel::globalGeometry() const { // panel is the the top-most widget/window, no calculation needed return geometry(); } /************************************************ ************************************************/ bool UKUIPanel::event(QEvent *event) { switch (event->type()) { case QEvent::ContextMenu: showPopupMenu(); break; case QEvent::LayoutRequest: emit realigned(); break; case QEvent::WinIdChange: { // qDebug() << "WinIdChange" << hex << effectiveWinId(); if(effectiveWinId() == 0) break; // Sometimes Qt needs to re-create the underlying window of the widget and // the winId() may be changed at runtime. So we need to reset all X11 properties // when this happens. qDebug() << "WinIdChange" << hex << effectiveWinId() << "handle" << windowHandle() << windowHandle()->screen(); // Qt::WA_X11NetWmWindowTypeDock becomes ineffective in Qt 5 // See QTBUG-39887: https://bugreports.qt-project.org/browse/QTBUG-39887 // Let's use KWindowSystem for that KWindowSystem::setType(effectiveWinId(), NET::Dock); updateWmStrut(); // reserve screen space for the panel KWindowSystem::setOnAllDesktops(effectiveWinId(), true); break; } case QEvent::DragEnter: dynamic_cast(event)->setDropAction(Qt::IgnoreAction); event->accept(); //no break intentionally case QEvent::Enter: mShowDelayTimer.start(); break; case QEvent::Leave: case QEvent::DragLeave: mShowDelayTimer.stop(); hidePanel(); break; default: break; } return QFrame::event(event); } /************************************************ ************************************************/ void UKUIPanel::showEvent(QShowEvent *event) { QFrame::showEvent(event); realign(); } /************************************************ ************************************************/ void UKUIPanel::showPopupMenu(Plugin *plugin) { PopupMenu * menu = new PopupMenu(tr("Panel"), this); menu->setAttribute(Qt::WA_DeleteOnClose); menu->setIcon(XdgIcon::fromTheme("configure-toolbars")); // Plugin Menu .............................. if (plugin) { QMenu *m = plugin->popupMenu(); if (m) { //menu->addTitle(plugin->windowTitle()); const auto actions = m->actions(); for (auto const & action : actions) { action->setParent(menu); action->setDisabled(mLockPanel); menu->addAction(action); } delete m; } } // Panel menu ............................... /* menu->addTitle(QIcon(), tr("Panel")); menu->addAction(XdgIcon::fromTheme(QLatin1String("configure")), tr("Configure Panel"), this, SLOT(showConfigDialog()) )->setDisabled(mLockPanel); menu->addAction(XdgIcon::fromTheme("preferences-plugin"), tr("Manage Widgets"), this, SLOT(showAddPluginDialog()) )->setDisabled(mLockPanel); */ /* menu->setWindowOpacity(0.9); menu->addAction(QIcon("/usr/share/ukui-panel/panel/img/setting.svg"), tr("Set up Panel"), this, SLOT(panelBackgroundChange()) )->setDisabled(mLockPanel); menu->addSeparator(); */ menu->addAction(XdgIcon::fromTheme(QLatin1String("configure")), tr("Show Taskview"), this, SLOT(showTaskView()) )->setDisabled(mLockPanel); menu->addAction(XdgIcon::fromTheme(QLatin1String("configure")), tr("Show Desktop"), this, SLOT(showDesktop()) )->setDisabled(mLockPanel); menu->addSeparator(); menu->addAction(XdgIcon::fromTheme(QLatin1String("list-remove")), tr("Show System Monitor"), this, SLOT(systeMonitor()) )->setDisabled(mLockPanel); menu->addSeparator(); QAction *pmenuaction_s; QAction *pmenuaction_m; QAction *pmenuaction_l; pmenuaction_s=new QAction(this); pmenuaction_s->setText(tr("Small")); pmenuaction_m=new QAction(this); pmenuaction_m->setText(tr("Media")); pmenuaction_l=new QAction(this); pmenuaction_l->setText(tr("Large")); QMenu *pmenu_panelsize; pmenu_panelsize=new QMenu(this); pmenu_panelsize->setTitle(tr("Adjustment Size")); pmenu_panelsize->addAction(pmenuaction_s); pmenu_panelsize->addAction(pmenuaction_m); pmenu_panelsize->addAction(pmenuaction_l); menu->addMenu(pmenu_panelsize); connect(pmenuaction_s,SIGNAL(triggered()),this,SLOT(changeSizeToSmall())); connect(pmenuaction_m,SIGNAL(triggered()),this,SLOT(changeSizeToMedium())); connect(pmenuaction_l,SIGNAL(triggered()),this,SLOT(changeSizeToLarge())); menu->addSeparator(); QAction *pmenuaction_top; QAction *pmenuaction_bottom; QAction *pmenuaction_left; QAction *pmenuaction_right; pmenuaction_top=new QAction(this); pmenuaction_top->setText(tr("Up")); pmenuaction_bottom=new QAction(this); pmenuaction_bottom->setText(tr("Bottom")); pmenuaction_left=new QAction(this); pmenuaction_left->setText(tr("Left")); pmenuaction_right=new QAction(this); pmenuaction_right->setText(tr("Right")); QMenu *pmenu_positon; pmenu_positon=new QMenu(this); pmenu_positon->setTitle(tr("Adjustment Position")); pmenu_positon->addAction(pmenuaction_top); pmenu_positon->addAction(pmenuaction_bottom); pmenu_positon->addAction(pmenuaction_left); pmenu_positon->addAction(pmenuaction_right); menu->addMenu(pmenu_positon); connect(pmenuaction_top,SIGNAL(triggered()),this,SLOT(changePositionToTop())); connect(pmenuaction_bottom,SIGNAL(triggered()),this,SLOT(changePositionToBottom())); connect(pmenuaction_left,SIGNAL(triggered()),this,SLOT(changePositionToLeft())); connect(pmenuaction_right,SIGNAL(triggered()),this,SLOT(changePositionToRight())); pmenu_positon->setDisabled(mLockPanel); /* UKUIPanelApplication *a = reinterpret_cast(qApp); menu->addAction(XdgIcon::fromTheme(QLatin1String("list-add")), tr("Add New Panel"), a, SLOT(addNewPanel()) ); if (a->count() > 1) { menu->addAction(XdgIcon::fromTheme(QLatin1String("list-remove")), tr("Remove Panel", "Menu Item"), this, SLOT(userRequestForDeletion()) )->setDisabled(mLockPanel); } */ QAction * act_lock = menu->addAction(tr("Lock This Panel")); act_lock->setCheckable(true); act_lock->setChecked(mLockPanel); connect(act_lock, &QAction::triggered, [this] { mLockPanel = !mLockPanel; saveSettings(false); }); //Hidden features, lock the panel /* menu->addAction(XdgIcon::fromTheme(QLatin1String("configure")), tr("Reset Panel"), this, SLOT(panelReset()) )->setDisabled(mLockPanel); */ #ifdef DEBUG menu->addSeparator(); menu->addAction("Exit (debug only)", qApp, SLOT(quit())); #endif /* Note: in multihead & multipanel setup the QMenu::popup/exec places the window * sometimes wrongly (it seems that this bug is somehow connected to misinterpretation * of QDesktopWidget::availableGeometry) */ menu->setGeometry(calculatePopupWindowPos(QCursor::pos(), menu->sizeHint())); willShowWindow(menu); menu->show(); } Plugin* UKUIPanel::findPlugin(const IUKUIPanelPlugin* iPlugin) const { const auto plugins = mPlugins->plugins(); for (auto const & plug : plugins) if (plug->iPlugin() == iPlugin) return plug; return nullptr; } /************************************************ ************************************************/ QRect UKUIPanel::calculatePopupWindowPos(QPoint const & absolutePos, QSize const & windowSize) const { int x = absolutePos.x(), y = absolutePos.y(); switch (position()) { case IUKUIPanel::PositionTop: y = globalGeometry().bottom(); break; case IUKUIPanel::PositionBottom: y = globalGeometry().top() - windowSize.height(); break; case IUKUIPanel::PositionLeft: x = globalGeometry().right(); break; case IUKUIPanel::PositionRight: x = globalGeometry().left() - windowSize.width(); break; } QRect res(QPoint(x, y), windowSize); QRect screen = QApplication::desktop()->screenGeometry(this); // NOTE: We cannot use AvailableGeometry() which returns the work area here because when in a // multihead setup with different resolutions. In this case, the size of the work area is limited // by the smallest monitor and may be much smaller than the current screen and we will place the // menu at the wrong place. This is very bad for UX. So let's use the full size of the screen. if (res.right() > screen.right()) res.moveRight(screen.right()); if (res.bottom() > screen.bottom()) res.moveBottom(screen.bottom()); if (res.left() < screen.left()) res.moveLeft(screen.left()); if (res.top() < screen.top()) res.moveTop(screen.top()); return res; } /************************************************ ************************************************/ QRect UKUIPanel::calculatePopupWindowPos(const IUKUIPanelPlugin *plugin, const QSize &windowSize) const { Plugin *panel_plugin = findPlugin(plugin); if (nullptr == panel_plugin) { qWarning() << Q_FUNC_INFO << "Wrong logic? Unable to find Plugin* for" << plugin << "known plugins follow..."; const auto plugins = mPlugins->plugins(); for (auto const & plug : plugins) qWarning() << plug->iPlugin() << plug; return QRect(); } // Note: assuming there are not contentMargins around the "BackgroundWidget" (UKUIPanelWidget) return calculatePopupWindowPos(globalGeometry().topLeft() + panel_plugin->geometry().topLeft(), windowSize); } /************************************************ ************************************************/ void UKUIPanel::willShowWindow(QWidget * w) { mStandaloneWindows->observeWindow(w); } /************************************************ ************************************************/ void UKUIPanel::pluginFlagsChanged(const IUKUIPanelPlugin * /*plugin*/) { mLayout->rebuild(); } /************************************************ ************************************************/ QString UKUIPanel::qssPosition() const { return positionToStr(position()); } /************************************************ ************************************************/ void UKUIPanel::pluginMoved(Plugin * plug) { //get new position of the moved plugin bool found{false}; QString plug_is_before; for (int i=0; icount(); ++i) { Plugin *plugin = qobject_cast(mLayout->itemAt(i)->widget()); if (plugin) { if (found) { //we found our plugin in previous cycle -> is before this (or empty as last) plug_is_before = plugin->settingsGroup(); break; } else found = (plug == plugin); } } mPlugins->movePlugin(plug, plug_is_before); } /************************************************ ************************************************/ void UKUIPanel::userRequestForDeletion() { const QMessageBox::StandardButton ret = QMessageBox::warning(this, tr("Remove Panel", "Dialog Title") , tr("Removing a panel can not be undone.\nDo you want to remove this panel?"), QMessageBox::Yes | QMessageBox::No); if (ret != QMessageBox::Yes) { return; } mSettings->beginGroup(mConfigGroup); const QStringList plugins = mSettings->value("plugins").toStringList(); mSettings->endGroup(); for(const QString& i : plugins) if (!i.isEmpty()) mSettings->remove(i); mSettings->remove(mConfigGroup); emit deletedByUser(this); } void UKUIPanel::showPanel(bool animate) { if (mHidable) { mHideTimer.stop(); if (mHidden) { mHidden = false; setPanelGeometry(mAnimationTime > 0 && animate); } } } void UKUIPanel::hidePanel() { if (mHidable && !mHidden && !mStandaloneWindows->isAnyWindowShown() ) mHideTimer.start(); } void UKUIPanel::hidePanelWork() { if (!geometry().contains(QCursor::pos())) { if (!mStandaloneWindows->isAnyWindowShown()) { mHidden = true; setPanelGeometry(mAnimationTime > 0); } else { mHideTimer.start(); } } } void UKUIPanel::setHidable(bool hidable, bool save) { if (mHidable == hidable) return; mHidable = hidable; if (save) saveSettings(true); realign(); } void UKUIPanel::setVisibleMargin(bool visibleMargin, bool save) { if (mVisibleMargin == visibleMargin) return; mVisibleMargin = visibleMargin; if (save) saveSettings(true); realign(); } void UKUIPanel::setAnimationTime(int animationTime, bool save) { if (mAnimationTime == animationTime) return; mAnimationTime = animationTime; if (save) saveSettings(true); } void UKUIPanel::setShowDelay(int showDelay, bool save) { if (mShowDelayTimer.interval() == showDelay) return; mShowDelayTimer.setInterval(showDelay); if (save) saveSettings(true); } QString UKUIPanel::iconTheme() const { return mSettings->value("iconTheme").toString(); } void UKUIPanel::setIconTheme(const QString& iconTheme) { UKUIPanelApplication *a = reinterpret_cast(qApp); a->setIconTheme(iconTheme); } void UKUIPanel::updateConfigDialog() const { if (!mConfigDialog.isNull() && mConfigDialog->isVisible()) { mConfigDialog->updateIconThemeSettings(); const QList widgets = mConfigDialog->findChildren(); for (QWidget *widget : widgets) widget->update(); } } bool UKUIPanel::isPluginSingletonAndRunnig(QString const & pluginId) const { Plugin const * plugin = mPlugins->pluginByID(pluginId); if (nullptr == plugin) return false; else return plugin->iPlugin()->flags().testFlag(IUKUIPanelPlugin::SingleInstance); } void UKUIPanel::setPanelPosition(Position position) { setPosition(0,position,true); } void UKUIPanel::changePositionToTop() { setPosition(0,PositionTop,true); gsettings->set(PANEL_POSITION_KEY,1); } void UKUIPanel::changePositionToBottom() { setPosition(0,PositionBottom,true); gsettings->set(PANEL_POSITION_KEY,0); } void UKUIPanel::changePositionToLeft() { setPosition(0,PositionLeft,true); gsettings->set(PANEL_POSITION_KEY,2); } void UKUIPanel::changePositionToRight() { this->setPosition(0,PositionRight,true); gsettings->set(PANEL_POSITION_KEY,3); } void UKUIPanel::changeSizeToSmall() { setPanelSize(PANEL_SIZE_SMALL,true); setIconSize(ICON_SIZE_SMALL,true); gsettings->set(PANEL_SIZE_KEY,PANEL_SIZE_SMALL); gsettings->set(ICON_SIZE_KEY,ICON_SIZE_SMALL); } void UKUIPanel::changeSizeToMedium() { setPanelSize(PANEL_SIZE_MEDIUM,true); setIconSize(ICON_SIZE_MEDIUM,true); gsettings->set(PANEL_SIZE_KEY,PANEL_SIZE_MEDIUM); gsettings->set(ICON_SIZE_KEY,ICON_SIZE_MEDIUM); } void UKUIPanel::changeSizeToLarge() { setPanelSize(PANEL_SIZE_LARGE,true); setIconSize(ICON_SIZE_MEDIUM,true); gsettings->set(PANEL_SIZE_KEY,PANEL_SIZE_LARGE); gsettings->set(ICON_SIZE_KEY,ICON_SIZE_LARGE); } void UKUIPanel::panelReset() { QFile::remove(QString(qgetenv("HOME"))+"/.config/lxqt/panel.conf"); system("killall ukui-panel"); } void UKUIPanel::panelBackgroundChange() { qDebug()<<"panel background change ***"; if(mConfigDialog.isNull()) { mConfigDialog = new ConfigPanelDialog(this, nullptr); } mConfigDialog->backgroundChange(); } ukui-panel/panel/plugin.h0000644000175000017500000000736213632320722014326 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef PLUGIN_H #define PLUGIN_H #include #include #include //#include //#include #include "common/ukuisettings.h" #include "common/ukuiplugininfo.h" #include "iukuipanel.h" #include "ukuipanelglobals.h" #include "pluginsettings.h" class QPluginLoader; class QSettings; class IUKUIPanelPlugin; class IUKUIPanelPluginLibrary; class UKUIPanel; class QMenu; class UKUI_PANEL_API Plugin : public QFrame { Q_OBJECT Q_PROPERTY(QColor moveMarkerColor READ moveMarkerColor WRITE setMoveMarkerColor) public: enum Alignment { AlignLeft, AlignRight }; explicit Plugin(const UKUi::PluginInfo &desktopFile, UKUi::Settings *settings, const QString &settingsGroup, UKUIPanel *panel); ~Plugin(); bool isLoaded() const { return mPlugin != 0; } Alignment alignment() const { return mAlignment; } void setAlignment(Alignment alignment); QString settingsGroup() const { return mSettings->group(); } void saveSettings(); QMenu* popupMenu() const; const IUKUIPanelPlugin * iPlugin() const { return mPlugin; } const UKUi::PluginInfo desktopFile() const { return mDesktopFile; } bool isSeparate() const; bool isExpandable() const; QWidget *widget() { return mPluginWidget; } QString name() const { return mName; } virtual bool eventFilter(QObject * watched, QEvent * event); // For QSS properties .................. static QColor moveMarkerColor() { return mMoveMarkerColor; } static void setMoveMarkerColor(QColor color) { mMoveMarkerColor = color; } public slots: void realign(); void showConfigureDialog(); void requestRemove(); signals: void startMove(); void remove(); /*! * \brief Signal emitted when this widget or some of its children * get the DragLeave event delivered. */ void dragLeft(); protected: void contextMenuEvent(QContextMenuEvent *event); void mousePressEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); void showEvent(QShowEvent *event); private: bool loadLib(IUKUIPanelPluginLibrary const * pluginLib); bool loadModule(const QString &libraryName); IUKUIPanelPluginLibrary const * findStaticPlugin(const QString &libraryName); void watchWidgets(QObject * const widget); void unwatchWidgets(QObject * const widget); const UKUi::PluginInfo mDesktopFile; QPluginLoader *mPluginLoader; IUKUIPanelPlugin *mPlugin; QWidget *mPluginWidget; Alignment mAlignment; PluginSettings *mSettings; UKUIPanel *mPanel; static QColor mMoveMarkerColor; QString mName; QPointer mConfigDialog; //!< plugin's config dialog (if any) private slots: void settingsChanged(); }; #endif // PLUGIN_H ukui-panel/panel/img/0000755000175000017500000000000013633355350013431 5ustar fengfengukui-panel/panel/img/tick.svg0000644000175000017500000000102613632320722015075 0ustar fengfeng ukui-panel/panel/img/setting.svg0000644000175000017500000000177213632320722015630 0ustar fengfeng ukui-panel/panel/img/nightmode-light.svg0000644000175000017500000000173513633070712017237 0ustar fengfeng 24 ukui-panel/panel/img/nightmode-night.svg0000644000175000017500000000253613633070712017241 0ustar fengfeng 24 ukui-panel/panel/img/startmenu.svg0000644000175000017500000001316113633355350016176 0ustar fengfeng ukui-panel/panel/img/taskview.svg0000644000175000017500000000057013633070712016005 0ustar fengfeng32ukui-panel/panel/img/up.svg0000644000175000017500000000103513632320722014567 0ustar fengfeng ukui-panel/panel/config/0000755000175000017500000000000013640356061014120 5ustar fengfengukui-panel/panel/config/configpanelwidget.h0000644000175000017500000001236413632320722017764 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Marat "Morion" Talipov * * Copyright: 2019-2020 UKUI team * modified by hepuyao * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef CONFIGPANELWIDGET_H #define CONFIGPANELWIDGET_H #include "../ukuipanel.h" #include #include //#include #include "../common/ukuiconfigdialog.h" #include class UKUIPanel; namespace Ui { class ConfigPanelWidget; } class ConfigPanelWidget : public QWidget { Q_OBJECT public: explicit ConfigPanelWidget(UKUIPanel *panel, QWidget *parent = 0); ~ConfigPanelWidget(); friend class FileSetPanel; int screenNum() const { return mScreenNum; } IUKUIPanel::Position position() const { return mPosition; } void updateIconThemeSettings(); IUKUIPanel::Position mPosition; void editChangedByManual(); signals: void changed(); public slots: void reset(); void positionChanged_top(); void positionChanged_bottom(); void positionChanged_left(); void positionChanged_right(); void changeToMidSize(); void changeToLargeSize(); void changeToSmallSize(); void changeBackground(); private slots: void editChanged(); void widthTypeChanged(); void positionChanged(); void pickFontColor(); void pickBackgroundColor(); void pickBackgroundImage(); private: Ui::ConfigPanelWidget *ui; UKUIPanel *mPanel; int mScreenNum; void addPosition(const QString& name, int screen, UKUIPanel::Position position); void fillComboBox_position(); void fillComboBox_alignment(); void fillComboBox_icon(); int indexForPosition(int screen, IUKUIPanel::Position position); int getMaxLength(); // new values QColor mFontColor; QColor mBackgroundColor; // old values for reset uint mOldPanelSize; int mOldIconSize; int mOldLineCount; int mOldLength; bool mOldLengthInPercents; UKUIPanel::Alignment mOldAlignment; IUKUIPanel::Position mOldPosition; bool mOldHidable; bool mOldVisibleMargin; int mOldAnimation; int mOldShowDelay; int mOldScreenNum; QColor mOldFontColor; QColor mOldBackgroundColor; QString mOldBackgroundImage; int mOldOpacity; bool mOldReserveSpace; public slots: bool SetPanelsizeSmall(QString arg); bool SetPanelsizeMid(QString arg); bool SetPanelsizeLarge(QString arg); bool SetPanelPositionLeft(QString arg); bool SetPanelPositionRight(QString arg); bool SetPanelPositionUp(QString arg); bool SetPanelPositionBottom(QString arg); }; class FileSetPanel: public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "panelset.DBus") Q_CLASSINFO("D-Bus Introspection", "" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "") public: FileSetPanel(QObject *parent); virtual ~FileSetPanel(); public: // PROPERTIES public Q_SLOTS: // METHODS bool SetPanelsizeSmall(const QString &arg); bool SetPanelsizeMid(const QString &arg); bool SetPanelsizeLarge(const QString &arg); bool SetPanelPositionLeft(const QString &arg); bool SetPanelPositionRight(const QString &arg); bool SetPanelPositionUp(const QString &arg); bool SetPanelPositionBottom(const QString &arg); Q_SIGNALS: // SIGNALS signals: void addtak(int); }; #endif ukui-panel/panel/config/configpaneldialog.h0000644000175000017500000000367213632320722017742 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Marat "Morion" Talipov * * Copyright: 2019-2020 UKUI team * modified by hepuyao * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef CONFIGPANELDIALOG_H #define CONFIGPANELDIALOG_H #include "configpanelwidget.h" #include "configpluginswidget.h" #include "../ukuipanel.h" //#include #include "../common/ukuiconfigdialog.h" class ConfigPanelDialog : public UKUi::ConfigDialog { Q_OBJECT public: ConfigPanelDialog(UKUIPanel *panel, QWidget *parent = 0); //this three funtion influnce nothing void showConfigPanelPage(); void showConfigPluginsPage(); void updateIconThemeSettings(); private: ConfigPanelWidget *mPanelPage; ConfigPluginsWidget *mPluginsPage; public slots: //void testpaneldig(); public slots: void configPosition_top(); void configPosition_bottom(); void configPosition_left(); void configPosition_right(); void configPanelSize_m(); void configPanelSize_l(); void configPanelSize_S(); void backgroundChange(); signals: void testsig(); }; #endif // CONFIGPANELDIALOG_H ukui-panel/panel/config/configpluginswidget.h0000644000175000017500000000315313633355350020350 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * Paulo Lieuthier * * Copyright: 2019-2020 UKUI team * modified by hepuyao * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef CONFIGPLUGINSWIDGET_H #define CONFIGPLUGINSWIDGET_H #include "../ukuipanel.h" #include #include "comm_func.h" namespace Ui { class ConfigPluginsWidget; } class AddPluginDialog; class ConfigPluginsWidget : public QWidget { Q_OBJECT public: ConfigPluginsWidget(UKUIPanel *panel, QWidget* parent = 0); ~ConfigPluginsWidget(); signals: void changed(); public slots: void reset(); private slots: void showAddPluginDialog(); void resetButtons(); private: Ui::ConfigPluginsWidget *ui; QScopedPointer mAddPluginDialog; UKUIPanel *mPanel; }; #endif ukui-panel/panel/config/addplugindialog.h0000644000175000017500000000317513633355350017430 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019-2020 LXQt team * Modified by hepuyao * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUI_ADDPLUGINDIALOG_H #define UKUI_ADDPLUGINDIALOG_H //#include #include "../panel/common/ukuiplugininfo.h" #include #include #define SEARCH_DELAY 125 namespace Ui { class AddPluginDialog; } class AddPluginDialog : public QDialog { Q_OBJECT public: AddPluginDialog(QWidget *parent = 0); ~AddPluginDialog(); signals: void pluginSelected(const UKUi::PluginInfo &plugin); private: Ui::AddPluginDialog *ui; UKUi::PluginInfoList mPlugins; QTimer mSearchTimer; private slots: void filter(); void emitPluginSelected(); }; #endif // UKUI_ADDPLUGINDIALOG_H ukui-panel/panel/config/configpanelwidget.cpp0000644000175000017500000006531413640356061020326 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Marat "Morion" Talipov * * Copyright: 2019-2020 UKUI team * modified by hepuyao * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "configpanelwidget.h" #include "ui_configpanelwidget.h" #include "../ukuipanellimits.h" #include #include #include #include #include #include #include #include #include using namespace UKUi; #define GSETTINGS_SCHEMA_SCREENSAVER "org.mate.interface" #define KEY_MODE "gtk-theme" struct ScreenPosition { int screen; IUKUIPanel::Position position; }; Q_DECLARE_METATYPE(ScreenPosition) ConfigPanelWidget::ConfigPanelWidget(UKUIPanel *panel, QWidget *parent) : QWidget(parent), ui(new Ui::ConfigPanelWidget), mPanel(panel) { ui->setupUi(this); fillComboBox_position(); fillComboBox_alignment(); fillComboBox_icon(); mOldPanelSize = mPanel->panelSize(); mOldIconSize = mPanel->iconSize(); mOldLineCount = mPanel->lineCount(); mOldLength = mPanel->length(); mOldLengthInPercents = mPanel->lengthInPercents(); mOldAlignment = mPanel->alignment(); mOldScreenNum = mPanel->screenNum(); mScreenNum = mOldScreenNum; mOldPosition = mPanel->position(); mPosition = mOldPosition; mOldHidable = mPanel->hidable(); mOldVisibleMargin = mPanel->visibleMargin(); mOldAnimation = mPanel->animationTime(); mOldShowDelay = mPanel->showDelay(); ui->spinBox_panelSize->setMinimum(PANEL_MINIMUM_SIZE); ui->spinBox_panelSize->setMaximum(PANEL_MAXIMUM_SIZE); mOldFontColor = mPanel->fontColor(); mFontColor = mOldFontColor; mOldBackgroundColor = mPanel->backgroundColor(); mBackgroundColor = mOldBackgroundColor; mOldBackgroundImage = mPanel->backgroundImage(); mOldOpacity = mPanel->opacity(); mOldReserveSpace = mPanel->reserveSpace(); // reset configurations from file reset(); connect(ui->spinBox_panelSize, SIGNAL(valueChanged(int)), this, SLOT(editChanged())); connect(ui->spinBox_iconSize, SIGNAL(valueChanged(int)), this, SLOT(editChanged())); connect(ui->spinBox_lineCount, SIGNAL(valueChanged(int)), this, SLOT(editChanged())); connect(ui->spinBox_length, SIGNAL(valueChanged(int)), this, SLOT(editChanged())); connect(ui->comboBox_lenghtType, SIGNAL(activated(int)), this, SLOT(widthTypeChanged())); connect(ui->comboBox_alignment, SIGNAL(activated(int)), this, SLOT(editChanged())); connect(ui->comboBox_position, SIGNAL(activated(int)), this, SLOT(positionChanged())); connect(ui->checkBox_hidable, SIGNAL(toggled(bool)), this, SLOT(editChanged())); connect(ui->checkBox_visibleMargin, SIGNAL(toggled(bool)), this, SLOT(editChanged())); connect(ui->spinBox_animation, SIGNAL(valueChanged(int)), this, SLOT(editChanged())); connect(ui->spinBox_delay, SIGNAL(valueChanged(int)), this, SLOT(editChanged())); connect(ui->checkBox_customFontColor, SIGNAL(toggled(bool)), this, SLOT(editChanged())); connect(ui->pushButton_customFontColor, SIGNAL(clicked(bool)), this, SLOT(pickFontColor())); connect(ui->checkBox_customBgColor, SIGNAL(toggled(bool)), this, SLOT(editChanged())); connect(ui->pushButton_customBgColor, SIGNAL(clicked(bool)), this, SLOT(pickBackgroundColor())); connect(ui->checkBox_customBgImage, SIGNAL(toggled(bool)), this, SLOT(editChanged())); connect(ui->lineEdit_customBgImage, SIGNAL(textChanged(QString)), this, SLOT(editChanged())); connect(ui->pushButton_customBgImage, SIGNAL(clicked(bool)), this, SLOT(pickBackgroundImage())); connect(ui->slider_opacity, &QSlider::valueChanged, this, &ConfigPanelWidget::editChanged); connect(ui->checkBox_reserveSpace, &QAbstractButton::toggled, [this](bool checked) { mPanel->setReserveSpace(checked, true); }); connect(ui->groupBox_icon, &QGroupBox::clicked, this, &ConfigPanelWidget::editChanged); connect(ui->comboBox_icon, QOverload::of(&QComboBox::activated), this, &ConfigPanelWidget::editChanged); QStringList sheet; QGSettings *gsettings; gsettings= new QGSettings("org.mate.interface", "", this); connect(gsettings,&QGSettings::changed,this,&ConfigPanelWidget::reset); } /************************************************ * ************************************************/ void ConfigPanelWidget::reset() { QStringList sheet; // QGSettings *gsettings; // gsettings= new QGSettings("org.mate.interface", "", this); // QString mode; // mode=gsettings->get("gtk-theme").toString(); // qDebug()<<"ukui-theme:"<spinBox_panelSize->setValue(mOldPanelSize); ui->spinBox_iconSize->setValue(mOldIconSize); ui->spinBox_lineCount->setValue(mOldLineCount); ui->comboBox_position->setCurrentIndex(indexForPosition(mOldScreenNum, mOldPosition)); ui->checkBox_hidable->setChecked(mOldHidable); ui->checkBox_visibleMargin->setChecked(mOldVisibleMargin); ui->spinBox_animation->setValue(mOldAnimation); ui->spinBox_delay->setValue(mOldShowDelay); fillComboBox_alignment(); ui->comboBox_alignment->setCurrentIndex(mOldAlignment + 1); ui->comboBox_lenghtType->setCurrentIndex(mOldLengthInPercents ? 0 : 1); widthTypeChanged(); ui->spinBox_length->setValue(mOldLength); mFontColor.setNamedColor(mOldFontColor.name()); ui->pushButton_customFontColor->setStyleSheet(QString("background: %1").arg(mOldFontColor.name())); mBackgroundColor.setNamedColor(mOldBackgroundColor.name()); ui->pushButton_customBgColor->setStyleSheet(QString("background: %1").arg(mOldBackgroundColor.name())); ui->lineEdit_customBgImage->setText(mOldBackgroundImage); ui->slider_opacity->setValue(mOldOpacity); ui->checkBox_reserveSpace->setChecked(mOldReserveSpace); ui->checkBox_customFontColor->setChecked(mOldFontColor.isValid()); ui->checkBox_customBgColor->setChecked(mOldBackgroundColor.isValid()); ui->checkBox_customBgImage->setChecked(QFileInfo(mOldBackgroundImage).exists()); // update position positionChanged(); } /************************************************ * ************************************************/ void ConfigPanelWidget::fillComboBox_position() { int screenCount = QApplication::desktop()->screenCount(); if (screenCount == 1) { addPosition(tr("Top of desktop"), 0, UKUIPanel::PositionTop); addPosition(tr("Left of desktop"), 0, UKUIPanel::PositionLeft); addPosition(tr("Right of desktop"), 0, UKUIPanel::PositionRight); addPosition(tr("Bottom of desktop"), 0, UKUIPanel::PositionBottom); } else { for (int screenNum = 0; screenNum < screenCount; screenNum++) { if (screenNum) ui->comboBox_position->insertSeparator(9999); addPosition(tr("Top of desktop %1").arg(screenNum +1), screenNum, UKUIPanel::PositionTop); addPosition(tr("Left of desktop %1").arg(screenNum +1), screenNum, UKUIPanel::PositionLeft); addPosition(tr("Right of desktop %1").arg(screenNum +1), screenNum, UKUIPanel::PositionRight); addPosition(tr("Bottom of desktop %1").arg(screenNum +1), screenNum, UKUIPanel::PositionBottom); } } } /************************************************ * ************************************************/ void ConfigPanelWidget::fillComboBox_alignment() { ui->comboBox_alignment->setItemData(0, QVariant(UKUIPanel::AlignmentLeft)); ui->comboBox_alignment->setItemData(1, QVariant(UKUIPanel::AlignmentCenter)); ui->comboBox_alignment->setItemData(2, QVariant(UKUIPanel::AlignmentRight)); if (mPosition == IUKUIPanel::PositionTop || mPosition == IUKUIPanel::PositionBottom) { ui->comboBox_alignment->setItemText(0, tr("Left")); ui->comboBox_alignment->setItemText(1, tr("Center")); ui->comboBox_alignment->setItemText(2, tr("Right")); } else { ui->comboBox_alignment->setItemText(0, tr("Top")); ui->comboBox_alignment->setItemText(1, tr("Center")); ui->comboBox_alignment->setItemText(2, tr("Bottom")); }; } /************************************************ * ************************************************/ void ConfigPanelWidget::fillComboBox_icon() { ui->groupBox_icon->setChecked(!mPanel->iconTheme().isEmpty()); QStringList themeList; QStringList processed; const QStringList baseDirs = QIcon::themeSearchPaths(); for (const QString &baseDirName : baseDirs) { QDir baseDir(baseDirName); if (!baseDir.exists()) continue; const QFileInfoList dirs = baseDir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name); for (const QFileInfo &dir : dirs) { if (!processed.contains(dir.canonicalFilePath())) { processed << dir.canonicalFilePath(); QDir Dir(dir.canonicalFilePath()); QSettings file(Dir.absoluteFilePath(QStringLiteral("index.theme")), QSettings::IniFormat); if (file.status() == QSettings::NoError && !file.value(QStringLiteral("Icon Theme/Directories")).toStringList().join(QLatin1Char(' ')).isEmpty() && !file.value(QStringLiteral("Icon Theme/Hidden"), false).toBool()) { themeList << Dir.dirName(); } } } } if (!themeList.isEmpty()) { themeList.sort(); ui->comboBox_icon->insertItems(0, themeList); QString curTheme = QIcon::themeName(); if (!curTheme.isEmpty()) ui->comboBox_icon->setCurrentText(curTheme); } } /************************************************ * ************************************************/ void ConfigPanelWidget::updateIconThemeSettings() { ui->groupBox_icon->setChecked(!mPanel->iconTheme().isEmpty()); QString curTheme = QIcon::themeName(); if (!curTheme.isEmpty()) ui->comboBox_icon->setCurrentText(curTheme); } /************************************************ * ************************************************/ void ConfigPanelWidget::addPosition(const QString& name, int screen, UKUIPanel::Position position) { if (UKUIPanel::canPlacedOn(screen, position)) ui->comboBox_position->addItem(name, QVariant::fromValue((ScreenPosition){screen, position})); } /************************************************ * ************************************************/ int ConfigPanelWidget::indexForPosition(int screen, IUKUIPanel::Position position) { for (int i = 0; i < ui->comboBox_position->count(); i++) { ScreenPosition sp = ui->comboBox_position->itemData(i).value(); if (screen == sp.screen && position == sp.position) return i; } return -1; } /************************************************ * ************************************************/ ConfigPanelWidget::~ConfigPanelWidget() { delete ui; } /************************************************ * ************************************************/ void ConfigPanelWidget::editChanged() { QStringList sheet; // QGSettings *gsettings; // gsettings= new QGSettings("org.mate.interface", "", this); // QString mode; // mode=gsettings->get("gtk-theme").toString(); // qDebug()<<"ukui-theme:"<setPanelSize(ui->spinBox_panelSize->value(), true); mPanel->setIconSize(ui->spinBox_iconSize->value(), true); mPanel->setLineCount(ui->spinBox_lineCount->value(), true); mPanel->setLength(ui->spinBox_length->value(), ui->comboBox_lenghtType->currentIndex() == 0, true); UKUIPanel::Alignment align = UKUIPanel::Alignment( ui->comboBox_alignment->itemData( ui->comboBox_alignment->currentIndex() ).toInt()); mPanel->setAlignment(align, true); mPanel->setPosition(mScreenNum, mPosition, true); mPanel->setHidable(ui->checkBox_hidable->isChecked(), true); mPanel->setVisibleMargin(ui->checkBox_visibleMargin->isChecked(), true); mPanel->setAnimationTime(ui->spinBox_animation->value(), true); mPanel->setShowDelay(ui->spinBox_delay->value(), true); mPanel->setFontColor(ui->checkBox_customFontColor->isChecked() ? mFontColor : QColor(), true); if (ui->checkBox_customBgColor->isChecked()) { mPanel->setBackgroundColor(mBackgroundColor, true); mPanel->setOpacity(ui->slider_opacity->value(), true); } else { mPanel->setBackgroundColor(QColor(), true); mPanel->setOpacity(100, true); } QString image = ui->checkBox_customBgImage->isChecked() ? ui->lineEdit_customBgImage->text() : QString(); mPanel->setBackgroundImage(image, true); if (!ui->groupBox_icon->isChecked()) mPanel->setIconTheme(QString()); else if (!ui->comboBox_icon->currentText().isEmpty()) mPanel->setIconTheme(ui->comboBox_icon->currentText()); } /************************************************ * ************************************************/ void ConfigPanelWidget::widthTypeChanged() { int max = getMaxLength(); if (ui->comboBox_lenghtType->currentIndex() == 0) { // Percents ............................. int v = ui->spinBox_length->value() * 100.0 / max; ui->spinBox_length->setRange(1, 100); ui->spinBox_length->setValue(v); } else { // Pixels ............................... int v = max / 100.0 * ui->spinBox_length->value(); ui->spinBox_length->setRange(-max, max); ui->spinBox_length->setValue(v); } } /************************************************ * ************************************************/ int ConfigPanelWidget::getMaxLength() { QDesktopWidget* dw = QApplication::desktop(); if (mPosition == IUKUIPanel::PositionTop || mPosition == IUKUIPanel::PositionBottom) return dw->screenGeometry(mScreenNum).width(); else return dw->screenGeometry(mScreenNum).height(); } /************************************************ * ************************************************/ void ConfigPanelWidget::positionChanged() { ScreenPosition sp = ui->comboBox_position->itemData( ui->comboBox_position->currentIndex()).value(); bool updateAlig = (sp.position == IUKUIPanel::PositionTop || sp.position == IUKUIPanel::PositionBottom) != (mPosition == IUKUIPanel::PositionTop || mPosition == IUKUIPanel::PositionBottom); int oldMax = getMaxLength(); mPosition = sp.position; mScreenNum = sp.screen; int newMax = getMaxLength(); if (ui->comboBox_lenghtType->currentIndex() == 1 && oldMax != newMax) { // Pixels ............................... int v = ui->spinBox_length->value() * 1.0 * newMax / oldMax; ui->spinBox_length->setMaximum(newMax); ui->spinBox_length->setValue(v); } if (updateAlig) fillComboBox_alignment(); editChanged(); } /************************************************ * ************************************************/ void ConfigPanelWidget::pickFontColor() { QColorDialog d(QColor(mFontColor.name()), this); d.setWindowTitle(tr("Pick color")); d.setWindowModality(Qt::WindowModal); if (d.exec() && d.currentColor().isValid()) { mFontColor.setNamedColor(d.currentColor().name()); ui->pushButton_customFontColor->setStyleSheet(QString("background: %1").arg(mFontColor.name())); editChanged(); } } /************************************************ * ************************************************/ void ConfigPanelWidget::pickBackgroundColor() { QColorDialog d(QColor(mBackgroundColor.name()), this); d.setWindowTitle(tr("Pick color")); d.setWindowModality(Qt::WindowModal); if (d.exec() && d.currentColor().isValid()) { mBackgroundColor.setNamedColor(d.currentColor().name()); ui->pushButton_customBgColor->setStyleSheet(QString("background: %1").arg(mBackgroundColor.name())); editChanged(); } } /************************************************ * ************************************************/ void ConfigPanelWidget::pickBackgroundImage() { QString picturesLocation; picturesLocation = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); QFileDialog* d = new QFileDialog(this, tr("Pick image"), picturesLocation, tr("Images (*.png *.gif *.jpg)")); d->setAttribute(Qt::WA_DeleteOnClose); d->setWindowModality(Qt::WindowModal); connect(d, &QFileDialog::fileSelected, ui->lineEdit_customBgImage, &QLineEdit::setText); d->show(); } void ConfigPanelWidget::positionChanged_top() { mPosition =IUKUIPanel::PositionTop; editChanged(); mOldScreenNum = mScreenNum; mOldPosition = mPosition; QDBusMessage message = QDBusMessage::createMethodCall("com.ukui.panel.sidebar", "/getvalue/panel", "com.ukui.panel.sidebar.value", "panelPositionChangeNotify"); uint position=mPosition; message << position; QDBusConnection::sessionBus().send(message); QDBusMessage menuMessage = QDBusMessage::createMethodCall("com.ukui.panel.menu", "/getvalue/panel", "com.ukui.panel.sidebar.value", "panelPositionChangeNotify"); menuMessage << position; QDBusConnection::sessionBus().send(menuMessage); } void ConfigPanelWidget::positionChanged_bottom() { mPosition =IUKUIPanel::PositionBottom; editChanged(); mOldScreenNum = mScreenNum; mOldPosition = mPosition; QDBusMessage message = QDBusMessage::createMethodCall("com.ukui.panel.sidebar", "/getvalue/panel", "com.ukui.panel.sidebar.value", "panelPositionChangeNotify"); uint position=mPosition; message << position; QDBusConnection::sessionBus().send(message); QDBusMessage menuMessage = QDBusMessage::createMethodCall("com.ukui.panel.menu", "/getvalue/panel", "com.ukui.panel.sidebar.value", "panelPositionChangeNotify"); menuMessage << position; QDBusConnection::sessionBus().send(menuMessage); } void ConfigPanelWidget::positionChanged_left() { mPosition =IUKUIPanel::PositionLeft; editChanged(); mOldScreenNum = mScreenNum; mOldPosition = mPosition; QDBusMessage message = QDBusMessage::createMethodCall("com.ukui.panel.sidebar", "/getvalue/panel", "com.ukui.panel.sidebar.value", "panelPositionChangeNotify"); uint position=mPosition; message << position; QDBusConnection::sessionBus().send(message); QDBusMessage menuMessage = QDBusMessage::createMethodCall("com.ukui.panel.menu", "/getvalue/panel", "com.ukui.panel.sidebar.value", "panelPositionChangeNotify"); menuMessage << position; QDBusConnection::sessionBus().send(menuMessage); } void ConfigPanelWidget::positionChanged_right() { mPosition =IUKUIPanel::PositionRight; editChanged(); mOldScreenNum = mScreenNum; mOldPosition = mPosition; QDBusMessage message = QDBusMessage::createMethodCall("com.ukui.panel.sidebar", "/getvalue/panel", "com.ukui.panel.sidebar.value", "panelPositionChangeNotify"); uint position=mPosition; message << position; QDBusConnection::sessionBus().send(message); QDBusMessage menuMessage = QDBusMessage::createMethodCall("com.ukui.panel.menu", "/getvalue/panel", "com.ukui.panel.sidebar.value", "panelPositionChangeNotify"); menuMessage << position; QDBusConnection::sessionBus().send(menuMessage); } void ConfigPanelWidget::changeToSmallSize() { mOldPanelSize = 46; mOldIconSize = 32; editChanged(); QDBusMessage message = QDBusMessage::createMethodCall("com.ukui.panel.sidebar", "/getvalue/panel", "com.ukui.panel.sidebar.value", "panelSizeChangeNotify"); message << mOldPanelSize; QDBusConnection::sessionBus().send(message); QDBusMessage menuMessage = QDBusMessage::createMethodCall("com.ukui.panel.menu", "/getvalue/panel", "com.ukui.panel.sidebar.value", "panelSizeChangeNotify"); menuMessage << mOldPanelSize; QDBusConnection::sessionBus().send(menuMessage); reset(); } void ConfigPanelWidget::changeToMidSize() { mOldPanelSize = 72; mOldIconSize = 48; editChanged(); QDBusMessage message = QDBusMessage::createMethodCall("com.ukui.panel.sidebar", "/getvalue/panel", "com.ukui.panel.sidebar.value", "panelSizeChangeNotify"); message << mOldPanelSize; QDBusConnection::sessionBus().send(message); reset(); } void ConfigPanelWidget::changeToLargeSize() { mOldPanelSize = 94; mOldIconSize = 64; editChanged(); QDBusMessage message = QDBusMessage::createMethodCall("com.ukui.panel.sidebar", "/getvalue/panel", "com.ukui.panel.sidebar.value", "panelSizeChangeNotify"); message << mOldPanelSize; QDBusConnection::sessionBus().send(message); QDBusMessage menuMessage = QDBusMessage::createMethodCall("com.ukui.panel.menu", "/getvalue/panel", "com.ukui.panel.sidebar.value", "panelSizeChangeNotify"); menuMessage << mOldPanelSize; QDBusConnection::sessionBus().send(menuMessage); reset(); } void ConfigPanelWidget::changeBackground() { QStringList sheet; // QGSettings *gsettings; // gsettings= new QGSettings("org.mate.interface", "", this); // QString mode; // mode=gsettings->get("gtk-theme").toString(); // qDebug()<<"ukui-theme:"< ConfigPluginsWidget 0 0 339 220 Configure Plugins 0 0 0 0 6 0 0 0 0 QAbstractScrollArea::AdjustToContents true QAbstractItemView::SingleSelection QAbstractItemView::SelectRows QAbstractItemView::ScrollPerPixel QListView::TopToBottom QListView::Adjust 0 false true Note: changes made in this page cannot be reset. true 0 0 0 0 Move up ... ../../../../../.designer/backup../../../../../.designer/backup Move down ... ../../../../../.designer/backup../../../../../.designer/backup Qt::Horizontal Add ... ../../../../../.designer/backup../../../../../.designer/backup Remove ... ../../../../../.designer/backup../../../../../.designer/backup Qt::Horizontal Configure ... ../../../../../.designer/backup../../../../../.designer/backup Qt::Vertical 20 40 ukui-panel/panel/config/addplugindialog.cpp0000644000175000017500000001215213632320722017750 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019-2020 UKUI team * modifed by hepuyao * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ui_addplugindialog.h" #include "addplugindialog.h" #include "plugin.h" #include "../ukuipanelapplication.h" //#include #include "common/ukuihtmldelegate.h" #include #include #include #include #include #include #define SEARCH_ROLE Qt::UserRole #define INDEX_ROLE SEARCH_ROLE+1 AddPluginDialog::AddPluginDialog(QWidget *parent): QDialog(parent), ui(new Ui::AddPluginDialog) { ui->setupUi(this); QStringList desktopFilesDirs; desktopFilesDirs << QString(getenv("UKUI_PANEL_PLUGINS_DIR")).split(':', QString::SkipEmptyParts); desktopFilesDirs << QString("%1/%2").arg(XdgDirs::dataHome(), "/ukui/ukui-panel"); desktopFilesDirs << PLUGIN_DESKTOPS_DIR; mPlugins = UKUi::PluginInfo::search(desktopFilesDirs, QLatin1String("UKUIPanel/Plugin"), QLatin1String("*")); std::sort(mPlugins.begin(), mPlugins.end(), [](const UKUi::PluginInfo &p1, const UKUi::PluginInfo &p2) { return p1.name() < p2.name() || (p1.name() == p2.name() && p1.comment() < p2.comment()); }); ui->pluginList->setItemDelegate(new UKUi::HtmlDelegate(QSize(32, 32), ui->pluginList)); ui->pluginList->setContextMenuPolicy(Qt::CustomContextMenu); filter(); // search mSearchTimer.setInterval(300); mSearchTimer.setSingleShot(true); connect(ui->searchEdit, &QLineEdit::textEdited, &mSearchTimer, static_cast(&QTimer::start)); connect(&mSearchTimer, &QTimer::timeout, this, &AddPluginDialog::filter); connect(ui->pluginList, &QListWidget::doubleClicked, this, &AddPluginDialog::emitPluginSelected); connect(ui->addButton, &QPushButton::clicked, this, &AddPluginDialog::emitPluginSelected); connect(dynamic_cast(qApp), &UKUIPanelApplication::pluginAdded , this, &AddPluginDialog::filter); connect(dynamic_cast(qApp), &UKUIPanelApplication::pluginRemoved , this, &AddPluginDialog::filter); } AddPluginDialog::~AddPluginDialog() { delete ui; } void AddPluginDialog::filter() { QListWidget* pluginList = ui->pluginList; const int curr_item = 0 < pluginList->count() ? pluginList->currentRow() : 0; pluginList->clear(); static QIcon fallIco = XdgIcon::fromTheme("preferences-plugin"); int pluginCount = mPlugins.length(); for (int i = 0; i < pluginCount; ++i) { const UKUi::PluginInfo &plugin = mPlugins.at(i); QString s = QString("%1 %2 %3 %4 %5").arg(plugin.name(), plugin.comment(), plugin.value("Name").toString(), plugin.value("Comment").toString(), plugin.id()); if (!s.contains(ui->searchEdit->text(), Qt::CaseInsensitive)) continue; QListWidgetItem* item = new QListWidgetItem(ui->pluginList); // disable single-instances plugins already in use if (dynamic_cast(qApp)->isPluginSingletonAndRunnig(plugin.id())) { item->setFlags(item->flags() & ~Qt::ItemIsEnabled); item->setBackground(palette().brush(QPalette::Disabled, QPalette::Text)); item->setText(QString("%1 (%2)
%3
%4") .arg(plugin.name(), plugin.id(), plugin.comment(), tr("(only one instance can run at a time)"))); } else item->setText(QString("%1 (%2)
%3").arg(plugin.name(), plugin.id(), plugin.comment())); item->setIcon(plugin.icon(fallIco)); item->setData(INDEX_ROLE, i); } if (pluginCount > 0) ui->pluginList->setCurrentRow(curr_item < pluginCount ? curr_item : pluginCount - 1); } void AddPluginDialog::emitPluginSelected() { QListWidget* pluginList = ui->pluginList; if (pluginList->currentItem() && pluginList->currentItem()->isSelected()) { UKUi::PluginInfo plugin = mPlugins.at(pluginList->currentItem()->data(INDEX_ROLE).toInt()); emit pluginSelected(plugin); } } ukui-panel/panel/config/addplugindialog.ui0000644000175000017500000000714013632320722017604 0ustar fengfeng AddPluginDialog 0 0 400 359 Add Plugins Search: QAbstractScrollArea::AdjustToContents true true QAbstractItemView::SingleSelection QAbstractItemView::SelectRows QAbstractItemView::ScrollPerPixel QListView::Static QListView::TopToBottom QListView::Adjust 0 0 false true -1 false Qt::Horizontal 40 20 Add Widget Close false true pluginList addButton closeButton searchEdit closeButton clicked() AddPluginDialog close() 380 279 118 270 ukui-panel/panel/config/configpaneldialog.cpp0000644000175000017500000000624213632320722020271 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Marat "Morion" Talipov * * Copyright: 2019-2020 UKUI team * modified by hepuyao * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ //this class to show the page of config panel #include "configpaneldialog.h" #include ConfigPanelDialog::ConfigPanelDialog(UKUIPanel *panel, QWidget *parent): UKUi::ConfigDialog(tr("Configure Panel"), panel->settings(), parent), mPanelPage(nullptr), mPluginsPage(nullptr) { setAttribute(Qt::WA_DeleteOnClose); mPanelPage = new ConfigPanelWidget(panel, this); addPage(mPanelPage, tr("Panel"), QLatin1String("configure")); //connect(this, &ConfigPanelDialog::reset, mPanelPage, &ConfigPanelWidget::reset); mPluginsPage = new ConfigPluginsWidget(panel, this); addPage(mPluginsPage, tr("Widgets"), QLatin1String("preferences-plugin")); //connect(this, &ConfigPanelDialog::reset, mPluginsPage, &ConfigPluginsWidget::reset); // connect(this, &ConfigPanelDialog::accepted, [panel] { // panel->saveSettings(); // }); FileSetPanel *f; f=new FileSetPanel(mPanelPage); QDBusConnection conp=QDBusConnection::sessionBus(); if(!conp.registerService("com.ukui.panel.settings") || !conp.registerObject("/set",mPanelPage)) { qDebug()<<"fail"; } } void ConfigPanelDialog::showConfigPanelPage() { showPage(mPanelPage); } void ConfigPanelDialog::showConfigPluginsPage() { showPage(mPluginsPage); } void ConfigPanelDialog::updateIconThemeSettings() { mPanelPage->updateIconThemeSettings(); } void ConfigPanelDialog::configPosition_top() { //qDebug()<<"mPanelPage ptr is:"<positionChanged_top(); } void ConfigPanelDialog::configPosition_bottom() { //qDebug()<<"mPanelPage ptr is:"<positionChanged_bottom(); } void ConfigPanelDialog::configPosition_left() { mPanelPage->positionChanged_left(); } void ConfigPanelDialog::configPosition_right() { mPanelPage->positionChanged_right(); } void ConfigPanelDialog::configPanelSize_S() { mPanelPage->changeToSmallSize(); } void ConfigPanelDialog::configPanelSize_m() { mPanelPage->changeToMidSize(); } void ConfigPanelDialog::configPanelSize_l() { mPanelPage->changeToLargeSize(); } void ConfigPanelDialog::backgroundChange() { mPanelPage->changeBackground(); } ukui-panel/panel/config/configpanelwidget.ui0000644000175000017500000005176013632320722020155 0ustar fengfeng ConfigPanelWidget 0 0 382 517 0 0 Configure panel 0 0 0 0 0 0 Size false 0 0 0 0 <p>Negative pixel value sets the panel length to that many pixels less than available screen space.</p><p/><p><i>E.g. "Length" set to -100px, screen size is 1000px, then real panel length will be 900 px.</i></p> 1 100 Size: Length: % px px 24 Qt::Horizontal QSizePolicy::MinimumExpanding 5 20 0 0 0 0 px 10 128 Icon size: Rows: 1 20 0 0 Alignment && position Alignment: 1 Left Center Right Position: true A&uto-hide true false Zero means no animation Animation duration: Qt::Horizontal 102 5 Zero means no animation ms 500 50 Zero means no delay Show with delay: Zero means no delay ms 2000 50 Visible thin margin for hidden panel Don't allow maximized windows go under the panel window Reserve space on display 0 0 Custom styling 0 0 0 0 Font color: false ../../../../../.designer/backup../../../../../.designer/backup Qt::Horizontal QSizePolicy::MinimumExpanding 5 20 Background color: false ../../../../../.designer/backup../../../../../.designer/backup 6 6 false Background opacity: false 100 5 100 Qt::Horizontal false <small>Compositing is required for panel transparency.</small> Qt::AlignCenter 0 0 0 0 Background image: 0 0 0 0 false false ../../../../../.designer/backup../../../../../.designer/backup A partial workaround for widget styles that cannot give a separate theme to the panel. You might also want to disable: UKUi Appearance Configuration → Icons Theme → Colorize icons based on widget style (palette) Override icon &theme true false Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter Icon theme for panels: checkBox_customBgColor toggled(bool) pushButton_customBgColor setEnabled(bool) 144 332 350 350 checkBox_customBgImage toggled(bool) lineEdit_customBgImage setEnabled(bool) 137 403 149 440 checkBox_customBgImage toggled(bool) pushButton_customBgImage setEnabled(bool) 125 403 350 441 checkBox_customFontColor toggled(bool) pushButton_customFontColor setEnabled(bool) 190 294 350 312 checkBox_customBgColor toggled(bool) slider_opacity setEnabled(bool) 99 333 114 367 checkBox_customBgColor toggled(bool) label_2 setEnabled(bool) 34 341 32 362 checkBox_customBgColor toggled(bool) compositingL setEnabled(bool) 20 20 20 20 ukui-panel/panel/config/configpluginswidget.cpp0000644000175000017500000001124713633355350020706 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * Paulo Lieuthier * * Copyright: 2019-2020 UKUI team * modified by hepuyao * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "configpluginswidget.h" #include "ui_configpluginswidget.h" #include "addplugindialog.h" #include "panelpluginsmodel.h" #include "../plugin.h" #include "../iukuipanelplugin.h" #include "../common/ukuihtmldelegate.h" #include #include ConfigPluginsWidget::ConfigPluginsWidget(UKUIPanel *panel, QWidget* parent) : QWidget(parent), ui(new Ui::ConfigPluginsWidget), mPanel(panel) { ui->setupUi(this); PanelPluginsModel * plugins = mPanel->mPlugins.data(); { QScopedPointer m(ui->listView_plugins->selectionModel()); ui->listView_plugins->setModel(plugins); } { QScopedPointer d(ui->listView_plugins->itemDelegate()); ui->listView_plugins->setItemDelegate(new UKUi::HtmlDelegate(QSize(16, 16), ui->listView_plugins)); } resetButtons(); connect(ui->listView_plugins->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ConfigPluginsWidget::resetButtons); connect(ui->pushButton_moveUp, &QToolButton::clicked, [this, plugins] { plugins->onMovePluginUp(ui->listView_plugins->currentIndex()); }); connect(ui->pushButton_moveDown, &QToolButton::clicked, [this, plugins] { plugins->onMovePluginDown(ui->listView_plugins->currentIndex()); }); connect(ui->pushButton_addPlugin, &QPushButton::clicked, this, &ConfigPluginsWidget::showAddPluginDialog); connect(ui->pushButton_removePlugin, &QToolButton::clicked, [this, plugins] { plugins->onRemovePlugin(ui->listView_plugins->currentIndex()); }); connect(ui->pushButton_pluginConfig, &QToolButton::clicked, [this, plugins] { plugins->onConfigurePlugin(ui->listView_plugins->currentIndex()); }); connect(plugins, &PanelPluginsModel::pluginAdded, this, &ConfigPluginsWidget::resetButtons); connect(plugins, &PanelPluginsModel::pluginRemoved, this, &ConfigPluginsWidget::resetButtons); connect(plugins, &PanelPluginsModel::pluginMoved, this, &ConfigPluginsWidget::resetButtons); } ConfigPluginsWidget::~ConfigPluginsWidget() { delete ui; } void ConfigPluginsWidget::reset() { qDebug()<<"ConfigPluginsWidget reset is here"; } void ConfigPluginsWidget::showAddPluginDialog() { if (mAddPluginDialog.isNull()) { mAddPluginDialog.reset(new AddPluginDialog); connect(mAddPluginDialog.data(), &AddPluginDialog::pluginSelected, mPanel->mPlugins.data(), &PanelPluginsModel::addPlugin); } mAddPluginDialog->show(); mAddPluginDialog->raise(); mAddPluginDialog->activateWindow(); qDebug()<<"showAddPluginDialog here"<listView_plugins->currentIndex()<mPlugins.data(); QItemSelectionModel *selectionModel = ui->listView_plugins->selectionModel(); bool hasSelection = selectionModel->hasSelection(); bool isFirstSelected = selectionModel->isSelected(model->index(0)); bool isLastSelected = selectionModel->isSelected(model->index(model->rowCount() - 1)); bool hasConfigDialog = false; if (hasSelection) { Plugin const * plugin = ui->listView_plugins->model()->data(selectionModel->currentIndex(), Qt::UserRole).value(); if (nullptr != plugin) hasConfigDialog = plugin->iPlugin()->flags().testFlag(IUKUIPanelPlugin::HaveConfigDialog); } ui->pushButton_removePlugin->setEnabled(hasSelection); ui->pushButton_moveUp->setEnabled(hasSelection && !isFirstSelected); ui->pushButton_moveDown->setEnabled(hasSelection && !isLastSelected); ui->pushButton_pluginConfig->setEnabled(hasSelection && hasConfigDialog); } ukui-panel/panel/resources/0000755000175000017500000000000013643566146014677 5ustar fengfengukui-panel/panel/resources/ukui-panel_zh_CN.ts0000644000175000017500000016521713643566146020416 0ustar fengfeng AddPluginDialog Add Plugins Search: Add Widget Close 关闭 (only one instance can run at a time) CalendarActiveLabel Time and Date Setting 时间日期设置 Config panel 设置任务栏 ConfigDialog Dialog ConfigPanelDialog Configure Panel Panel Widgets ConfigPanelWidget Configure panel Size <p>Negative pixel value sets the panel length to that many pixels less than available screen space.</p><p/><p><i>E.g. "Length" set to -100px, screen size is 1000px, then real panel length will be 900 px.</i></p> Size: Length: % px px Icon size: Rows: Alignment && position Alignment: Left Center Right Position: A&uto-hide Zero means no animation Animation duration: ms Zero means no delay Show with delay: Visible thin margin for hidden panel Don't allow maximized windows go under the panel window Reserve space on display Custom styling Font color: Background color: Background opacity: <small>Compositing is required for panel transparency.</small> Background image: A partial workaround for widget styles that cannot give a separate theme to the panel. You might also want to disable: UKUi Appearance Configuration → Icons Theme → Colorize icons based on widget style (palette) Override icon &theme Icon theme for panels: Top of desktop Left of desktop Right of desktop Bottom of desktop Top of desktop %1 Left of desktop %1 Right of desktop %1 Bottom of desktop %1 Top Bottom Pick color Pick image Images (*.png *.gif *.jpg) ConfigPluginsWidget Configure Plugins Note: changes made in this page cannot be reset. Move up ... Move down Add Remove Configure IndicatorCalendar '<b>'HH:mm:ss'</b><br/><font size="-2">'ddd, d MMM yyyy'<br/>'TT'</font>' MainWindow MainWindow usb management tool NightMode nightmode 夜间模式 NightModeButton nightmode open 夜间模式开启 nightmode close 夜间模式关闭 please install redshift first 请先安装redshift QCoreApplication Choose the page to be shown. QObject Power Manager Error QDBusInterface is invalid Power Manager Error (D-BUS call) QuickLaunchButton move left 左移 move right 右移 move to left 左移 move to right 右移 delete from quicklaunch 从任务栏取消固定 SpacerConfiguration Spacer Settings Space width: Space type: fixed expandable lined dotted invisible StartMenuButton Lock The Screen 锁定屏幕 Switch The User 切换用户 Logout 注销 Reboot 重启 Shutdown 关机 TaskView taskviewWindow 预览窗口 UKUIPanel Panel Set up Panel 设置任务栏 Show Taskview 显示预览 Show Desktop 显示桌面 Show System Monitor 系统监视器 Small 小尺寸 Media 中尺寸 Large 大尺寸 Adjustment Size 调整大小 Up Bottom Left Right Adjustment Position 调整位置 Lock This Panel 锁定任务栏 Remove Panel Dialog Title Removing a panel can not be undone. Do you want to remove this panel? UKUIQuickLaunch Drop Error File/URL '%1' cannot be embedded into QuickLaunch for now Drop application icons here UKUIStartMenuButton Lock Screen 锁屏 Switch User 切换用户 LogOut 注销 Restart 重启 Power Off 关机 UKUITaskButton Application To &Desktop &All Desktops Desktop &%1 &To Current Desktop &Move Resi&ze Ma&ximize Maximize vertically Maximize horizontally &Restore Mi&nimize Roll down Roll up &Layer Always on &top &Normal Always on &bottom &Close &关闭 UKUITaskGroup Group close 关闭 UKUITaskbarConfiguration Task Manager Settings General Show only windows from desktop Show only windows from &panel's screen Show only minimized windows Raise minimized windows on current desktop Close on middle-click Cycle windows on wheel scrolling Window &grouping Show popup on mouse hover Appearance Button style Maximum button width px Maximum button height Auto&rotate buttons when the panel is vertical Use icons by WindowClass, if available Icon and text Only icon Only text Current UKUi::MessageBox UKUi Power Manager Error Hibernate failed. UKUi::NotificationPrivate Notifications Fallback UKUi::PowerManager Hibernate Suspend Reboot 重启 Shutdown 关机 Logout 注销 UKUi Session Suspend Do you want to really suspend your computer?<p>Suspends the computer into a low power state. System state is not preserved if the power is lost. UKUi Session Hibernate Do you want to really hibernate your computer?<p>Hibernates the computer into a low power state. System state is preserved if the power is lost. UKUi Session Reboot Do you want to really restart your computer? All unsaved work will be lost... UKUi Session Shutdown Do you want to really switch off your computer? All unsaved work will be lost... UKUi Session Logout Do you want to really logout? All unsaved work will be lost... UKUi Power Manager Error Hibernate failed. Suspend failed. UKUi::ScreenSaver Screen Saver Error An error occurred starting screensaver. Syntax error in xdg-screensaver arguments. Screen Saver Activation Error An error occurred starting screensaver. Ensure you have xscreensaver installed and running. An error occurred starting screensaver. Action 'activate' failed. Ensure you have xscreensaver installed and running. An error occurred starting screensaver. Unknown error - undocumented return value from xdg-screensaver: %1. Lock Screen UkuiWebviewDialog Dialog ejectInterface usb has been unplugged safely main Use alternate configuration file. Configuration file ukui-panel/panel/resources/ukui-panel.desktop0000644000175000017500000000032013632320722020321 0ustar fengfeng[Desktop Entry] Name=ukui-panel comment=Panel Comment[zh_CN]=任务栏 Exec=ukui-panel Terminal=false Type=Application Icon=panel X-UKUI-AutoRestart=true OnlyShowIn=UKUI X-UKUI-Autostart-Phase=Initialization ukui-panel/panel/resources/panel.qss0000644000175000017500000002505013632320722016512 0ustar fengfengQSplitter::handle{ background:white; } QScrollArea{ border:0px; } QWidget#scrollArea_widget{ background-color:white; border:0px; } /* QWidget:focus{ outline-color: gray; outline-style: dotted; outline-width: 1px; outline-color: red; } */ QWidget:focus{ outline:none; } QWidget#login_keep_widget{ background:#eef3f6; border-style:solid; border-color:#d7dee3; border-left-width: 0px; border-top-width: 1px; border-right-width: 0px; border-bottom-width: 0px; } /*---------配置一个指定边框色的主界面窗口---------------*/ QWidget#custom_border_widget{ background:white; border-style:solid; border-width:1px; border-top-color:#ff7846; border-left-color:#a6adbc; border-right-color:#a6adb3; border-bottom-color:#a6adb3; } QWidget#settings_bottom_widget{ background: #eef3f6; border-style: solid; border-color: #d7dee3; border-left-width: 0px; border-top-width: 1px; border-right-width: 0px; border-bottom-width: 0px; } QWidget#category_widget{ background:#eef3f6; } QWidget#border_widget{ background:white; border-style: solid; border-color:#d7dee3; border-width: 1px; } QWidget#white_widget{ background:white; } QWidget#stacked_widget{ background:#eef3f6; border-style: solid; border-color:#d7dee3; border-left-width: 1px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; } /*-------------------QListWidget-------------------*/ /* QListWidget#sss::item{ border-left-width: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; padding-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; } */ QListWidget#sss::item:hover{ background-color:#ff7846; } QListWidget#sss::item:selected { background-color:skyblue; } /* QListWidget#sss::item:pressed { background-color:#e6ebee; } QListWidget#sss::item:selected:!active { background-color:#f6f6f6; } QListWidget#sss::item:selected:active { background-color:#e6ebee; }*/ /*-------------------QTableWidget----------------*/ QTableView::item { padding:1; border: none; background: white; } QTableView::item:selected { background:#ff7846; color:white; } QHeaderView::section { color: black; font: 13px ; text-align:center; height:32px; background-color: white; border:1px solid #bec3c9; border-left:none; border-top:none; } QHeaderView::section:first { border-left:0px solid #bec3c9; } QHeaderView::section:last { border-right:1px solid #bec3c9; } QTableView { /*color: white; 表格内文字颜色*/ gridline-color: white; /*表格内框颜色*/ background-color: white; /*表格内背景色*/ border: 1px groove #bec3c9; border-radius: 0px; padding: 0px 0px; } QTableView::indicator { width: 12px; height: 12px; } QTableView::indicator:enabled:unchecked{ image:url(://picture/check-default.png); } QTableView::indicator:enabled:unchecked:hover { image:url(://picture/check-hover.png); } QTableView::indicator:enabled:unchecked:pressed { image:url(://picture/check-click.png); } QTableView::indicator:enabled:checked{ image:url(://picture/check-select.png); } QTableView::indicator:enabled:checked:hover { image:url(://picture/check-select-hover.png); } QTableView::indicator:enabled:checked:pressed { image:url(://picture/check-select-click.png); } /*-------------------QLineEdit-------------------*/ QLineEdit{ border:1px solid #bec3c9; height: 24px; font-family: "Droid Sans Fallback"; } QLineEdit::hover{ border:1px solid #ffa888; } QLineEdit::pressed{ border:1px solid #ffa888; } QLineEdit::disabled{ border:1px solid #d9dfe3; } /*-------------------QTextEdit-------------------*/ QTextEdit{ border:1px solid #bec3c9; font-family: "Droid Sans Fallback"; } QTextEdit::hover{ border:1px solid #ffa888; } QTextEdit::pressed{ border:1px solid #ffa888; } QTextEdit::disabled{ border:1px solid #d9dfe3; } /*-------------------QComboBox-------------------*/ QComboBox{ border:1px solid #bec3c9; height: 24px; font-family: "Droid Sans Fallback"; } QComboBox::hover{ border:1px solid #ffa888; } QComboBox::focus{ border:1px solid #ffa888; } QComboBox::disabled{ border:1px solid #d9dfe3; background-color:#f4f7f9; } QComboBox QAbstractItemView{ border:1px solid #bec3c9; selection-background-color: #ff7846; } QComboBox QAbstractItemView::item{ height:24px; } QComboBox::down-arrow{ image:url(://picture/arrow-default.png); } QComboBox::down-arrow:hover{ image:url(://picture/arrow-hover.png); } QComboBox::down-arrow:pressed{ image:url(://picture/arrow-click.png); } QComboBox::down-arrow:disabled{ image:url(://picture/arrow-disable.png); } QComboBox::drop-down{ border:0px; background-color:white; width:20px; } QComboBox::drop-down:disabled{ border:0px; background-color:#f4f7f9; width:20px; } /*-------------------QRadioButton-------------------*/ QRadioButton { spacing: 5px; font-family: "Droid Sans Fallback"; } QRadioButton::indicator { width: 12px; height: 12px } QRadioButton::indicator:disabled { image:url(://picture/single-disable.png); } QRadioButton::indicator:unchecked { image:url(://picture/single-default.png); } QRadioButton::indicator:unchecked:hover { image:url(://picture/single-hover.png); } QRadioButton::indicator:unchecked:pressed { image:url(://picture/single-click.png); } QRadioButton::indicator:checked { image:url(://picture/single-select.png); } QRadioButton::indicator:checked:hover { image:url(://picture/single-select-hover.png); } QRadioButton::indicator:checked:pressed { image:url(://picture/single-select-click.png); } /*-------------------QCheckBox-------------------*/ QCheckBox{ spacing: 5px; font-family: "Droid Sans Fallback"; } QCheckBox::indicator:disabled{ image:url(://picture/check-disable.png); } QCheckBox::indicator:unchecked{ image:url(://picture/check-default.png); } QCheckBox::indicator:unchecked:hover { image:url(://picture/check-hover.png); } QCheckBox::indicator:unchecked:pressed { image:url(://picture/check-click.png); } QCheckBox::indicator:checked{ image:url(://picture/check-select.png); } QCheckBox::indicator:checked:hover { image:url(://picture/check-select-hover.png); } QCheckBox::indicator:checked:pressed { image:url(://picture/check-select-click.png); } /*-------------------tableWidgetCheckbox-------------------*/ QCheckBox#tableWidgetCheckbox{ spacing: 5px; font-family: "Droid Sans Fallback"; } QCheckBox#tableWidgetCheckbox::indicator:disabled{ image:url(://picture/check-disable.png); } QCheckBox#tableWidgetCheckbox::indicator:unchecked{ image:url(://picture/check-default.png); } QCheckBox#tableWidgetCheckbox::indicator:unchecked:hover { image:url(://picture/check-hover.png); } QCheckBox#tableWidgetCheckbox::indicator:unchecked:pressed { image:url(://picture/check-click.png); } QCheckBox#tableWidgetCheckbox::indicator:checked{ image:url(://picture/check-select.png); } QCheckBox#tableWidgetCheckbox::indicator:checked:hover { image:url(://picture/check-select-hover.png); } QCheckBox#tableWidgetCheckbox::indicator:checked:pressed { image:url(://picture/check-select-click.png); } /*-------------------QPushButton-------------------*/ QPushButton{ font-family: "Droid Sans Fallback"; border: 1px solid #bec3c9; background-color:#f0fdfe; } QPushButton::hover{ border: 1px solid #ff7846; background-color:#ffffff; } QPushButton::pressed{ border: 1px solid #ffa888; background-color:#f8f3f1; } QPushButton::disabled{ border: 1px solid #d9dfe3; background-color:#f4f7f9; } QPushButton::focus{ border: 1px solid red; } QPushButton#settings_bottom_button{ border: 1px solid #bec3c9; background-color:#f0fdfe; } QPushButton#settings_bottom_button::hover{ border: 1px solid #ff7846; background-color:#ffffff; } QPushButton#settings_bottom_button::pressed{ border: 1px solid #ffa888; background-color:#f8f3f1; } QPushButton#settings_bottom_button::disabled{ border: 1px solid #d9dfe3; background-color:#f4f7f9; } QPushButton#settings_bottom_button::focus{ border: 1px solid red; } /*-------------------QLabel--------font-weight:bold---------*/ QLabel{ font-family: "Droid Sans Fallback"; } QLabel#one_title_label{ font-family: "Droid Sans Fallback"; font-size: 17px; text-align: left; } QLabel#line_label{ border-style: solid; border-color:#d7dee3; border-bottom-width: 1px; } QLabel#settings_logo_label{ background:url(://picture/logo.png); } /*分割线 QMenu::separator{ height:1px; background: #3b3b3b; margin:2px 0px 2px 0px; } */ /**********滚动条基本样式**********/ QScrollBar:vertical{ width: 8px; background: white; margin:0px 0px 0px 0px; border:0px solid #b9bec7; } QScrollBar::handle:vertical{ width: 8px; min-height: 45px; background: #b9bec7; margin-left: 0px; margin-right: 0px; } QScrollBar::handle:vertical:hover { background: #b9bec7; } QScrollBar::handle:vertical:pressed { background: #b9bec7; } QScrollBar::sub-line:vertical{ height: 0px; background: transparent; subcontrol-position: top; } QScrollBar::add-line:vertical{ height: 0px; background: transparent; subcontrol-position: bottom; } QScrollBar::sub-line:vertical:hover { background: #292929; } QScrollBar::add-line:vertical:hover { background: #292929; } QScrollBar::add-page:vertical,QScrollBar::sub-page:vertical { background: transparent; } QScrollBar:horizontal{ height: 8px; background: white; margin:0px 0px 0px 0px; border:0px solid #b9bec7; } QScrollBar::handle:horizontal{ height: 8px; min-width: 20px; background: #b9bec7; margin-left: 0px; margin-right: 0px; } QScrollBar::handle:horizontal:hover { background: #b9bec7; } QScrollBar::handle:horizontal:pressed { background: #b9bec7; } QScrollBar::sub-line:horizontal{ width: 0px; background: transparent; subcontrol-position: top; } QScrollBar::add-line:horizontal{ width: 0px; background: transparent; subcontrol-position: bottom; } QScrollBar::sub-line:horizontal:hover { background: #292929; } QScrollBar::add-line:horizontal:hover { background: #292929; } QScrollBar::add-page:horizontal,QScrollBar::sub-page:horizontal { background: transparent; } ukui-panel/panel/resources/org.ukui.panel.tray.gschema.xml0000644000175000017500000000166613640356061022645 0ustar fengfeng '' Keybinding Keybinding associated with a custom shortcut. '' Command Command associated with a custom keybinding. '' Name Description associated with a custom keybinding. '' Record Description associated with a custom keybinding. ukui-panel/panel/resources/org.ukui.panel.settings.gschema.xml0000644000175000017500000000133113642614010023504 0ustar fengfeng 46 panelsize the size of UKUI Panel 32 IconSize the size of ukui-panel's icon 0 PanelPosition The Position of ukui-panel ukui-panel/panel/resources/panel.conf0000644000175000017500000000174613633070712016641 0ustar fengfengpanels=panel1 [panel1] alignment=-1 animation-duration=0 background-color=@Variant(\0\0\0\x43\x1\xff\xff\b\b\n\n\f\f\0\0) desktop=0 font-color=@Variant(\0\0\0\x43\0\xff\xff\0\0\0\0\0\0\0\0) hidable=false iconSize=28 lineCount=1 lockPanel=false opacity=90 panelSize=46 plugins=spacer,startmenu,spacer,taskview,quicklaunch,segmentation,taskbar,spacer,tray,calendar, nightmode,showdesktop position=Bottom reserve-space=true show-delay=0 visible-margin=true width=100 width-percent=true [startmenu] type=startmenu [quicklaunch] alignment=Left apps\1\desktop=/usr/share/applications/peony.desktop apps\2\desktop=/usr/share/applications/firefox.desktop apps\3\desktop=/usr/share/applications/wps-office-wps.desktop apps\size=3 type=quicklaunch [taskbar] type=taskbar [tray] type=tray [calendar] type=calendar [recyclebin] type=recyclebin [nightmode] type=nightmode [showdesktop] alignment=Right type=showdesktop [taskview] type=taskview [spacer] type=spacer [segmentation] type=segmentation ukui-panel/panel/resources/ukui-panel_zh_CN.qm0000644000175000017500000003107013643566146020372 0ustar fengfeng Ka WD tm]~>ʳN&~ӽ xa 'i,F%(only one instance can run at a time)AddPluginDialog Add PluginsAddPluginDialog Add WidgetAddPluginDialogQsCloseAddPluginDialogSearch:AddPluginDialog nNRh Config panelCalendarActiveLabel eegnTime and Date SettingCalendarActiveLabelDialog ConfigDialogConfigure PanelConfigPanelDialogPanelConfigPanelDialogWidgetsConfigPanelDialog msConfigPanelWidget pxConfigPanelWidget%ConfigPanelWidget

Negative pixel value sets the panel length to that many pixels less than available screen space.

E.g. "Length" set to -100px, screen size is 1000px, then real panel length will be 900 px.

ConfigPanelWidget>Compositing is required for panel transparency.ConfigPanelWidgetA partial workaround for widget styles that cannot give a separate theme to the panel. You might also want to disable: UKUi Appearance Configuration → Icons Theme → Colorize icons based on widget style (palette)ConfigPanelWidget A&uto-hideConfigPanelWidgetAlignment && positionConfigPanelWidget Alignment:ConfigPanelWidgetAnimation duration:ConfigPanelWidgetBackground color:ConfigPanelWidgetBackground image:ConfigPanelWidgetBackground opacity:ConfigPanelWidgetN BottomConfigPanelWidgetBottom of desktopConfigPanelWidgetBottom of desktop %1ConfigPanelWidgetCenterConfigPanelWidgetConfigure panelConfigPanelWidgetCustom stylingConfigPanelWidget7Don't allow maximized windows go under the panel windowConfigPanelWidget Font color:ConfigPanelWidget Icon size:ConfigPanelWidgetIcon theme for panels:ConfigPanelWidgetImages (*.png *.gif *.jpg)ConfigPanelWidget]LeftConfigPanelWidgetLeft of desktopConfigPanelWidgetLeft of desktop %1ConfigPanelWidgetLength:ConfigPanelWidgetOverride icon &themeConfigPanelWidget Pick colorConfigPanelWidget Pick imageConfigPanelWidget Position:ConfigPanelWidgetReserve space on displayConfigPanelWidgetSRightConfigPanelWidgetRight of desktopConfigPanelWidgetRight of desktop %1ConfigPanelWidgetRows:ConfigPanelWidgetShow with delay:ConfigPanelWidgetSizeConfigPanelWidgetSize:ConfigPanelWidgetTopConfigPanelWidgetTop of desktopConfigPanelWidgetTop of desktop %1ConfigPanelWidget$Visible thin margin for hidden panelConfigPanelWidgetZero means no animationConfigPanelWidgetZero means no delayConfigPanelWidgetpxConfigPanelWidget...ConfigPluginsWidgetAddConfigPluginsWidget ConfigureConfigPluginsWidgetConfigure PluginsConfigPluginsWidget Move downConfigPluginsWidgetMove upConfigPluginsWidget0Note: changes made in this page cannot be reset.ConfigPluginsWidgetRemoveConfigPluginsWidgetI''HH:mm:ss'
'ddd, d MMM yyyy'
'TT'
'IndicatorCalendar MainWindow MainWindowusb management tool MainWindowYj!_ nightmode NightMode Yj!_Qsnightmode closeNightModeButton Yj!__T/nightmode openNightModeButtonQH[redshiftplease install redshift firstNightModeButtonChoose the page to be shown.QCoreApplicationPower Manager ErrorQObject Power Manager Error (D-BUS call)QObjectQDBusInterface is invalidQObjectNNRhSmV[delete from quicklaunchQuickLaunchButton]y move to leftQuickLaunchButtonSy move to rightQuickLaunchButton Space type:SpacerConfiguration Space width:SpacerConfigurationSpacer SettingsSpacerConfigurationdottedSpacerConfiguration expandableSpacerConfigurationfixedSpacerConfiguration invisibleSpacerConfigurationlinedSpacerConfigurationzStaskviewWindowTaskViewetOMnAdjustment Position UKUIPaneletY'\Adjustment Size UKUIPanelN Bottom UKUIPanelY'\:[Large UKUIPanel]Left UKUIPanel [NRhLock This Panel UKUIPanelN-\:[Media UKUIPanelPanel UKUIPanel Remove Panel UKUIPanelERemoving a panel can not be undone. Do you want to remove this panel? UKUIPanelSRight UKUIPanelf>y:hLb Show Desktop UKUIPanel |~vщVhShow System Monitor UKUIPanelf>y: Show Taskview UKUIPanel\\:[Small UKUIPanelN Up UKUIPanel Drop ErrorUKUIQuickLaunchDrop application icons hereUKUIQuickLaunch9File/URL '%1' cannot be embedded into QuickLaunch for nowUKUIQuickLaunch\O Lock ScreenUKUIStartMenuButtonlLogOutUKUIStartMenuButtonQsg: Power OffUKUIStartMenuButtonT/RestartUKUIStartMenuButtonRcbu(b7 Switch UserUKUIStartMenuButton &All DesktopsUKUITaskButton&Qs&CloseUKUITaskButton&LayerUKUITaskButton&MoveUKUITaskButton&NormalUKUITaskButton&RestoreUKUITaskButton&To Current DesktopUKUITaskButtonAlways on &bottomUKUITaskButtonAlways on &topUKUITaskButton ApplicationUKUITaskButton Desktop &%1UKUITaskButton Ma&ximizeUKUITaskButtonMaximize horizontallyUKUITaskButtonMaximize verticallyUKUITaskButton Mi&nimizeUKUITaskButtonResi&zeUKUITaskButton Roll downUKUITaskButtonRoll upUKUITaskButton To &DesktopUKUITaskButtonGroup UKUITaskGroupQsclose UKUITaskGroup pxUKUITaskbarConfiguration AppearanceUKUITaskbarConfiguration.Auto&rotate buttons when the panel is verticalUKUITaskbarConfiguration Button styleUKUITaskbarConfigurationClose on middle-clickUKUITaskbarConfigurationCurrentUKUITaskbarConfiguration Cycle windows on wheel scrollingUKUITaskbarConfigurationGeneralUKUITaskbarConfiguration Icon and textUKUITaskbarConfigurationMaximum button heightUKUITaskbarConfigurationMaximum button widthUKUITaskbarConfiguration Only iconUKUITaskbarConfiguration Only textUKUITaskbarConfiguration*Raise minimized windows on current desktopUKUITaskbarConfigurationShow only minimized windowsUKUITaskbarConfiguration&Show only windows from &panel's screenUKUITaskbarConfigurationShow only windows from desktopUKUITaskbarConfigurationShow popup on mouse hoverUKUITaskbarConfigurationTask Manager SettingsUKUITaskbarConfiguration&Use icons by WindowClass, if availableUKUITaskbarConfigurationWindow &groupingUKUITaskbarConfigurationHibernate failed.UKUi::MessageBoxUKUi Power Manager ErrorUKUi::MessageBoxNotifications FallbackUKUi::NotificationPrivateDo you want to really hibernate your computer?

Hibernates the computer into a low power state. System state is preserved if the power is lost.UKUi::PowerManager>Do you want to really logout? All unsaved work will be lost...UKUi::PowerManagerMDo you want to really restart your computer? All unsaved work will be lost...UKUi::PowerManagerDo you want to really suspend your computer?

Suspends the computer into a low power state. System state is not preserved if the power is lost.UKUi::PowerManagerPDo you want to really switch off your computer? All unsaved work will be lost...UKUi::PowerManager HibernateUKUi::PowerManagerHibernate failed.UKUi::PowerManagerlLogoutUKUi::PowerManagerT/RebootUKUi::PowerManagerQsg:ShutdownUKUi::PowerManagerSuspendUKUi::PowerManagerSuspend failed.UKUi::PowerManagerUKUi Power Manager ErrorUKUi::PowerManagerUKUi Session HibernateUKUi::PowerManagerUKUi Session LogoutUKUi::PowerManagerUKUi Session RebootUKUi::PowerManagerUKUi Session ShutdownUKUi::PowerManagerUKUi Session SuspendUKUi::PowerManageruAn error occurred starting screensaver. Action 'activate' failed. Ensure you have xscreensaver installed and running.UKUi::ScreenSaver[An error occurred starting screensaver. Ensure you have xscreensaver installed and running.UKUi::ScreenSaverRAn error occurred starting screensaver. Syntax error in xdg-screensaver arguments.UKUi::ScreenSaverkAn error occurred starting screensaver. Unknown error - undocumented return value from xdg-screensaver: %1.UKUi::ScreenSaver Lock ScreenUKUi::ScreenSaverScreen Saver Activation ErrorUKUi::ScreenSaverScreen Saver ErrorUKUi::ScreenSaverDialogUkuiWebviewDialogusb has been unplugged safelyejectInterfaceConfiguration filemain!Use alternate configuration file.mainukui-panel/panel/pluginsettings_p.h0000644000175000017500000000236713633355350016434 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * Paulo Lieuthier * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef PLUGIN_SETTINGS_P_H #define PLUGIN_SETTINGS_P_H #include "pluginsettings.h" class PluginSettingsFactory { public: static PluginSettings * create(UKUi::Settings *settings, const QString &group, QObject *parent = nullptr); }; #endif //PLUGIN_SETTINGS_P_H ukui-panel/panel/windownotifier.h0000644000175000017500000000274513633355350016105 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * Palo Kisa * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #if !defined(WINDOWNOTIFIER_H) #define WINDOWNOTIFIER_H #include class QWidget; class WindowNotifier : public QObject { Q_OBJECT public: using QObject::QObject; void observeWindow(QWidget * w); inline bool isAnyWindowShown() const { return !mShownWindows.isEmpty(); } virtual bool eventFilter(QObject * watched, QEvent * event) override; signals: void lastHidden(); void firstShown(); private: QList mShownWindows; //!< known shown windows (sorted) }; #endif ukui-panel/panel/ukuipanelpluginconfigdialog.cpp0000644000175000017500000000477413632320722021151 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuipanelpluginconfigdialog.h" #include #include #include #include /************************************************ ************************************************/ UKUIPanelPluginConfigDialog::UKUIPanelPluginConfigDialog(PluginSettings &settings, QWidget *parent) : QDialog(parent), mSettings(settings) { } /************************************************ ************************************************/ UKUIPanelPluginConfigDialog::~UKUIPanelPluginConfigDialog() { } /************************************************ ************************************************/ PluginSettings& UKUIPanelPluginConfigDialog::settings() const { return mSettings; } /************************************************ ************************************************/ void UKUIPanelPluginConfigDialog::dialogButtonsAction(QAbstractButton *btn) { QDialogButtonBox *box = qobject_cast(btn->parent()); if (box && box->buttonRole(btn) == QDialogButtonBox::ResetRole) { mSettings.loadFromCache(); loadSettings(); } else { close(); } } /************************************************ ************************************************/ void UKUIPanelPluginConfigDialog::setComboboxIndexByData(QComboBox *comboBox, const QVariant &data, int defaultIndex) const { int index = comboBox ->findData(data); if (index < 0) index = defaultIndex; comboBox->setCurrentIndex(index); } ukui-panel/panel/iukuipanelplugin.h0000644000175000017500000002117113640356061016413 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef IUKUIPANELPLUGIN_H #define IUKUIPANELPLUGIN_H #include #include "iukuipanel.h" #include "ukuipanelglobals.h" #include /** UKUi panel plugins are standalone sharedlibraries (*.so) located in PLUGIN_DIR (define provided by CMakeLists.txt). Plugin for the panel is a library written in C++. One more necessary thing is a .desktop file describing this plugin. The same may be additional files, like translations. Themselves plugins will be installed to /usr/local/lib/ukui-panel or /usr/lib/ukui-panel (dependent on cmake option -DCMAKE_INSTALL_PREFIX). Desktop files are installed to /usr/local/share/ukui/ukui-panel, translations to /usr/local/share/ukui/ukui-panel/PLUGIN_NAME. **/ class QDialog; class PluginSettings; namespace UKUi { class PluginInfo; } struct UKUI_PANEL_API IUKUIPanelPluginStartupInfo { IUKUIPanel *ukuiPanel; PluginSettings *settings; const UKUi::PluginInfo *desktopFile; }; /** \brief Base abstract class for UKUi panel widgets/plugins. All plugins *must* be inherited from this one. This class provides some basic API and inherited/implemented plugins GUIs will be responsible on the functionality itself. **/ class UKUI_PANEL_API IUKUIPanelPlugin { public: /** This enum describes the properties of a plugin. **/ enum Flag { NoFlags = 0, ///< It does not have any properties set. PreferRightAlignment = 1, /**< The plugin prefers right alignment (for example the clock plugin); otherwise the plugin prefers left alignment (like main menu). This flag is used only at the first start, later positions of all plugins are saved in a config, and this saved information is used. */ HaveConfigDialog = 2, ///< The plugin have a configuration dialog. SingleInstance = 4, ///< The plugin allows only one instance to run. NeedsHandle = 8 ///< The plugin needs a handle for the context menu }; Q_DECLARE_FLAGS(Flags, Flag) /** This enum describes the reason the plugin was activated. **/ enum ActivationReason { Unknown = 0, ///< Unknown reason DoubleClick = 2, ///< The plugin entry was double clicked Trigger = 3, ///< The plugin was clicked MiddleClick = 4 ///< The plugin was clicked with the middle mouse button }; enum CalendarShowMode { lunarSunday = 0,//show lunar and first day a week is sunday lunarMonday = 1,//show lunar and first day a week is monday solarSunday = 2,//show solar and first day a week is sunday solarMonday = 3,//show solar and first day a week is monday defaultMode = 0xff }; /** Constructs an IUKUIPanelPlugin object with the given startupInfo. You do not have to worry about the startupInfo parameters, IUKUIPanelPlugin processes the parameters itself. **/ IUKUIPanelPlugin(const IUKUIPanelPluginStartupInfo &startupInfo): mSettings(startupInfo.settings), mPanel(startupInfo.ukuiPanel), mDesktopFile(startupInfo.desktopFile) {} /** Destroys the object. **/ virtual ~IUKUIPanelPlugin() {} /** Returns the plugin flags. The base class implementation returns a NoFlags. **/ virtual Flags flags() const { return NoFlags; } /** Returns the string that is used in the theme QSS file. If you return "WorldClock" string, theme author may write something like `#WorldClock { border: 1px solid red; }` to set a custom border for your plugin. **/ virtual QString themeId() const = 0; /** From the user's point of view, your plugin is some visual widget on the panel. This function returns a pointer to it. This method is called only once, so you are free to return the pointer on a class member, or create the widget on the fly. **/ virtual QWidget *widget() = 0; /** Returns the plugin settings dialog. Reimplement this function if your plugin has it. The panel does not take ownership of the dialog, it is probably a good idea to set Qt::WA_DeleteOnClose attribute for the dialog. The default implementation returns 0, no dialog; Note that the flags method has to return HaveConfigDialog flag. To save the settings you should use a ready-to-use IUKUIPanelPlugin::settings() object. **/ virtual QDialog *configureDialog() { return 0; } /** This function is called when values are changed in the plugin settings. Reimplement this function to your plugin corresponded the new settings. The default implementation do nothing. **/ virtual void settingsChanged() {} /** This function is called when the user activates the plugin. reason specifies the reason for activation. IUKUIPanelPlugin::ActivationReason enumerates the various reasons. The default implementation do nothing. **/ virtual void activated(ActivationReason reason) {} /** This function is called when the panel geometry or lines count are changed. The default implementation do nothing. **/ virtual void realign() {} /** Returns the panel object. **/ IUKUIPanel *panel() const { return mPanel; } PluginSettings *settings() const { return mSettings; } const UKUi::PluginInfo *desktopFile() const { return mDesktopFile; } /** Helper functions for calculating global screen position of some popup window with windowSize size. If you need to show some popup window, you can use it, to get global screen position for the new window. **/ virtual QRect calculatePopupWindowPos(const QSize &windowSize) { return mPanel->calculatePopupWindowPos(this, windowSize); } /*! * \brief By calling this function plugin notifies the panel about showing a (standalone) window/menu. * * \param w the shown window * */ inline void willShowWindow(QWidget * w) { mPanel->willShowWindow(w); } /*! * \brief By calling this function, a plugin notifies the panel about change of it's "static" * configuration * * \sa isSeparate(), isExpandable */ inline void pluginFlagsChanged() { mPanel->pluginFlagsChanged(this); } virtual bool isSeparate() const { return false; } virtual bool isExpandable() const { return false; } private: PluginSettings *mSettings; IUKUIPanel *mPanel; const UKUi::PluginInfo *mDesktopFile; }; Q_DECLARE_OPERATORS_FOR_FLAGS(IUKUIPanelPlugin::Flags) /** Every plugin must have the IUKUIPanelPluginLibrary loader. You should only reimplement the instance() method which should return your plugin. Example: @code class UKUiClockPluginLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) { return new UKUiClock(startupInfo);} }; @endcode **/ class UKUI_PANEL_API IUKUIPanelPluginLibrary { public: /** Destroys the IUKUIPanelPluginLibrary object. **/ virtual ~IUKUIPanelPluginLibrary() {} /** Returns the root component object of the plugin. When the library is finally unloaded, the root component will automatically be deleted. **/ virtual IUKUIPanelPlugin* instance(const IUKUIPanelPluginStartupInfo &startupInfo) const = 0; }; Q_DECLARE_INTERFACE(IUKUIPanelPluginLibrary, "ukui.org/Panel/PluginInterface/3.0") #endif // IUKUIPANELPLUGIN_H ukui-panel/panel/ukuipanelapplication_p.h0000644000175000017500000000262513632320722017565 0ustar fengfeng/* * Copyright (C) 2016 Luís Pereira * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef UKUIPanelAPPLICATION_P_H #define UKUIPanelAPPLICATION_P_H #include "ukuipanelapplication.h" namespace UKUi { class Settings; } class UKUIPanelApplicationPrivate { Q_DECLARE_PUBLIC(UKUIPanelApplication) public: UKUIPanelApplicationPrivate(UKUIPanelApplication *q); ~UKUIPanelApplicationPrivate() {}; UKUi::Settings *mSettings; IUKUIPanel::Position computeNewPanelPosition(const UKUIPanel *p, const int screenNum); private: UKUIPanelApplication *const q_ptr; }; #endif // UKUIPanelAPPLICATION_P_H ukui-panel/panel/ukuipanelpluginconfigdialog.h0000644000175000017500000000370213632320722020604 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPANELPLUGINCONFIGDIALOG_H #define UKUIPANELPLUGINCONFIGDIALOG_H #include #include #include "ukuipanelglobals.h" #include "pluginsettings.h" class QComboBox; class UKUI_PANEL_API UKUIPanelPluginConfigDialog : public QDialog { Q_OBJECT public: explicit UKUIPanelPluginConfigDialog(PluginSettings &settings, QWidget *parent = nullptr); explicit UKUIPanelPluginConfigDialog(PluginSettings *settings, QWidget *parent = nullptr) : UKUIPanelPluginConfigDialog(*settings, parent) {} virtual ~UKUIPanelPluginConfigDialog(); PluginSettings &settings() const; protected slots: /* Saves settings in conf file. */ virtual void loadSettings() = 0; virtual void dialogButtonsAction(QAbstractButton *btn); protected: void setComboboxIndexByData(QComboBox *comboBox, const QVariant &data, int defaultIndex = 0) const; private: PluginSettings &mSettings; }; #endif // UKUIPANELPLUGINCONFIGDIALOG_H ukui-panel/panel/pluginmoveprocessor.cpp0000644000175000017500000002071013632320722017500 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "pluginmoveprocessor.h" #include "plugin.h" #include "ukuipanellayout.h" #include /************************************************ ************************************************/ PluginMoveProcessor::PluginMoveProcessor(UKUIPanelLayout *layout, Plugin *plugin): QWidget(plugin), mLayout(layout), mPlugin(plugin) { mDestIndex = mLayout->indexOf(plugin); grabKeyboard(); } /************************************************ ************************************************/ PluginMoveProcessor::~PluginMoveProcessor() { } /************************************************ ************************************************/ void PluginMoveProcessor::start() { // We have not memoryleaks there. // The animation will be automatically deleted when stopped. CursorAnimation *cursorAnimation = new CursorAnimation(); connect(cursorAnimation, SIGNAL(finished()), this, SLOT(doStart())); cursorAnimation->setEasingCurve(QEasingCurve::InOutQuad); cursorAnimation->setDuration(150); cursorAnimation->setStartValue(QCursor::pos()); cursorAnimation->setEndValue(mPlugin->mapToGlobal(mPlugin->rect().center())); cursorAnimation->start(QAbstractAnimation::DeleteWhenStopped); } /************************************************ ************************************************/ void PluginMoveProcessor::doStart() { setMouseTracking(true); show(); // Only visible widgets can grab mouse input. grabMouse(mLayout->isHorizontal() ? Qt::SizeHorCursor : Qt::SizeVerCursor); } /************************************************ ************************************************/ void PluginMoveProcessor::mouseMoveEvent(QMouseEvent *event) { QPoint mouse = mLayout->parentWidget()->mapFromGlobal(event->globalPos()); qDebug()<<"mouse:"<itemAt(pos.index + 1); } else { prevItem = mLayout->itemAt(pos.index - 1); nextItem = pos.item; mDestIndex = pos.index; } bool plugSep = mPlugin->isSeparate(); bool prevSep =UKUIPanelLayout::itemIsSeparate(prevItem); bool nextSep =UKUIPanelLayout::itemIsSeparate(nextItem); if (!nextItem) { if (mLayout->isHorizontal()) drawMark(prevItem, prevSep ? RightMark : BottomMark); else drawMark(prevItem, prevSep ? BottomMark : RightMark); return; } if (mLayout->lineCount() == 1) { if (mLayout->isHorizontal()) drawMark(nextItem, LeftMark); else drawMark(nextItem, TopMark); return; } if (!prevItem) { if (mLayout->isHorizontal()) drawMark(nextItem, nextSep ? LeftMark : TopMark); else drawMark(nextItem, nextSep ? TopMark : LeftMark); return; } // We prefer to draw line at the top/left of next item. // But if next item and moved plugin have different types (separate an not) and // previous item hase same type as moved plugin we draw line at the end of previous one. if (plugSep != nextSep && plugSep == prevSep) { if (mLayout->isHorizontal()) drawMark(prevItem, prevSep ? RightMark : BottomMark); else drawMark(prevItem, prevSep ? BottomMark : RightMark); } else { if (mLayout->isHorizontal()) drawMark(nextItem, nextSep ? LeftMark : TopMark); else drawMark(nextItem, nextSep ? TopMark : LeftMark); } } /************************************************ ************************************************/ PluginMoveProcessor::MousePosInfo PluginMoveProcessor::itemByMousePos(const QPoint mouse) const { MousePosInfo ret; for (int i = mLayout->count()-1; i > -1; --i) { QLayoutItem *item = mLayout->itemAt(i); QRect itemRect = item->geometry(); if (mouse.x() > itemRect.left() && mouse.y() > itemRect.top()) { ret.index = i; ret.item = item; if (mLayout->isHorizontal()) { ret.after =UKUIPanelLayout::itemIsSeparate(item) ? mouse.x() > itemRect.center().x() : mouse.y() > itemRect.center().y() ; } else { ret.after =UKUIPanelLayout::itemIsSeparate(item) ? mouse.y() > itemRect.center().y() : mouse.x() > itemRect.center().x() ; } return ret; } } ret.index = 0; ret.item = mLayout->itemAt(0); ret.after = false; return ret; } /************************************************ ************************************************/ void PluginMoveProcessor::drawMark(QLayoutItem *item, MarkType markType) { QWidget *widget = (item) ? item->widget() : 0; static QWidget *prevWidget = 0; if (prevWidget && prevWidget != widget) prevWidget->setStyleSheet(""); prevWidget = widget; if (!widget) return; QString border1; QString border2; switch(markType) { case TopMark: border1 = "top"; border2 = "bottom"; break; case BottomMark: border1 = "bottom"; border2 = "top"; break; case LeftMark: border1 = "left"; border2 = "right"; break; case RightMark: border1 = "right"; border2 = "left"; break; } widget->setStyleSheet(QString("#%1 {" "border-%2: 2px solid rgba(%4, %5, %6, %7); " "border-%3: -2px solid; " "background-color: transparent; }") .arg(widget->objectName()) .arg(border1) .arg(border2) .arg(Plugin::moveMarkerColor().red()) .arg(Plugin::moveMarkerColor().green()) .arg(Plugin::moveMarkerColor().blue()) .arg(Plugin::moveMarkerColor().alpha()) ); } /************************************************ ************************************************/ void PluginMoveProcessor::mousePressEvent(QMouseEvent *event) { event->accept(); } /************************************************ ************************************************/ void PluginMoveProcessor::mouseReleaseEvent(QMouseEvent *event) { event->accept(); releaseMouse(); setMouseTracking(false); doFinish(false); } /************************************************ ************************************************/ void PluginMoveProcessor::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Escape) { doFinish(true); return; } QWidget::keyPressEvent(event); } /************************************************ ************************************************/ void PluginMoveProcessor::doFinish(bool cancel) { releaseKeyboard(); drawMark(0, TopMark); if (!cancel) { int currentIdx = mLayout->indexOf(mPlugin); if (currentIdx == mDestIndex) return; if (mDestIndex > currentIdx) mDestIndex--; mLayout->moveItem(currentIdx, mDestIndex, true); } emit finished(); deleteLater(); } ukui-panel/panel/panelpluginsmodel.cpp0000644000175000017500000003201713632320722017100 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "panelpluginsmodel.h" #include "plugin.h" #include "iukuipanelplugin.h" #include "ukuipanel.h" #include "ukuipanelapplication.h" #include #include #include "common/ukuisettings.h" #include PanelPluginsModel::PanelPluginsModel(UKUIPanel * panel, QString const & namesKey, QStringList const & desktopDirs, QObject * parent/* = nullptr*/) : QAbstractListModel{parent}, mNamesKey(namesKey), mPanel(panel) { loadPlugins(desktopDirs); } PanelPluginsModel::~PanelPluginsModel() { qDeleteAll(plugins()); } int PanelPluginsModel::rowCount(const QModelIndex & parent/* = QModelIndex()*/) const { return QModelIndex() == parent ? mPlugins.size() : 0; } QVariant PanelPluginsModel::data(const QModelIndex & index, int role/* = Qt::DisplayRole*/) const { Q_ASSERT(QModelIndex() == index.parent() && 0 == index.column() && mPlugins.size() > index.row() ); pluginslist_t::const_reference plugin = mPlugins[index.row()]; QVariant ret; switch (role) { case Qt::DisplayRole: if (plugin.second.isNull()) ret = QString("Unknown (%1)").arg(plugin.first); else ret = QString("%1 (%2)").arg(plugin.second->name(), plugin.first); break; case Qt::DecorationRole: if (plugin.second.isNull()) ret = XdgIcon::fromTheme("preferences-plugin"); else ret = plugin.second->desktopFile().icon(XdgIcon::fromTheme("preferences-plugin")); break; case Qt::UserRole: ret = QVariant::fromValue(const_cast(plugin.second.data())); break; } return ret; } Qt::ItemFlags PanelPluginsModel::flags(const QModelIndex & index) const { return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemNeverHasChildren; } QStringList PanelPluginsModel::pluginNames() const { QStringList names; for (auto const & p : mPlugins) names.append(p.first); return names; } QList PanelPluginsModel::plugins() const { QList plugins; for (auto const & p : mPlugins) if (!p.second.isNull()) plugins.append(p.second.data()); return plugins; } Plugin* PanelPluginsModel::pluginByName(QString name) const { for (auto const & p : mPlugins) if (p.first == name) return p.second.data(); return nullptr; } Plugin const * PanelPluginsModel::pluginByID(QString id) const { for (auto const & p : mPlugins) { Plugin *plugin = p.second.data(); if (plugin && plugin->desktopFile().id() == id) return plugin; } return nullptr; } void PanelPluginsModel::addPlugin(const UKUi::PluginInfo &desktopFile) { if (dynamic_cast(qApp)->isPluginSingletonAndRunnig(desktopFile.id())) return; QString name = findNewPluginSettingsGroup(desktopFile.id()); QPointer plugin = loadPlugin(desktopFile, name); if (plugin.isNull()) return; qDebug()<< plugin->name()<settings()->setValue(mNamesKey, pluginNames()); emit pluginAdded(plugin.data()); } void PanelPluginsModel::removePlugin(pluginslist_t::iterator plugin) { if (mPlugins.end() != plugin) { mPanel->settings()->remove(plugin->first); Plugin * p = plugin->second.data(); const int row = plugin - mPlugins.begin(); beginRemoveRows(QModelIndex(), row, row); mPlugins.erase(plugin); endRemoveRows(); emit pluginRemoved(p); // p can be nullptr mPanel->settings()->setValue(mNamesKey, pluginNames()); if (nullptr != p) p->deleteLater(); } } void PanelPluginsModel::removePlugin() { Plugin * p = qobject_cast(sender()); auto plugin = std::find_if(mPlugins.begin(), mPlugins.end(), [p] (pluginslist_t::const_reference obj) { return p == obj.second; }); removePlugin(std::move(plugin)); } void PanelPluginsModel::movePlugin(Plugin * plugin, QString const & nameAfter) { //merge list of plugins (try to preserve original position) //subtract mPlugin.begin() from the found Plugins to get the model index const int from = std::find_if(mPlugins.begin(), mPlugins.end(), [plugin] (pluginslist_t::const_reference obj) { return plugin == obj.second.data(); }) - mPlugins.begin(); const int to = std::find_if(mPlugins.begin(), mPlugins.end(), [nameAfter] (pluginslist_t::const_reference obj) { return nameAfter == obj.first; }) - mPlugins.begin(); /* 'from' is the current position of the Plugin to be moved ("moved Plugin"), * 'to' is the position of the Plugin behind the one that is being moved * ("behind Plugin"). There are several cases to distinguish: * 1. from > to: The moved Plugin had been behind the behind Plugin before * and is moved to the front of the behind Plugin. The moved Plugin will * be inserted at position 'to', the behind Plugin and all the following * Plugins (until the former position of the moved Plugin) will increment * their indexes. * 2. from < to: The moved Plugin had already been located before the * behind Plugin. In this case, the move operation only reorders the * Plugins before the behind Plugin. All the Plugins between the moved * Plugin and the behind Plugin will decrement their index. Therefore, the * movedPlugin will not be at position 'to' but rather on position 'to-1'. * 3. from == to: This does not make sense, we catch this case to prevent * errors. * 4. from == to-1: The moved Plugin has not moved because it had already * been located in front of the behind Plugin. */ const int to_plugins = from < to ? to - 1 : to; if (from != to && from != to_plugins) { /* Although the new position of the moved Plugin will be 'to-1' if * from < to, we insert 'to' here. This is exactly how it is done * in the Qt documentation. */ beginMoveRows(QModelIndex(), from, from, QModelIndex(), to); // For the QList::move method, use the right position mPlugins.move(from, to_plugins); endMoveRows(); emit pluginMoved(plugin); mPanel->settings()->setValue(mNamesKey, pluginNames()); } } void PanelPluginsModel::loadPlugins(QStringList const & desktopDirs) { QStringList plugin_names = mPanel->settings()->value(mNamesKey).toStringList(); qDebug()<<"desktopDirs = "<settings()->value(name + "/type").toString(); if (type.isEmpty()) { qWarning() << QString("Section \"%1\" not found in %2.").arg(name, mPanel->settings()->fileName()); continue; } #ifdef WITH_SCREENSAVER_FALLBACK if (QStringLiteral("screensaver") == type) { //plugin-screensaver was dropped //convert settings to plugin-quicklaunch const QString & lock_desktop = QStringLiteral(UKUI_LOCK_DESKTOP); qWarning().noquote() << "Found deprecated plugin of type 'screensaver', migrating to 'quicklaunch' with '" << lock_desktop << '\''; type = QStringLiteral("quicklaunch"); UKUi::Settings * settings = mPanel->settings(); settings->beginGroup(name); settings->remove(QString{});//remove all existing keys settings->setValue(QStringLiteral("type"), type); settings->beginWriteArray(QStringLiteral("apps"), 1); settings->setArrayIndex(0); settings->setValue(QStringLiteral("desktop"), lock_desktop); settings->endArray(); settings->endGroup(); } #endif UKUi::PluginInfoList list = UKUi::PluginInfo::search(desktopDirs, "UKUIPanel/Plugin", QString("%1.desktop").arg(type)); if( !list.count()) { qWarning() << QString("Plugin \"%1\" not found.").arg(type); continue; } i->second = loadPlugin(list.first(), name); #ifdef DEBUG_PLUGIN_LOADTIME qDebug() << "load plugin" << type << "takes" << (timer.elapsed() - lastTime) << "ms"; lastTime = timer.elapsed(); #endif } } QPointer PanelPluginsModel::loadPlugin(UKUi::PluginInfo const & desktopFile, QString const & settingsGroup) { std::unique_ptr plugin(new Plugin(desktopFile, mPanel->settings(), settingsGroup, mPanel)); if (plugin->isLoaded()) { connect(mPanel, &UKUIPanel::realigned, plugin.get(), &Plugin::realign); connect(plugin.get(), &Plugin::remove, this, static_cast(&PanelPluginsModel::removePlugin)); return plugin.release(); } return nullptr; } QString PanelPluginsModel::findNewPluginSettingsGroup(const QString &pluginType) const { QStringList groups = mPanel->settings()->childGroups(); groups.sort(); // Generate new section name QString pluginName = QString("%1").arg(pluginType); if (!groups.contains(pluginName)) return pluginName; else { for (int i = 2; true; ++i) { pluginName = QString("%1%2").arg(pluginType).arg(i); if (!groups.contains(pluginName)) return pluginName; } } } bool PanelPluginsModel::isIndexValid(QModelIndex const & index) const { return index.isValid() && QModelIndex() == index.parent() && 0 == index.column() && mPlugins.size() > index.row(); } void PanelPluginsModel::onMovePluginUp(QModelIndex const & index) { if (!isIndexValid(index)) return; const int row = index.row(); if (0 >= row) return; //can't move up beginMoveRows(QModelIndex(), row, row, QModelIndex(), row - 1); mPlugins.swap(row - 1, row); endMoveRows(); pluginslist_t::const_reference moved_plugin = mPlugins[row - 1]; pluginslist_t::const_reference prev_plugin = mPlugins[row]; emit pluginMoved(moved_plugin.second.data()); //emit signal for layout only in case both plugins are loaded/displayed if (!moved_plugin.second.isNull() && !prev_plugin.second.isNull()) emit pluginMovedUp(moved_plugin.second.data()); mPanel->settings()->setValue(mNamesKey, pluginNames()); } void PanelPluginsModel::onMovePluginDown(QModelIndex const & index) { if (!isIndexValid(index)) return; const int row = index.row(); if (mPlugins.size() <= row + 1) return; //can't move down beginMoveRows(QModelIndex(), row, row, QModelIndex(), row + 2); mPlugins.swap(row, row + 1); endMoveRows(); pluginslist_t::const_reference moved_plugin = mPlugins[row + 1]; pluginslist_t::const_reference next_plugin = mPlugins[row]; emit pluginMoved(moved_plugin.second.data()); //emit signal for layout only in case both plugins are loaded/displayed if (!moved_plugin.second.isNull() && !next_plugin.second.isNull()) emit pluginMovedUp(next_plugin.second.data()); mPanel->settings()->setValue(mNamesKey, pluginNames()); } void PanelPluginsModel::onConfigurePlugin(QModelIndex const & index) { if (!isIndexValid(index)) return; Plugin * const plugin = mPlugins[index.row()].second.data(); if (nullptr != plugin && (IUKUIPanelPlugin::HaveConfigDialog & plugin->iPlugin()->flags())) plugin->showConfigureDialog(); } void PanelPluginsModel::onRemovePlugin(QModelIndex const & index) { if (!isIndexValid(index)) return; auto plugin = mPlugins.begin() + index.row(); if (plugin->second.isNull()) removePlugin(std::move(plugin)); else plugin->second->requestRemove(); } ukui-panel/panel/customstyle.cpp0000644000175000017500000003664113640356246015771 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #if QT_CONFIG(toolbutton) static void drawArrow(const QStyle *style, const QStyleOptionToolButton *toolbutton, const QRect &rect, QPainter *painter, const QWidget *widget = 0) { QStyle::PrimitiveElement pe; switch (toolbutton->arrowType) { case Qt::LeftArrow: pe = QStyle::PE_IndicatorArrowLeft; break; case Qt::RightArrow: pe = QStyle::PE_IndicatorArrowRight; break; case Qt::UpArrow: pe = QStyle::PE_IndicatorArrowUp; break; case Qt::DownArrow: pe = QStyle::PE_IndicatorArrowDown; break; default: return; } QStyleOption arrowOpt = *toolbutton; arrowOpt.rect = rect; style->drawPrimitive(pe, &arrowOpt, painter, widget); } #endif // QT_CONFIG(toolbutton) CustomStyle::CustomStyle(const QString &proxyStyleName, QObject *parent) : QProxyStyle (proxyStyleName) { } CustomStyle::~CustomStyle() { }; void CustomStyle::drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const { // if(control == CC_ToolButton) // { // /// 我们需要获取ToolButton的详细信息,通过qstyleoption_cast可以得到 // /// 对应的option,通过拷贝构造函数得到一份备份用于绘制子控件 // /// 我们一般不用在意option是怎么得到的,大部分的Qt控件都能够提供了option的init方法 // } switch (cc) { case CC_ToolButton: if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast(opt)) { QRect button, menuarea; button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget); menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget); State bflags = toolbutton->state & ~State_Sunken; if (bflags & State_AutoRaise) { if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) { bflags &= ~State_Raised; } } State mflags = bflags; if (toolbutton->state & State_Sunken) { if (toolbutton->activeSubControls & SC_ToolButton) bflags |= State_Sunken; mflags |= State_Sunken; } QStyleOption tool = *toolbutton; if (toolbutton->subControls & SC_ToolButton) { if (bflags & (State_Sunken | State_On | State_Raised)) { tool.rect = button; tool.state = bflags; proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); } } if (toolbutton->state & State_HasFocus) { QStyleOptionFocusRect fr; fr.QStyleOption::operator=(*toolbutton); fr.rect.adjust(3, 3, -3, -3); if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup) fr.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, toolbutton, widget), 0); proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget); } QStyleOptionToolButton label = *toolbutton; label.state = bflags; int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); label.rect = button.adjusted(fw, fw, -fw, -fw); proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); if (toolbutton->subControls & SC_ToolButtonMenu) { tool.rect = menuarea; tool.state = mflags; if (mflags & (State_Sunken | State_On | State_Raised)) proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget); proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget); } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget); QRect ir = toolbutton->rect; QStyleOptionToolButton newBtn = *toolbutton; newBtn.rect = QRect(ir.right() + 5 - mbi, ir.y() + ir.height() - mbi + 4, mbi - 6, mbi - 6); newBtn.rect = visualRect(toolbutton->direction, button, newBtn.rect); //proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); } } return; default: break; } return QProxyStyle::drawComplexControl(cc, opt, p, widget); } void CustomStyle::drawControl(QStyle::ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *widget) const { switch (element) { case CE_ToolButtonLabel: { if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast(opt)) { QRect rect = toolbutton->rect; int shiftX = 0; int shiftY = 0; // if (toolbutton->state & (State_Sunken | State_On)) { // shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, toolbutton, widget); // shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, toolbutton, widget); // } // Arrow type always overrules and is always shown bool hasArrow = toolbutton->features & QStyleOptionToolButton::Arrow; if (((!hasArrow && toolbutton->icon.isNull()) && !toolbutton->text.isEmpty()) || toolbutton->toolButtonStyle == Qt::ToolButtonTextOnly) { int alignment = Qt::AlignCenter | Qt::TextShowMnemonic; if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget)) alignment |= Qt::TextHideMnemonic; rect.translate(shiftX, shiftY); p->setFont(toolbutton->font); proxy()->drawItemText(p, rect, alignment, toolbutton->palette, opt->state & State_Enabled, toolbutton->text, QPalette::ButtonText); } else { QPixmap pm; QSize pmSize = toolbutton->iconSize; if (!toolbutton->icon.isNull()) { QIcon::State state = toolbutton->state & State_On ? QIcon::On : QIcon::Off; QIcon::Mode mode; if (!(toolbutton->state & State_Enabled)) mode = QIcon::Disabled; else if ((opt->state & State_MouseOver) && (opt->state & State_AutoRaise)) mode = QIcon::Active; else mode = QIcon::Normal; pm = toolbutton->icon.pixmap(widget->window()->windowHandle(), toolbutton->rect.size().boundedTo(toolbutton->iconSize), mode, state); pmSize = pm.size() / pm.devicePixelRatio(); } if (toolbutton->toolButtonStyle != Qt::ToolButtonIconOnly) { p->setFont(toolbutton->font); QRect pr = rect, tr = rect; int alignment = Qt::TextShowMnemonic; if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget)) alignment |= Qt::TextHideMnemonic; if (toolbutton->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { pr.setHeight(pmSize.height() + 4); //### 4 is currently hardcoded in QToolButton::sizeHint() tr.adjust(0, pr.height() - 1, 0, -1); pr.translate(shiftX, shiftY); if (!hasArrow) { proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pm); } else { drawArrow(proxy(), toolbutton, pr, p, widget); } alignment |= Qt::AlignCenter; } else { pr.setWidth(pmSize.width() + 4); //### 4 is currently hardcoded in QToolButton::sizeHint() tr.adjust(pr.width(), 0, 0, 0); pr.translate(shiftX, shiftY); if (!hasArrow) { proxy()->drawItemPixmap(p, QStyle::visualRect(opt->direction, rect, pr), Qt::AlignCenter, pm); } else { drawArrow(proxy(), toolbutton, pr, p, widget); } alignment |= Qt::AlignLeft | Qt::AlignVCenter; } tr.translate(shiftX, shiftY); //const QString text = d->toolButtonElideText(toolbutton, tr, alignment); proxy()->drawItemText(p, QStyle::visualRect(opt->direction, rect, tr), alignment, toolbutton->palette, toolbutton->state & State_Enabled, toolbutton->text, QPalette::ButtonText); } else { rect.translate(shiftX, shiftY); if (hasArrow) { drawArrow(proxy(), toolbutton, rect, p, widget); } else { proxy()->drawItemPixmap(p, rect, Qt::AlignCenter, pm); } } } } return; } default: break; } return QProxyStyle::drawControl(element, opt, p, widget); } void CustomStyle::drawItemPixmap(QPainter *painter, const QRect &rectangle, int alignment, const QPixmap &pixmap) const { return QProxyStyle::drawItemPixmap(painter, rectangle, alignment, pixmap); } void CustomStyle::drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, bool enabled, const QString &text, QPalette::ColorRole textRole) const { return QProxyStyle::drawItemText(painter, rectangle, alignment, palette, enabled, text, textRole); } //绘制简单的颜色圆角等 void CustomStyle::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { switch (element) { //绘制 ToolButton case PE_PanelButtonTool:{ painter->save(); painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); // painter->setBrush(QColor(0xff,0xff,0xff,0xff)); painter->drawRoundedRect(option->rect,6,6); if (option->state & State_MouseOver) { if (option->state & State_Sunken) { painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); painter->setBrush(QColor(0xff,0xff,0xff,0x0f)); painter->drawRoundedRect(option->rect,6,6); } else { painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); painter->setBrush(QColor(0xff,0xff,0xff,0x1f)); painter->drawRoundedRect(option->rect.adjusted(2,2,-2,-2),6,6); } } painter->restore(); return; }break; } return QProxyStyle::drawPrimitive(element, option, painter, widget); } QPixmap CustomStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const { return QProxyStyle::generatedIconPixmap(iconMode, pixmap, option); } QStyle::SubControl CustomStyle::hitTestComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, const QPoint &position, const QWidget *widget) const { return QProxyStyle::hitTestComplexControl(control, option, position, widget); } QRect CustomStyle::itemPixmapRect(const QRect &rectangle, int alignment, const QPixmap &pixmap) const { return QProxyStyle::itemPixmapRect(rectangle, alignment, pixmap); } QRect CustomStyle::itemTextRect(const QFontMetrics &metrics, const QRect &rectangle, int alignment, bool enabled, const QString &text) const { return QProxyStyle::itemTextRect(metrics, rectangle, alignment, enabled, text); } // int CustomStyle::pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const { switch (metric){ case PM_ToolBarIconSize:{ return (int)48*qApp->devicePixelRatio(); } default: break; } return QProxyStyle::pixelMetric(metric, option, widget); } // void CustomStyle::polish(QWidget *widget) { widget->setAttribute(Qt::WA_Hover); return QProxyStyle::polish(widget); } void CustomStyle::polish(QApplication *application) { return QProxyStyle::polish(application); } // void CustomStyle::polish(QPalette &palette) { // return QProxyStyle::polish(palette); // QProxyStyle::polish(palette); // palette.setBrush(QPalette::Foreground, Qt::black); QColor lightBlue(200, 0, 0); palette.setBrush(QPalette::Highlight, lightBlue); } void CustomStyle::unpolish(QWidget *widget) { return QProxyStyle::unpolish(widget); } void CustomStyle::unpolish(QApplication *application) { return QProxyStyle::unpolish(application); } QSize CustomStyle::sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const { return QProxyStyle::sizeFromContents(type, option, contentsSize, widget); } QIcon CustomStyle::standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const { return QProxyStyle::standardIcon(standardIcon, option, widget); } QPalette CustomStyle::standardPalette() const { return QProxyStyle::standardPalette(); } //如果需要背景透明也许需要用到这个函数 int CustomStyle::styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const { switch (hint) { /// 让ScrollView viewport的绘制区域包含scrollbar和corner widget /// 这个例子中没有什么作用,如果我们需要绘制一个背景透明的滚动条 /// 这个style hint对我们的意义应该很大,因为我们希望视图能够帮助 /// 我们填充滚动条的背景区域,否则当背景透明时底下会出现明显的分割 case SH_ScrollView_FrameOnlyAroundContents: { return false; } default: break; } return QProxyStyle::styleHint(hint, option, widget, returnData); } QRect CustomStyle::subControlRect(QStyle::ComplexControl control, const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget) const { return QProxyStyle::subControlRect(control, option, subControl, widget); } QRect CustomStyle::subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget) const { return QProxyStyle::subElementRect(element, option, widget); } ukui-panel/panel/pluginmoveprocessor.h0000644000175000017500000000454313632320722017153 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef PLUGINMOVEPROCESSOR_H #define PLUGINMOVEPROCESSOR_H #include #include #include #include "plugin.h" #include "ukuipanelglobals.h" class UKUIPanelLayout; class QLayoutItem; class UKUI_PANEL_API PluginMoveProcessor : public QWidget { Q_OBJECT public: explicit PluginMoveProcessor(UKUIPanelLayout *layout, Plugin *plugin); ~PluginMoveProcessor(); Plugin *plugin() const { return mPlugin; } signals: void finished(); public slots: void start(); protected: void mouseMoveEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void keyPressEvent(QKeyEvent *event); private slots: void doStart(); void doFinish(bool cancel); private: enum MarkType { TopMark, BottomMark, LeftMark, RightMark }; struct MousePosInfo { int index; QLayoutItem *item; bool after; }; UKUIPanelLayout *mLayout; Plugin *mPlugin; int mDestIndex; MousePosInfo itemByMousePos(const QPoint mouse) const; void drawMark(QLayoutItem *item, MarkType markType); }; class UKUI_PANEL_API CursorAnimation: public QVariantAnimation { Q_OBJECT public: void updateCurrentValue(const QVariant &value) { QCursor::setPos(value.toPoint()); } }; #endif // PLUGINMOVEPROCESSOR_H ukui-panel/panel/popupmenu.cpp0000644000175000017500000000673713633355350015426 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * Paulo Lieuthier * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "popupmenu.h" #include #include #include #include static const char POPUPMENU_TITLE[] = "POPUP_MENU_TITLE_OBJECT_NAME"; /************************************************ ************************************************/ QAction* PopupMenu::addTitle(const QIcon &icon, const QString &text) { QAction *buttonAction = new QAction(this); QFont font = buttonAction->font(); font.setBold(true); buttonAction->setText(QString(text).replace("&", "&&")); buttonAction->setFont(font); buttonAction->setIcon(icon); QWidgetAction *action = new QWidgetAction(this); action->setObjectName(POPUPMENU_TITLE); QToolButton *titleButton = new QToolButton(this); titleButton->installEventFilter(this); // prevent clicks on the title of the menu titleButton->setDefaultAction(buttonAction); titleButton->setDown(true); // prevent hover style changes in some styles titleButton->setCheckable(true); titleButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); action->setDefaultWidget(titleButton); addAction(action); return action; } /************************************************ ************************************************/ QAction* PopupMenu::addTitle(const QString &text) { return addTitle(QIcon(), text); } /************************************************ ************************************************/ bool PopupMenu::eventFilter(QObject *object, QEvent *event) { Q_UNUSED(object); if (event->type() == QEvent::Paint || event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease ) { return false; } event->accept(); return true; } /************************************************ ************************************************/ void PopupMenu::keyPressEvent(QKeyEvent* e) { if (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down) { QMenu::keyPressEvent(e); QWidgetAction *action = qobject_cast(this->activeAction()); QWidgetAction *firstAction = action; while (action && action->objectName() == POPUPMENU_TITLE) { this->keyPressEvent(e); action = qobject_cast(this->activeAction()); if (firstAction == action) // we looped and only found titles { this->setActiveAction(0); break; } } return; } QMenu::keyPressEvent(e); } ukui-panel/panel/ukuipanel.h0000644000175000017500000006767213642614010015034 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPANEL_H #define UKUIPANEL_H #include #include #include #include #include #include #include #include "common/ukuisettings.h" #include "iukuipanel.h" #include "ukuipanelglobals.h" class QMenu; class Plugin; class QAbstractItemModel; namespace UKUi { class Settings; class PluginInfo; } class UKUIPanelLayout; class ConfigPanelDialog; class PanelPluginsModel; class WindowNotifier; /*! \brief The UKUIPanel class provides a single ukui-panel. All UKUIPanel * instances should be created and handled by UKUIPanelApplication. In turn, * all Plugins should be created and handled by UKUIPanels. * * UKUIPanel is just the panel, it does not incorporate any functionality. * Each function of the panel is implemented by Plugins, even the mainmenu * (plugin-mainmenu) and the taskbar (plugin-taskbar). So the UKUIPanel is * just the container for several Plugins while the different Plugins * incorporate the functions of the panel. Without the Plugins, the panel * is quite useless because it is just a box occupying space on the screen. * * UKUIPanel itself is a window (QFrame/QWidget) and this class is mainly * responsible for handling the size and position of this window on the * screen(s) as well as the different settings. The handling of the plugins * is outsourced in PanelPluginsModel and UKUIPanelLayout. PanelPluginsModel * is responsible for loading/creating and handling the plugins. * UKUIPanelLayout is inherited from QLayout and set as layout to the * background of UKUIPanel, so UKUIPanelLayout is responsible for the * layout of all the Plugins. * * \sa UKUIPanelApplication, Plugin, PanelPluginsModel, UKUIPanelLayout. */ class UKUI_PANEL_API UKUIPanel : public QFrame, public IUKUIPanel { Q_OBJECT Q_PROPERTY(QString position READ qssPosition) // for configuration dialog friend class ConfigPanelWidget; friend class ConfigPluginsWidget; friend class ConfigPanelDialog; friend class PanelPluginsModel; public: /** * @brief Stores how the panel should be aligned. Obviously, this applies * only if the panel does not occupy 100 % of the available space. If the * panel is vertical, AlignmentLeft means align to the top border of the * screen, AlignmentRight means align to the bottom. */ enum Alignment { AlignmentLeft = -1, //!< Align the panel to the left or top AlignmentCenter = 0, //!< Center the panel AlignmentRight = 1 //!< Align the panel to the right or bottom }; /** * @brief Creates and initializes the UKUIPanel. Performs the following * steps: * 1. Sets Qt window title, flags, attributes. * 2. Creates the panel layout. * 3. Prepares the timers. * 4. Connects signals and slots. * 5. Reads the settings for this panel. * 6. Optionally moves the panel to a valid screen (position-dependent). * 7. Loads the Plugins. * 8. Shows the panel, even if it is hidable (but then, starts the timer). * @param configGroup The name of the panel which is used as identifier * in the config file. * @param settings The settings instance of this ukui panel application. * @param parent Parent QWidget, can be omitted. */ UKUIPanel(const QString &configGroup, UKUi::Settings *settings, QWidget *parent = 0); virtual ~UKUIPanel(); /** * @brief Returns the name of this panel which is also used as identifier * in the config file. */ QString name() { return mConfigGroup; } /** * @brief Reads all the necessary settings from mSettings and stores them * in local variables. Additionally, calls necessary methods like realign() * or updateStyleSheet() which need to get called after changing settings. */ void readSettings(); /** * @brief Creates and shows the popup menu (right click menu). If a plugin * is given as parameter, the menu will be divided in two groups: * plugin-specific options and panel-related options. As these two are * shown together, this menu has to be created by UKUIPanel. * @param plugin The plugin whose menu options will be included in the * context menu. */ void showPopupMenu(Plugin *plugin = 0); // IUKUIPanel overrides ........ IUKUIPanel::Position position() const override { return mPosition; } QRect globalGeometry() const override; QRect calculatePopupWindowPos(QPoint const & absolutePos, QSize const & windowSize) const override; QRect calculatePopupWindowPos(const IUKUIPanelPlugin *plugin, const QSize &windowSize) const override; void willShowWindow(QWidget * w) override; void pluginFlagsChanged(const IUKUIPanelPlugin * plugin) override; // ........ end of IUKUIPanel overrides /** * @brief Searches for a Plugin in the Plugins-list of this panel. Takes * an IUKUIPanelPlugin as parameter and returns the corresponding Plugin. * @param iPlugin IUKUIPanelPlugin that we are looking for. * @return The corresponding Plugin if it is loaded in this panel, nullptr * otherwise. */ Plugin *findPlugin(const IUKUIPanelPlugin *iPlugin) const; // For QSS properties .................. /** * @brief Returns the position as string * * \sa positionToStr(). */ QString qssPosition() const; /** * @brief Checks if this UKUIPanel can be placed at a given position * on the screen with the given screenNum. The condition for doing so * is that the panel is not located between two screens. * * For example, if position is PositionRight, there should be no screen to * the right of the given screen. That means that there should be no * screen whose left border has a higher x-coordinate than the x-coordinate * of the right border of the given screen. This method iterates over all * screens and checks these conditions. * @param screenNum screen index as it is used by QDesktopWidget methods * @param position position where the panel should be placed * @return true if this panel can be placed at the given position on the * given screen. * * \sa findAvailableScreen(), mScreenNum, mActualScreenNum. */ static bool canPlacedOn(int screenNum, UKUIPanel::Position position); /** * @brief Returns a string representation of the given position. This * string is human-readable and can be used in config files. * @param position position that should be converted to a string. * @return the string representation of the given position, i.e. * "Top", "Left", "Right" or "Bottom". * * \sa strToPosition() */ static QString positionToStr(IUKUIPanel::Position position); /** * @brief Returns an IUKUIPanel::Position from the given string. This can * be used to retrieve IUKUIPanel::Position values from the config files. * @param str string that should be converted to IUKUIPanel::Position * @param defaultValue value that will be returned if the string can not * be converted to an IUKUIPanel::Position. * @return IUKUIPanel::Position that was determined from str or * defaultValue if str could not be converted. * * \sa positionToStr() */ static IUKUIPanel::Position strToPosition(const QString &str, IUKUIPanel::Position defaultValue); // Settings int iconSize() const override { return mIconSize; } //!< Implement IUKUIPanel::iconSize(). int lineCount() const override { return mLineCount; } //!< Implement IUKUIPanel::lineCount(). int panelSize() const override{ return mPanelSize; } int length() const { return mLength; } bool lengthInPercents() const { return mLengthInPercents; } UKUIPanel::Alignment alignment() const { return mAlignment; } int screenNum() const { return mScreenNum; } QColor fontColor() const { return mFontColor; } QColor backgroundColor() const { return mBackgroundColor; } QString backgroundImage() const { return mBackgroundImage; } int opacity() const { return mOpacity; } int reserveSpace() const { return mReserveSpace; } bool hidable() const { return mHidable; } bool visibleMargin() const { return mVisibleMargin; } int animationTime() const { return mAnimationTime; } int showDelay() const { return mShowDelayTimer.interval(); } QString iconTheme() const; /*! * \brief Checks if a given Plugin is running and has the * IUKUIPanelPlugin::SingleInstance flag set. * \param pluginId Plugin Identifier which is the basename of the * .desktop file that specifies the plugin. * \return true if the Plugin is running and has the * IUKUIPanelPlugin::SingleInstance flag set, false otherwise. */ bool isPluginSingletonAndRunnig(QString const & pluginId) const; /*! * \brief Updates the config dialog. Used for updating its icons * when the panel-specific icon theme changes. */ void updateConfigDialog() const; public slots: /** * @brief Shows the QWidget and makes it visible on all desktops. This * method is NOT related to showPanel(), hidePanel() and hidePanelWork() * which handle the UKUi hiding by resizing the panel. */ void show(); /** * @brief Shows the panel (immediately) after it had been hidden before. * Stops the QTimer mHideTimer. This it NOT the same as QWidget::show() * because hiding the panel in UKUi is done by making it very thin. So * this method in fact restores the original size of the panel. * \param animate flag for the panel show-up animation disabling (\sa mAnimationTime). * * \sa mHidable, mHidden, mHideTimer, hidePanel(), hidePanelWork() */ void showPanel(bool animate); /** * @brief Hides the panel (delayed) by starting the QTimer mHideTimer. * When this timer times out, hidePanelWork() will be called. So this * method is called when the cursor leaves the panel area but the panel * will be hidden later. * * \sa mHidable, mHidden, mHideTimer, showPanel(), hidePanelWork() */ void hidePanel(); /** * @brief Actually hides the panel. Will be invoked when the QTimer * mHideTimer times out. That timer will be started by showPanel(). This * is NOT the same as QWidget::hide() because hiding the panel in UKUi is * done by making the panel very thin. So this method in fact makes the * panel very thin while the QWidget stays visible. * * \sa mHidable, mHidden, mHideTimer, showPanel(), hidePanel() */ void hidePanelWork(); // Settings /** * @brief All the setter methods are designed similar: * 1. Check if the given value is different from the current value. If not, * do not do anything and return. * 2. Set the value. * 3. If parameter save is true, call saveSettings(true) to store the * new settings on the disk. * 4. If necessary, propagate the new value to child objects, e.g. to * mLayout. * 5. If necessary, call update methods like realign() or * updateStyleSheet(). * @param value The value that should be set. * @param save If true, saveSettings(true) will be called. */ void setPanelSize(int value, bool save); void setIconSize(int value, bool save); //!< \sa setPanelSize() void setLineCount(int value, bool save); //!< \sa setPanelSize() void setLength(int length, bool inPercents, bool save); //!< \sa setPanelSize() void setPosition(int screen, IUKUIPanel::Position position, bool save); //!< \sa setPanelSize() void setAlignment(UKUIPanel::Alignment value, bool save); //!< \sa setPanelSize() void setFontColor(QColor color, bool save); //!< \sa setPanelSize() void setBackgroundColor(QColor color, bool save); //!< \sa setPanelSize() void setBackgroundImage(QString path, bool save); //!< \sa setPanelSize() void setOpacity(int opacity, bool save); //!< \sa setPanelSize() void setReserveSpace(bool reserveSpace, bool save); //!< \sa setPanelSize() void setHidable(bool hidable, bool save); //!< \sa setPanelSize() void setVisibleMargin(bool visibleMargin, bool save); //!< \sa setPanelSize() void setAnimationTime(int animationTime, bool save); //!< \sa setPanelSize() void setShowDelay(int showDelay, bool save); //!< \sa setPanelSize() void setIconTheme(const QString& iconTheme); /** * @brief Saves the current configuration, i.e. writes the current * configuration varibles to mSettings. * @param later Determines if the settings are written immediately or * after a short delay. If later==true, the QTimer mDelaySave is started. * As soon as this timer times out, saveSettings(false) will be called. If * later==false, settings will be written. */ void saveSettings(bool later=false); /** * @brief Checks if the panel can be placed on the current screen at the * current position. If it can not, it will be moved on another screen * where the desired position is possible. */ void ensureVisible(); signals: /** * @brief This signal gets emitted whenever this panel receives a * QEvent::LayoutRequest, i.e. "Widget layout needs to be redone.". * The PanelPluginsModel will connect this signal to the individual * plugins so they can realign, too. */ void realigned(); /** * @brief This signal gets emitted at the end of * userRequestForDeletion() which in turn gets called when the user * decides to remove a panel. This signal is used by * UKUIPanelApplication to get notified whenever an UKUIPanel should * be removed. * @param self This UKUIPanel. UKUIPanelApplication will use this * parameter to identify the UKUIPanel that should be removed. */ void deletedByUser(UKUIPanel *self); /** * @brief This signal is just a relay signal. The pluginAdded signal * of the PanelPluginsModel (mPlugins) will be connected to this * signal. Thereby, we can make this signal of a private member * available as a public signal. * Currently, this signal is used by UKUIPanelApplication which * will further re-emit this signal. */ void pluginAdded(); /** * @brief This signal is just a relay signal. The pluginRemoved signal * of the PanelPluginsModel (mPlugins) will be connected to this * signal. Thereby, we can make this signal of a private member * available as a public signal. * Currently, this signal is used by UKUIPanelApplication which * will further re-emit this signal. */ void pluginRemoved(); protected: /** * @brief Overrides QObject::event(QEvent * e). Some functions of * the panel will be triggered by these events, e.g. showing/hiding * the panel or showing the context menu. * @param event The event that was received. * @return "QObject::event(QEvent *e) should return true if the event e * was recognized and processed." This is done by passing the event to * QFrame::event(QEvent *e) at the end. */ bool event(QEvent *event) override; /** * @brief Overrides QWidget::showEvent(QShowEvent * event). This * method is called when a widget (in this case: the UKUIPanel) is * shown. The call could happen before and after the widget is shown. * This method is just overridden to get notified when the UKUIPanel * will be shown. Then, UKUIPanel will call realign(). * @param event The QShowEvent sent by Qt. */ void showEvent(QShowEvent *event) override; public slots: /** * @brief Shows the ConfigPanelDialog and shows the "Config Panel" * page, i.e. calls showConfigPanelPage(). If the dialog does not * exist yet, it will be created before. * * The "Configure Panel" button in the context menu of the panel will * be connected to this slot so this method gets called whenever the * user clicks that button. * * Furthermore, this method will be called by UKUIPanelApplication * when a new plugin gets added (the UKUIPanel instances are handled * by UKUIPanelApplication). That is why this method/slot has to be * public. */ void showConfigDialog(); private slots: /** * @brief Shows the ConfigPanelDialog and shows the "Config Plugins" * page, i.e. calls showConfigPluginsPage(). If the dialog does not * exist yet, it will be created before. * * The "Manage Widgets" button in the context menu of the panel will * be connected to this slot so this method gets called whenever the * user clicks that button. */ void showAddPluginDialog(); /** * @brief Recalculates the geometry of the panel and reserves the * window manager strut, i.e. it calls setPanelGeometry() and * updateWmStrut(). * Two signals will be connected to this slot: * 1. QDesktopWidget::workAreaResized(int screen) which will be emitted * when the work area available (on screen) changes. * 2. UKUi::Application::themeChanged(), i.e. when the user changes * the theme. */ void setPanelStyle(); void systeMonitor(); void showDesktop(); void showTaskView(); void realign(); /** * @brief Moves a plugin in PanelPluginsModel, i.e. calls * PanelPluginsModel::movePlugin(Plugin * plugin, QString const & nameAfter). * UKUIPanelLayout::pluginMoved() will be connected to this slot so * it gets called whenever a plugin was moved in the layout by the user. * @param plug */ void pluginMoved(Plugin * plug); /** * @brief Removes this panel's entries from the config file and emits * the deletedByUser signal. * The "Remove Panel" button in the panel's contex menu will * be connected to this slot, so this method will be called whenever * the user clicks "Remove Panel". */ void userRequestForDeletion(); private: /** * @brief The UKUIPanelLayout of this panel. All the Plugins will be added * to the UI via this layout. */ UKUIPanelLayout* mLayout; /** * @brief The UKUi::Settings instance as retrieved from * UKUIPanelApplication. */ UKUi::Settings *mSettings; /** * @brief The background widget for the panel. This background widget will * have the background color or the background image if any of these is * set. This background widget will have the UKUIPanelLayout mLayout which * will in turn contain all the Plugins. */ QFrame *UKUIPanelWidget; /** * @brief The name of the panel which will also be used as an identifier * for config files. */ QString mConfigGroup; /** * @brief Pointer to the PanelPluginsModel which will store all the Plugins * that are loaded. */ QScopedPointer mPlugins; /** * @brief object for storing info if some standalone window is shown * (for preventing hide) */ QScopedPointer mStandaloneWindows; /** * @brief Returns the screen index of a screen on which this panel could * be placed at the given position. If possible, the current screen index * is preserved. So, if the panel can be placed on the current screen, the * index of that screen will be returned. * @param position position at which the panel should be placed. * @return The current screen index if the panel can be placed on the * current screen or the screen index of a screen that it can be placed on. * * \sa canPlacedOn(), mScreenNum, mActualScreenNum. */ int findAvailableScreen(UKUIPanel::Position position); /** * @brief Update the window manager struts _NET_WM_PARTIAL_STRUT and * _NET_WM_STRUT for this widget. "The purpose of struts is to reserve * space at the borders of the desktop. This is very useful for a * docking area, a taskbar or a panel, for instance. The Window Manager * should take this reserved area into account when constraining window * positions - maximized windows, for example, should not cover that * area." * \sa http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#NETWMSTRUT */ void updateWmStrut(); /** * @brief Loads the plugins, i.e. creates a new PanelPluginsModel. * Connects the signals and slots and adds all the plugins to the * layout. */ void loadPlugins(); /** * @brief Calculates and sets the geometry (i.e. the position and the size * on the screen) of the panel. Considers alignment, position, if the panel * is hidden and if its geometry should be set with animation. * \param animate flag if showing/hiding the panel should be animated. */ void setPanelGeometry(bool animate = false); /** * @brief Sets the contents margins of the panel according to its position * and hiddenness. All margins are zero for visible panels. */ void setMargins(); /** * @brief Calculates the height of the panel if it is horizontal or the * width if the panel is vertical. Considers if the panel is hidden and * ensures that the result is at least PANEL_MINIMUM_SIZE. * @return The height/width of the panel. */ int getReserveDimension(); /** * @brief Stores the size of the panel, i.e. the height of a horizontal * panel or the width of a vertical panel in pixels. If the panel is * hidden (which is achieved by making the panel very thin), this value * is unchanged. So this value stores the size of the non-hidden panel. * * \sa panelSize(), setPanelSize(). */ int mPanelSize; /** * @brief Stores the edge length of the panel icons in pixels. * * \sa IUKUIPanel::iconSize(), setIconSize(). */ int mIconSize; /** * @brief Stores the number of lines/rows of the panel. * * \sa IUKUIPanel::lineCount(), setLineCount(). */ int mLineCount; /** * @brief Stores the length of the panel, i.e. the width of a horizontal * panel or the height of a vertical panel. The unit of this value is * determined by mLengthInPercents. * * \sa mLengthInPercents */ int mLength; /** * @brief Stores if mLength is stored in pixels or relative to the * screen size in percents. If true, the length is stored in percents, * otherwise in pixels. * * \sa mLength */ bool mLengthInPercents; /** * @brief Stores how this panel is aligned. The meaning of this value * differs for horizontal and vertical panels. * * \sa Alignment. */ Alignment mAlignment; /** * @brief Stores the position where the panel is shown */ IUKUIPanel::Position mPosition; /** * @brief Returns the index of the screen on which this panel should be * shown. This is the user configured value which can differ from the * screen that the panel is actually shown on. If the panel can not be * shown on the configured screen, UKUIPanel will determine another * screen. The screen that the panel is actually shown on is stored in * mActualScreenNum. * * @return The index of the screen on which this panel should be shown. * * \sa mActualScreenNum, canPlacedOn(), findAvailableScreen(). */ int mScreenNum; /** * @brief screen that the panel is currently shown at (this could * differ from mScreenNum). * * \sa mScreenNum, canPlacedOn(), findAvailableScreen(). */ int mActualScreenNum; /** * @brief QTimer for delayed saving of changed settings. In many cases, * instead of storing changes to disk immediately we start this timer. * If this timer times out, we store the changes to disk. This has the * advantage that we can store a couple of changes with only one write to * disk. * * \sa saveSettings() */ QTimer mDelaySave; /** * @brief Stores if the panel is hidable, i.e. if the panel will be * hidden after the cursor has left the panel area. * * \sa mVisibleMargin, mHidden, mHideTimer, showPanel(), hidePanel(), hidePanelWork() */ bool mHidable; /** * @brief Stores if the hidable panel should have a visible margin. * * \sa mHidable, mHidden, mHideTimer, showPanel(), hidePanel(), hidePanelWork() */ bool mVisibleMargin; /** * @brief Stores if the panel is currently hidden. * * \sa mHidable, mVisibleMargin, mHideTimer, showPanel(), hidePanel(), hidePanelWork() */ bool mHidden; /** * @brief QTimer for hiding the panel. When the cursor leaves the panel * area, this timer will be started. After this timer has timed out, the * panel will actually be hidden. * * \sa mHidable, mVisibleMargin, mHidden, showPanel(), hidePanel(), hidePanelWork() */ QTimer mHideTimer; /** * @brief Stores the duration of auto-hide animation. * * \sa mHidden, mHideTimer, showPanel(), hidePanel(), hidePanelWork() */ int mAnimationTime; /** * @brief The timer used for showing an auto-hiding panel wih delay. * * \sa showPanel() */ QTimer mShowDelayTimer; QColor mFontColor; //!< Font color that is used in the style sheet. QColor mBackgroundColor; //!< Background color that is used in the style sheet. QString mBackgroundImage; //!< Background image that is used in the style sheet. /** * @brief Determines the opacity of the background color. The value * should be in the range from 0 to 100. This will not affect the opacity * of a background image. */ int mOpacity; /*! * \brief Flag if the panel should reserve the space under it as not usable * for "normal" windows. Usable for not 100% wide/hight or hiddable panels, * if user wants maximized windows go under the panel. * * \sa updateWmStrut() */ bool mReserveSpace; /** * @brief Pointer to the current ConfigPanelDialog if there is any. Make * sure to test this pointer for validity because it is lazily loaded. */ QPointer mConfigDialog; //ConfigPanelDialog *mConfigDialog; //QPointer mConfigWidget; /** * @brief The animation used for showing/hiding an auto-hiding panel. */ QPropertyAnimation *mAnimation; /** * @brief Flag for providing the configuration options in panel's context menu */ bool mLockPanel; /** * @brief Updates the style sheet for the panel. First, the stylesheet is * created from the preferences. Then, it is set via * QWidget::setStyleSheet(). */ void updateStyleSheet(); // settings should be kept private for security UKUi::Settings *settings() const { return mSettings; } private slots: void setPanelPosition(Position position); void changePositionToTop(); void changePositionToBottom(); void changePositionToLeft(); void changePositionToRight(); void changeSizeToSmall(); void changeSizeToMedium(); void changeSizeToLarge(); void panelReset(); void panelBackgroundChange(); public: QGSettings *gsettings; }; #endif // UKUIPANEL_H ukui-panel/panel/ukuicontrolstyle.h0000644000175000017500000000230313642614010016452 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include class UKUiMenu:public QMenu { public: UKUiMenu(); ~UKUiMenu(); protected: void paintEvent(QPaintEvent*); }; class UkuiToolButton:public QToolButton { public: UkuiToolButton(); ~UkuiToolButton(); void paintTooltipStyle(); }; class UKUiFrame:public QFrame { public: UKUiFrame(); ~UKUiFrame(); protected: void paintEvent(QPaintEvent*); }; #endif ukui-panel/panel/ukuipanellayout.cpp0000644000175000017500000007057413632320722016623 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuipanellayout.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "plugin.h" #include "ukuipanellimits.h" #include "iukuipanelplugin.h" #include "ukuipanel.h" #include "pluginmoveprocessor.h" #include #include #define ANIMATION_DURATION 250 class ItemMoveAnimation : public QVariantAnimation { public: ItemMoveAnimation(QLayoutItem *item) : mItem(item) { setEasingCurve(QEasingCurve::OutBack); setDuration(ANIMATION_DURATION); } void updateCurrentValue(const QVariant ¤t) { mItem->setGeometry(current.toRect()); } private: QLayoutItem* mItem; }; struct LayoutItemInfo { LayoutItemInfo(QLayoutItem *layoutItem=0); QLayoutItem *item; QRect geometry; bool separate; bool expandable; }; LayoutItemInfo::LayoutItemInfo(QLayoutItem *layoutItem): item(layoutItem), separate(false), expandable(false) { if (!item) return; Plugin *p = qobject_cast(item->widget()); if (p) { separate = p->isSeparate(); expandable = p->isExpandable(); return; } } /************************************************ This is logical plugins grid, it's same for horizontal and vertical panel. Plugins keeps as: <---LineCount--> + ---+----+----+ | P1 | P2 | P3 | +----+----+----+ | P4 | P5 | | +----+----+----+ ... +----+----+----+ | PN | | | +----+----+----+ ************************************************/ class LayoutItemGrid { public: explicit LayoutItemGrid(); ~LayoutItemGrid(); void addItem(QLayoutItem *item); int count() const { return mItems.count(); } QLayoutItem *itemAt(int index) const { return mItems[index]; } QLayoutItem *takeAt(int index); const LayoutItemInfo &itemInfo(int row, int col) const; LayoutItemInfo &itemInfo(int row, int col); void update(); int lineSize() const { return mLineSize; } void setLineSize(int value); int colCount() const { return mColCount; } void setColCount(int value); int usedColCount() const { return mUsedColCount; } int rowCount() const { return mRowCount; } void invalidate() { mValid = false; } bool isValid() const { return mValid; } QSize sizeHint() const { return mSizeHint; } bool horiz() const { return mHoriz; } void setHoriz(bool value); void clear(); void rebuild(); bool isExpandable() const { return mExpandable; } int expandableSize() const { return mExpandableSize; } void moveItem(int from, int to); private: QVector mInfoItems; int mColCount; int mUsedColCount; int mRowCount; bool mValid; int mExpandableSize; int mLineSize; QSize mSizeHint; QSize mMinSize; bool mHoriz; int mNextRow; int mNextCol; bool mExpandable; QList mItems; void doAddToGrid(QLayoutItem *item); }; /************************************************ ************************************************/ LayoutItemGrid::LayoutItemGrid() { mLineSize = 0; mHoriz = true; clear(); } LayoutItemGrid::~LayoutItemGrid() { qDeleteAll(mItems); } /************************************************ ************************************************/ void LayoutItemGrid::clear() { mRowCount = 0; mNextRow = 0; mNextCol = 0; mInfoItems.resize(0); mValid = false; mExpandable = false; mExpandableSize = 0; mUsedColCount = 0; mSizeHint = QSize(0,0); mMinSize = QSize(0,0); } /************************************************ ************************************************/ void LayoutItemGrid::rebuild() { clear(); for(QLayoutItem *item : qAsConst(mItems)) { doAddToGrid(item); } } /************************************************ ************************************************/ void LayoutItemGrid::addItem(QLayoutItem *item) { doAddToGrid(item); mItems.append(item); } /************************************************ ************************************************/ void LayoutItemGrid::doAddToGrid(QLayoutItem *item) { LayoutItemInfo info(item); if (info.separate && mNextCol > 0) { mNextCol = 0; mNextRow++; } int cnt = (mNextRow + 1 ) * mColCount; if (mInfoItems.count() <= cnt) mInfoItems.resize(cnt); int idx = mNextRow * mColCount + mNextCol; mInfoItems[idx] = info; mUsedColCount = qMax(mUsedColCount, mNextCol + 1); mExpandable = mExpandable || info.expandable; mRowCount = qMax(mRowCount, mNextRow+1); if (info.separate || mNextCol >= mColCount-1) { mNextRow++; mNextCol = 0; } else { mNextCol++; } invalidate(); } /************************************************ ************************************************/ QLayoutItem *LayoutItemGrid::takeAt(int index) { QLayoutItem *item = mItems.takeAt(index); rebuild(); return item; } /************************************************ ************************************************/ void LayoutItemGrid::moveItem(int from, int to) { mItems.move(from, to); rebuild(); } /************************************************ ************************************************/ const LayoutItemInfo &LayoutItemGrid::itemInfo(int row, int col) const { return mInfoItems[row * mColCount + col]; } /************************************************ ************************************************/ LayoutItemInfo &LayoutItemGrid::itemInfo(int row, int col) { return mInfoItems[row * mColCount + col]; } /************************************************ ************************************************/ void LayoutItemGrid::update() { mExpandableSize = 0; mSizeHint = QSize(0,0); if (mHoriz) { mSizeHint.setHeight(mLineSize * mColCount); int x = 0; for (int r=0; rsizeHint(); info.geometry = QRect(QPoint(x,y), sz); y += sz.height(); rw = qMax(rw, sz.width()); } x += rw; if (itemInfo(r, 0).expandable) mExpandableSize += rw; mSizeHint.setWidth(x); mSizeHint.rheight() = qMax(mSizeHint.rheight(), y); } } else { mSizeHint.setWidth(mLineSize * mColCount); int y = 0; for (int r=0; rsizeHint(); info.geometry = QRect(QPoint(x,y), sz); x += sz.width(); rh = qMax(rh, sz.height()); } y += rh; if (itemInfo(r, 0).expandable) mExpandableSize += rh; mSizeHint.setHeight(y); mSizeHint.rwidth() = qMax(mSizeHint.rwidth(), x); } } mValid = true; } /************************************************ ************************************************/ void LayoutItemGrid::setLineSize(int value) { mLineSize = qMax(1, value); invalidate(); } /************************************************ ************************************************/ void LayoutItemGrid::setColCount(int value) { mColCount = qMax(1, value); rebuild(); } /************************************************ ************************************************/ void LayoutItemGrid::setHoriz(bool value) { mHoriz = value; invalidate(); } /************************************************ ************************************************/ UKUIPanelLayout::UKUIPanelLayout(QWidget *parent) : QLayout(parent), mLeftGrid(new LayoutItemGrid()), mRightGrid(new LayoutItemGrid()), mPosition(IUKUIPanel::PositionBottom), mAnimate(false) { setContentsMargins(0, 0, 0, 0); } /************************************************ ************************************************/ UKUIPanelLayout::~UKUIPanelLayout() { delete mLeftGrid; delete mRightGrid; } /************************************************ ************************************************/ void UKUIPanelLayout::addItem(QLayoutItem *item) { LayoutItemGrid *grid = mRightGrid; Plugin *p = qobject_cast(item->widget()); if (p && p->alignment() == Plugin::AlignLeft) grid = mLeftGrid; grid->addItem(item); } /************************************************ ************************************************/ void UKUIPanelLayout::globalIndexToLocal(int index, LayoutItemGrid **grid, int *gridIndex) { if (index < mLeftGrid->count()) { *grid = mLeftGrid; *gridIndex = index; return; } *grid = mRightGrid; *gridIndex = index - mLeftGrid->count(); } /************************************************ ************************************************/ void UKUIPanelLayout::globalIndexToLocal(int index, LayoutItemGrid **grid, int *gridIndex) const { if (index < mLeftGrid->count()) { *grid = mLeftGrid; *gridIndex = index; return; } *grid = mRightGrid; *gridIndex = index - mLeftGrid->count(); } /************************************************ ************************************************/ QLayoutItem *UKUIPanelLayout::itemAt(int index) const { if (index < 0 || index >= count()) return 0; LayoutItemGrid *grid=0; int idx=0; globalIndexToLocal(index, &grid, &idx); return grid->itemAt(idx); } /************************************************ ************************************************/ QLayoutItem *UKUIPanelLayout::takeAt(int index) { if (index < 0 || index >= count()) return 0; LayoutItemGrid *grid=0; int idx=0; globalIndexToLocal(index, &grid, &idx); return grid->takeAt(idx); } /************************************************ ************************************************/ int UKUIPanelLayout::count() const { return mLeftGrid->count() + mRightGrid->count(); } /************************************************ ************************************************/ void UKUIPanelLayout::moveItem(int from, int to, bool withAnimation) { if (from != to) { LayoutItemGrid *fromGrid=0; int fromIdx=0; globalIndexToLocal(from, &fromGrid, &fromIdx); LayoutItemGrid *toGrid=0; int toIdx=0; globalIndexToLocal(to, &toGrid, &toIdx); if (fromGrid == toGrid) { fromGrid->moveItem(fromIdx, toIdx); } else { QLayoutItem *item = fromGrid->takeAt(fromIdx); toGrid->addItem(item); //recalculate position because we removed from one and put to another grid LayoutItemGrid *toGridAux=0; globalIndexToLocal(to, &toGridAux, &toIdx); Q_ASSERT(toGrid == toGridAux); //grid must be the same (if not something is wrong with our logic) toGrid->moveItem(toGridAux->count()-1, toIdx); } } mAnimate = withAnimation; invalidate(); } /************************************************ ************************************************/ QSize UKUIPanelLayout::sizeHint() const { if (!mLeftGrid->isValid()) mLeftGrid->update(); if (!mRightGrid->isValid()) mRightGrid->update(); QSize ls = mLeftGrid->sizeHint(); QSize rs = mRightGrid->sizeHint(); if (isHorizontal()) { return QSize(ls.width() + rs.width(), qMax(ls.height(), rs.height())); } else { return QSize(qMax(ls.width(), rs.width()), ls.height() + rs.height()); } } /************************************************ ************************************************/ void UKUIPanelLayout::setGeometry(const QRect &geometry) { if (!mLeftGrid->isValid()) mLeftGrid->update(); if (!mRightGrid->isValid()) mRightGrid->update(); QRect my_geometry{geometry}; my_geometry -= contentsMargins(); if (count()) { if (isHorizontal()) setGeometryHoriz(my_geometry); else setGeometryVert(my_geometry); } mAnimate = false; QLayout::setGeometry(my_geometry); } /************************************************ ************************************************/ void UKUIPanelLayout::setItemGeometry(QLayoutItem *item, const QRect &geometry, bool withAnimation) { Plugin *plugin = qobject_cast(item->widget()); if (withAnimation && plugin) { ItemMoveAnimation* animation = new ItemMoveAnimation(item); animation->setStartValue(item->geometry()); animation->setEndValue(geometry); animation->start(animation->DeleteWhenStopped); } else { item->setGeometry(geometry); } } /************************************************ ************************************************/ void UKUIPanelLayout::setGeometryHoriz(const QRect &geometry) { const bool visual_h_reversed = parentWidget() && parentWidget()->isRightToLeft(); // Calc expFactor for expandable plugins like TaskBar. double expFactor; { int expWidth = mLeftGrid->expandableSize() + mRightGrid->expandableSize(); int nonExpWidth = mLeftGrid->sizeHint().width() - mLeftGrid->expandableSize() + mRightGrid->sizeHint().width() - mRightGrid->expandableSize(); expFactor = expWidth ? ((1.0 * geometry.width() - nonExpWidth) / expWidth) : 1; } // Calc baselines for plugins like button. QVector baseLines(qMax(mLeftGrid->colCount(), mRightGrid->colCount())); const int bh = geometry.height() / baseLines.count(); const int base_center = bh >> 1; const int height_remain = 0 < bh ? geometry.height() % baseLines.size() : 0; { int base = geometry.top(); for (auto i = baseLines.begin(), i_e = baseLines.end(); i_e != i; ++i, base += bh) { *i = base; } } #if 0 qDebug() << "** UKUIPanelLayout::setGeometryHoriz **************"; qDebug() << "geometry: " << geometry; qDebug() << "Left grid"; qDebug() << " cols:" << mLeftGrid->colCount() << " rows:" << mLeftGrid->rowCount(); qDebug() << " usedCols" << mLeftGrid->usedColCount(); qDebug() << "Right grid"; qDebug() << " cols:" << mRightGrid->colCount() << " rows:" << mRightGrid->rowCount(); qDebug() << " usedCols" << mRightGrid->usedColCount(); #endif // Left aligned plugins. int left=geometry.left(); for (int r=0; rrowCount(); ++r) { int rw = 0; int remain = height_remain; for (int c=0; cusedColCount(); ++c) { const LayoutItemInfo &info = mLeftGrid->itemInfo(r, c); if (info.item) { QRect rect; if (info.separate) { rect.setLeft(left); rect.setTop(geometry.top()); rect.setHeight(geometry.height()); if (info.expandable) rect.setWidth(info.geometry.width() * expFactor); else rect.setWidth(info.geometry.width()); } else { int height = bh + (0 < remain-- ? 1 : 0); if (!info.item->expandingDirections().testFlag(Qt::Orientation::Vertical)) height = qMin(info.geometry.height(), height); height = qMin(geometry.height(), height); rect.setHeight(height); rect.setWidth(qMin(info.geometry.width(), geometry.width())); if (height < bh) rect.moveCenter(QPoint(0, baseLines[c] + base_center)); else rect.moveTop(baseLines[c]); rect.moveLeft(left); } rw = qMax(rw, rect.width()); if (visual_h_reversed) rect.moveLeft(geometry.left() + geometry.right() - rect.x() - rect.width() + 1); setItemGeometry(info.item, rect, mAnimate); } } left += rw; } // Right aligned plugins. int right=geometry.right(); for (int r=mRightGrid->rowCount()-1; r>=0; --r) { int rw = 0; int remain = height_remain; for (int c=0; cusedColCount(); ++c) { const LayoutItemInfo &info = mRightGrid->itemInfo(r, c); if (info.item) { QRect rect; if (info.separate) { rect.setTop(geometry.top()); rect.setHeight(geometry.height()); if (info.expandable) rect.setWidth(info.geometry.width() * expFactor); else rect.setWidth(info.geometry.width()); rect.moveRight(right); } else { int height = bh + (0 < remain-- ? 1 : 0); if (!info.item->expandingDirections().testFlag(Qt::Orientation::Vertical)) height = qMin(info.geometry.height(), height); height = qMin(geometry.height(), height); rect.setHeight(height); rect.setWidth(qMin(info.geometry.width(), geometry.width())); if (height < bh) rect.moveCenter(QPoint(0, baseLines[c] + base_center)); else rect.moveTop(baseLines[c]); rect.moveRight(right); } rw = qMax(rw, rect.width()); if (visual_h_reversed) rect.moveLeft(geometry.left() + geometry.right() - rect.x() - rect.width() + 1); setItemGeometry(info.item, rect, mAnimate); } } right -= rw; } } /************************************************ ************************************************/ void UKUIPanelLayout::setGeometryVert(const QRect &geometry) { const bool visual_h_reversed = parentWidget() && parentWidget()->isRightToLeft(); // Calc expFactor for expandable plugins like TaskBar. double expFactor; { int expHeight = mLeftGrid->expandableSize() + mRightGrid->expandableSize(); int nonExpHeight = mLeftGrid->sizeHint().height() - mLeftGrid->expandableSize() + mRightGrid->sizeHint().height() - mRightGrid->expandableSize(); expFactor = expHeight ? ((1.0 * geometry.height() - nonExpHeight) / expHeight) : 1; } // Calc baselines for plugins like button. QVector baseLines(qMax(mLeftGrid->colCount(), mRightGrid->colCount())); const int bw = geometry.width() / baseLines.count(); const int base_center = bw >> 1; const int width_remain = 0 < bw ? geometry.width() % baseLines.size() : 0; { int base = geometry.left(); for (auto i = baseLines.begin(), i_e = baseLines.end(); i_e != i; ++i, base += bw) { *i = base; } } #if 0 qDebug() << "** UKUIPanelLayout::setGeometryVert **************"; qDebug() << "geometry: " << geometry; qDebug() << "Left grid"; qDebug() << " cols:" << mLeftGrid->colCount() << " rows:" << mLeftGrid->rowCount(); qDebug() << " usedCols" << mLeftGrid->usedColCount(); qDebug() << "Right grid"; qDebug() << " cols:" << mRightGrid->colCount() << " rows:" << mRightGrid->rowCount(); qDebug() << " usedCols" << mRightGrid->usedColCount(); #endif // Top aligned plugins. int top=geometry.top(); for (int r=0; rrowCount(); ++r) { int rh = 0; int remain = width_remain; for (int c=0; cusedColCount(); ++c) { const LayoutItemInfo &info = mLeftGrid->itemInfo(r, c); if (info.item) { QRect rect; if (info.separate) { rect.moveTop(top); rect.setLeft(geometry.left()); rect.setWidth(geometry.width()); if (info.expandable) rect.setHeight(info.geometry.height() * expFactor); else rect.setHeight(info.geometry.height()); } else { rect.setHeight(qMin(info.geometry.height(), geometry.height())); int width = bw + (0 < remain-- ? 1 : 0); if (!info.item->expandingDirections().testFlag(Qt::Orientation::Horizontal)) width = qMin(info.geometry.width(), width); width = qMin(geometry.width(), width); rect.setWidth(width); if (width < bw) rect.moveCenter(QPoint(baseLines[c] + base_center, 0)); else rect.moveLeft(baseLines[c]); rect.moveTop(top); } rh = qMax(rh, rect.height()); if (visual_h_reversed) rect.moveLeft(geometry.left() + geometry.right() - rect.x() - rect.width() + 1); setItemGeometry(info.item, rect, mAnimate); } } top += rh; } // Bottom aligned plugins. int bottom=geometry.bottom(); for (int r=mRightGrid->rowCount()-1; r>=0; --r) { int rh = 0; int remain = width_remain; for (int c=0; cusedColCount(); ++c) { const LayoutItemInfo &info = mRightGrid->itemInfo(r, c); if (info.item) { QRect rect; if (info.separate) { rect.setLeft(geometry.left()); rect.setWidth(geometry.width()); if (info.expandable) rect.setHeight(info.geometry.height() * expFactor); else rect.setHeight(info.geometry.height()); rect.moveBottom(bottom); } else { rect.setHeight(qMin(info.geometry.height(), geometry.height())); int width = bw + (0 < remain-- ? 1 : 0); if (!info.item->expandingDirections().testFlag(Qt::Orientation::Horizontal)) width = qMin(info.geometry.width(), width); width = qMin(geometry.width(), width); rect.setWidth(width); if (width < bw) rect.moveCenter(QPoint(baseLines[c] + base_center, 0)); else rect.moveLeft(baseLines[c]); rect.moveBottom(bottom); } rh = qMax(rh, rect.height()); if (visual_h_reversed) rect.moveLeft(geometry.left() + geometry.right() - rect.x() - rect.width() + 1); setItemGeometry(info.item, rect, mAnimate); } } bottom -= rh; } } /************************************************ ************************************************/ void UKUIPanelLayout::invalidate() { mLeftGrid->invalidate(); mRightGrid->invalidate(); mMinPluginSize = QSize(); QLayout::invalidate(); } /************************************************ ************************************************/ int UKUIPanelLayout::lineCount() const { return mLeftGrid->colCount(); } /************************************************ ************************************************/ void UKUIPanelLayout::setLineCount(int value) { mLeftGrid->setColCount(value); mRightGrid->setColCount(value); invalidate(); } /************************************************ ************************************************/ void UKUIPanelLayout::rebuild() { mLeftGrid->rebuild(); mRightGrid->rebuild(); } /************************************************ ************************************************/ int UKUIPanelLayout::lineSize() const { return mLeftGrid->lineSize(); } /************************************************ ************************************************/ void UKUIPanelLayout::setLineSize(int value) { mLeftGrid->setLineSize(value); mRightGrid->setLineSize(value); invalidate(); } /************************************************ ************************************************/ void UKUIPanelLayout::setPosition(IUKUIPanel::Position value) { mPosition = value; mLeftGrid->setHoriz(isHorizontal()); mRightGrid->setHoriz(isHorizontal()); } /************************************************ ************************************************/ bool UKUIPanelLayout::isHorizontal() const { return mPosition == IUKUIPanel::PositionTop || mPosition == IUKUIPanel::PositionBottom; } /************************************************ ************************************************/ bool UKUIPanelLayout::itemIsSeparate(QLayoutItem *item) { if (!item) return true; Plugin *p = qobject_cast(item->widget()); if (!p) return true; return p->isSeparate(); } /************************************************ ************************************************/ void UKUIPanelLayout::startMovePlugin() { Plugin *plugin = qobject_cast(sender()); if (plugin) { // We have not memoryleaks there. // The processor will be automatically deleted when stopped. PluginMoveProcessor *moveProcessor = new PluginMoveProcessor(this, plugin); moveProcessor->start(); connect(moveProcessor, SIGNAL(finished()), this, SLOT(finishMovePlugin())); } } /************************************************ ************************************************/ void UKUIPanelLayout::finishMovePlugin() { PluginMoveProcessor *moveProcessor = qobject_cast(sender()); if (moveProcessor) { Plugin *plugin = moveProcessor->plugin(); int n = indexOf(plugin); plugin->setAlignment(ncount() ? Plugin::AlignLeft : Plugin::AlignRight); emit pluginMoved(plugin); } } /************************************************ ************************************************/ void UKUIPanelLayout::moveUpPlugin(Plugin * plugin) { const int i = indexOf(plugin); if (0 < i) moveItem(i, i - 1, true); } /************************************************ ************************************************/ void UKUIPanelLayout::addPlugin(Plugin * plugin) { connect(plugin, &Plugin::startMove, this, &UKUIPanelLayout::startMovePlugin); const int prev_count = count(); addWidget(plugin); //check actual position const int pos = indexOf(plugin); if (prev_count > pos) moveItem(pos, prev_count, false); } ukui-panel/panel/panelpluginsmodel.h0000644000175000017500000003172213632320722016547 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef PANELPLUGINSMODEL_H #define PANELPLUGINSMODEL_H #include #include namespace UKUi { class PluginInfo; struct PluginData; } class UKUIPanel; class Plugin; /*! * \brief The PanelPluginsModel class implements the Model part of the * Qt Model/View architecture for the Plugins, i.e. it is the interface * to access the Plugin data associated with this Panel. The * PanelPluginsModel takes care for read-access as well as changes * like adding, removing or moving Plugins. */ class PanelPluginsModel : public QAbstractListModel { Q_OBJECT public: PanelPluginsModel(UKUIPanel * panel, QString const & namesKey, QStringList const & desktopDirs, QObject * parent = nullptr); ~PanelPluginsModel(); /*! * \brief rowCount returns the number of Plugins. It overrides/implements * QAbstractListModel::rowCount(). * \param parent The parameter parent should be omitted to get the number of * Plugins. If it is given and a valid model index, the method returns 0 * because PanelPluginsModel is not a hierarchical model. */ virtual int rowCount(const QModelIndex & parent = QModelIndex()) const override; /*! * \brief data returns the Plugin data as defined by the Model/View * architecture. The Plugins itself can be accessed with the role * Qt::UserRole but they can also be accessed by the methods plugins(), * pluginByName() and pluginByID(). This method overrides/implements * QAbstractListModel::data(). * \param index should be a valid model index to determine the Plugin * that should be read. * \param role The Qt::ItemDataRole to determine what kind of data should * be read, can be one of the following: * 1. Qt::DisplayRole to return a string that describes the Plugin. * 2. Qt::DecorationRole to return an icon for the Plugin. * 3. Qt::UserRole to return a Plugin*. * \return The data as determined by index and role. */ virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override; /*! * \brief flags returns the item flags for the given model index. For * all Plugins, this is the same: * Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemNeverHasChildren. */ virtual Qt::ItemFlags flags(const QModelIndex & index) const override; /*! * \brief pluginNames returns a list of names for all the Plugins in * this panel. The names are not the human-readable names but the names * that are used to identify the Plugins, e.g. in the config files. These * names can be used in the method pluginByName() to get a corresponding * Plugin. * * The plugin names are normally chosen to be equal to the * filename of the corresponding *.desktop-file. If multiple instances * of a single plugin-type are created, their names are created by * appending increasing numbers, e.g. 'mainmenu' and 'mainmenu2'. * * \sa findNewPluginSettingsGroup */ QStringList pluginNames() const; /*! * \brief plugins returns a list of Plugins in this panel. */ QList plugins() const; /*! * \brief pluginByName gets a Plugin by its name. * \param name is the name of the plugin as it is used in the * config files. A list of names can be retrieved with the * method pluginNames(). * \return the Plugin with the given name. * * \sa pluginNames */ Plugin *pluginByName(QString name) const; /*! * \brief pluginByID gets a Plugin by its ID. * \param id is the *.desktop-file-ID of the plugin which in turn is the * QFileInfo::completeBaseName() of the desktop-file, e.g. "mainmenu". * * As these IDs are chosen according to the corresponding * desktop-file, these IDs are not unique. If multiple * instances of a single plugin-type are created, they share * the same ID in this sense. Then, this method will return * the first plugin of the given type. * \return the first Plugin found with the given ID. */ Plugin const *pluginByID(QString id) const; /*! * \brief movePlugin moves a Plugin in the underlying data. * * This method is useful whenever a Plugin should be moved several * positions at once. If a Plugin should only be moved one position * up or down, consider using onMovePluginUp or onMovePluginDown. * * \param plugin Plugin that has been moved * \param nameAfter name of the Plugin that should be located after * the moved Plugin after the move operation, so this parameter * determines the new position of plugin. If an empty string is * given, plugin will be moved to the end of the list. * * \note This method is especially useful for drag and drop reordering. * Therefore, it will be called whenever the user moves a Plugin in * the panel ("Move Plugin" in the context menu of the panel). * * \sa onMovePluginUp, onMovePluginDown */ void movePlugin(Plugin * plugin, QString const & nameAfter); signals: /*! * \brief pluginAdded gets emitted whenever a new Plugin is added * to the panel. */ void pluginAdded(Plugin * plugin); /*! * \brief pluginRemoved gets emitted whenever a Plugin is removed. * \param plugin The Plugin that was removed. This could be a nullptr. */ void pluginRemoved(Plugin * plugin); /*! * \brief pluginMoved gets emitted whenever a Plugin is moved. * * This signal gets emitted in movePlugin, onMovePluginUp and * onMovePluginDown. * * \param plugin The Plugin that was moved. This could be a nullptr. * * \sa pluginMovedUp */ void pluginMoved(Plugin * plugin); //plugin can be nullptr in case of move of not loaded plugin /*! * \brief pluginMovedUp gets emitted whenever a Plugin is moved a single * slot upwards. * * When a Plugin is moved a single slot upwards, this signal will be * emitted additionally to the pluginMoved signal so that two signals * get emitted. * * If a Plugin is moved downwards, that Plugin will swap places with * the following Plugin so that the result equals moving the following * Plugin a single slot upwards. So, whenever two adjacent Plugins * swap their places, this signal gets emitted with the Plugin that * moves upwards as parameter. * * For simplified use, only this signal is implemented. There is no * similar pluginMovedDown-signal. * * This signal gets emitted from onMovePluginUp and onMovePluginDown. * * \param plugin The Plugin that moved a slot upwards. * * \sa pluginMoved */ void pluginMovedUp(Plugin * plugin); public slots: /*! * \brief addPlugin Adds a new Plugin to the model. * * \param desktopFile The PluginInfo (which inherits XdgDesktopFile) * for the Plugin that should be added. * * \note AddPluginDialog::pluginSelected is connected to this slot. */ void addPlugin(const UKUi::PluginInfo &desktopFile); /*! * \brief removePlugin Removes a Plugin from the model. * * The Plugin to remove is identified by the QObject::sender() method * when the slot is called. Therefore, this method should only be called * by connecting a signal that a Plugin will emit to this slot. * Otherwise, nothing will happen. * * \note Plugin::remove is connected to this slot as soon as the * Plugin is loaded in the PanelPluginsModel. */ void removePlugin(); // slots for configuration dialog /*! * \brief onMovePluginUp Moves the Plugin corresponding to the given * model index a slot upwards. * * \note The 'Up' button in the configuration widget is connected to this * slot. */ void onMovePluginUp(QModelIndex const & index); /*! * \brief onMovePluginDown Moves the Plugin corresponding to the given * model index a slot downwards. * * \note The 'Down' button in the configuration widget is connected to this * slot. */ void onMovePluginDown(QModelIndex const & index); /*! * \brief onConfigurePlugin If the Plugin corresponding to the given * model index has a config dialog (checked via the flag * IUKUIPanelPlugin::HaveConfigDialog), this method shows * it by calling plugin->showConfigureDialog(). * * \note The 'Configure' button in the configuration widget is connected to * this slot. */ void onConfigurePlugin(QModelIndex const & index); /*! * \brief onRemovePlugin Removes the Plugin corresponding to the given * model index from the Model. * * \note The 'Remove' button in the configuration widget is connected to * this slot. */ void onRemovePlugin(QModelIndex const & index); private: /*! * \brief pluginslist_t is the data type used for mPlugins which stores * all the Plugins. * * \sa mPlugins */ typedef QList > > pluginslist_t; private: /*! * \brief loadPlugins Loads all the Plugins. * \param desktopDirs These directories are scanned for corresponding * .desktop-files which are necessary to load the plugins. */ void loadPlugins(QStringList const & desktopDirs); /*! * \brief loadPlugin Loads a Plugin and connects signals and slots. * \param desktopFile The desktop file that specifies how to load the * Plugin. * \param settingsGroup QString which specifies the settings group. This * will only be redirected to the Plugin so that it knows how to read * its settings. * \return A QPointer to the Plugin that was loaded. */ QPointer loadPlugin(UKUi::PluginInfo const & desktopFile, QString const & settingsGroup); /*! * \brief findNewPluginSettingsGroup Creates a name for a new Plugin * that is not yet present in the settings file. Whenever multiple * instances of a single Plugin type are created, they have to be * distinguished by this name. * * The first Plugin of a given type will be named like the type, e.g. * "mainmenu". If a name is already present, this method tries to * find a free name by appending increasing integers (starting with 2), * e.g. "mainmenu2". If, for example, only "mainmenu2" exists because * "mainmenu" was deleted, "mainmenu" would be returned. So, the method * always finds the first suitable name that is not yet present in the * settings file. * \param pluginType Type of the Plugin. * \return The created name for the Plugin. */ QString findNewPluginSettingsGroup(const QString &pluginType) const; /*! * \brief isIndexValid Checks if a given model index is valid for the * underlying data (column 0, row lower than number of Plugins and * so on). */ bool isIndexValid(QModelIndex const & index) const; /*! * \brief removePlugin Removes a given Plugin from the model. */ void removePlugin(pluginslist_t::iterator plugin); /*! * \brief mNamesKey The key to the settings-entry that stores the * names of the Plugins in a panel. Set upon creation, passed as * a parameter by the panel. */ const QString mNamesKey; /*! * \brief mPlugins Stores all the Plugins. * * mPlugins is a QList of elements while each element corresponds to a * single Plugin. Each element is a QPair of a QString and a QPointer * while the QPointer points to a Plugin. * * To access the elements, you can use indexing or an iterator on the * list. For each element p, p.first is the name of the Plugin as it * is used in the configuration files, p.second.data() is the Plugin. * * \sa pluginslist_t */ pluginslist_t mPlugins; /*! * \brief mPanel Stores a reference to the UKUIPanel. */ UKUIPanel * mPanel; }; Q_DECLARE_METATYPE(Plugin const *) #endif // PANELPLUGINSMODEL_H ukui-panel/panel/popupmenu.h0000644000175000017500000000301713632320722015051 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef POPUPMENU_H #define POPUPMENU_H #include #include "ukuipanelglobals.h" class UKUI_PANEL_API PopupMenu: public QMenu { public: explicit PopupMenu(QWidget *parent = 0): QMenu(parent) {} explicit PopupMenu(const QString &title, QWidget *parent = 0): QMenu(title, parent) {} QAction* addTitle(const QIcon &icon, const QString &text); QAction* addTitle(const QString &text); bool eventFilter(QObject *object, QEvent *event); protected: virtual void keyPressEvent(QKeyEvent* e); }; #endif // POPUPMENU_H ukui-panel/panel/CMakeLists.txt0000644000175000017500000001440713642614010015412 0ustar fengfengset(PROJECT ukui-panel) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) add_subdirectory(common) set(PRIV_HEADERS panelpluginsmodel.h windownotifier.h ukuipanel.h ukuipanelapplication.h ukuipanelapplication_p.h ukuipanellayout.h plugin.h pluginsettings_p.h ukuipanellimits.h popupmenu.h pluginmoveprocessor.h ukuipanelpluginconfigdialog.h config/configpaneldialog.h config/configpanelwidget.h config/configpluginswidget.h config/addplugindialog.h ) # using UKUi namespace in the public headers. set(PUB_HEADERS ukuipanelglobals.h pluginsettings.h iukuipanelplugin.h iukuipanel.h comm_func.h common/ukuihtmldelegate.h common/ukuisettings.h common/ukuiplugininfo.h #common/ukuipowermanager.h #common/ukuiscreensaver.h common/ukuiapplication.h common/ukuisingleapplication.h common/ukuitranslator.h common/ukuiprogramfinder.h common/configdialog/ukuiconfigdialog.h common/configdialog/ukuiconfigdialogcmdlineoptions.h common/configdialog/ukuipageselectwidget.h #common/ukuipower/ukuipower.h common/ukuinotification.h common/ukuiautostartentry.h common/ukuigridlayout.h common/ukuirotatedwidget.h common/ukuiglobals.h #common/ukuibacklight.h ukuicontrolstyle.h ) set(SOURCES main.cpp panelpluginsmodel.cpp windownotifier.cpp ukuipanel.cpp ukuipanelapplication.cpp ukuipanellayout.cpp plugin.cpp pluginsettings.cpp popupmenu.cpp pluginmoveprocessor.cpp ukuipanelpluginconfigdialog.cpp config/configpaneldialog.cpp config/configpanelwidget.cpp config/configpluginswidget.cpp config/addplugindialog.cpp comm_func.cpp common/ukuihtmldelegate.cpp common/ukuiplugininfo.cpp #common/ukuipowermanager.cpp common/ukuisettings.cpp #common/ukuiscreensaver.cpp common/ukuiapplication.cpp common/ukuisingleapplication.cpp common/ukuitranslator.cpp common/ukuiprogramfinder.cpp common/configdialog/ukuiconfigdialog.cpp common/configdialog/ukuiconfigdialogcmdlineoptions.cpp common/configdialog/ukuipageselectwidget.cpp #common/ukuipower/ukuipower.cpp #common/ukuipower/ukuipowerproviders.cpp common/ukuiautostartentry.cpp common/ukuinotification.cpp common/ukuigridlayout.cpp common/ukuirotatedwidget.cpp #common/ukuibacklight.cpp #common/ukuibacklight/virtual_backend.cpp #common/ukuibacklight/linux_backend/linuxbackend.cpp ukuicontrolstyle.cpp ) set(UI config/configpanelwidget.ui config/configpluginswidget.ui config/addplugindialog.ui common/configdialog/ukuiconfigdialog.ui ) #set(LIBRARIES # ukui #) file(GLOB CONFIG_FILES resources/*.conf resources/*.qss) ############################################ add_definitions(-DCOMPILE_UKUI_PANEL) set(PLUGIN_DESKTOPS_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/ukui/${PROJECT}") add_definitions(-DPLUGIN_DESKTOPS_DIR=\"${PLUGIN_DESKTOPS_DIR}\") if (WITH_SCREENSAVER_FALLBACK) message(STATUS "Building with conversion of deprecated 'screensaver' plugin") add_definitions(-DWITH_SCREENSAVER_FALLBACK "-DUKUI_LOCK_DESKTOP=\"${CMAKE_INSTALL_FULL_DATAROOTDIR}/applications/ukui-lockscreen.desktop\"") endif () project(${PROJECT}) set(QTX_LIBRARIES Qt5::Widgets Qt5::Xml Qt5::DBus) #Translations #ukui_translate_ts(QM_FILES SOURCES # UPDATE_TRANSLATIONS # ${UPDATE_TRANSLATIONS} # SOURCES # ${PUB_HEADERS} # ${PRIV_HEADERS} # ${SOURCES} # ${UI} # INSTALL_DIR # "${UKUI_TRANSLATIONS_DIR}/${PROJECT_NAME}" #) ukui_app_translation_loader(SOURCES ${PROJECT_NAME}) QT5_ADD_DBUS_INTERFACE(DBUS_INTERFACE_SRCS common/dbus/org.freedesktop.Notifications.xml notifications_interface ) QT5_ADD_DBUS_ADAPTOR(DBUS_ADAPTOR_SRCS common/dbus/org.ukui.SingleApplication.xml common/ukuisingleapplication.h UKUi::SingleApplication ) set_property(SOURCE ${DBUS_INTERFACE_SRCS} ${DBUS_ADAPTOR_SRCS} PROPERTY SKIP_AUTOGEN ON) list(APPEND SOURCES "${DBUS_INTERFACE_SRCS}" "${DBUS_ADAPTOR_SRCS}") add_executable(${PROJECT} ${PUB_HEADERS} ${PRIV_HEADERS} ${QM_FILES} ${SOURCES} ${UI} ) find_package(PkgConfig) pkg_check_modules(GLIB2 REQUIRED glib-2.0) pkg_check_modules(GIO2 REQUIRED gio-2.0) pkg_check_modules(Gsetting REQUIRED gsettings-qt) include_directories(${GLIB2_INCLUDE_DIRS}) include_directories(${GIO2_INCLUDE_DIRS}) include_directories(${Gsetting_INCLUDE_DIRS}) #ADD_DEFINITIONS(-DQT_NO_KEYWORDS) target_link_libraries(${PROJECT} ${LIBRARIES} ${QTX_LIBRARIES} KF5::WindowSystem ${STATIC_PLUGINS} Qt5Xdg ${GLIB2_LIBRARIES} ${GIO2_LIBRARIES} ${Gsetting_LIBRARIES} ) target_compile_definitions(${PROJECT} PRIVATE "UKUI_RELATIVE_SHARE_DIR=\"${UKUI_RELATIVE_SHARE_DIR}\"" #"UKUI_SHARE_DIR=\"${UKUI_SHARE_DIR}\"" "UKUI_RELATIVE_SHARE_TRANSLATIONS_DIR=\"${UKUI_RELATIVE_TRANSLATIONS_DIR}\"" "UKUI_SHARE_TRANSLATIONS_DIR=\"${UKUI_TRANSLATIONS_DIR}\"" "UKUI_GRAPHICS_DIR=\"${UKUI_GRAPHICS_DIR}\"" #"UKUI_ETC_XDG_DIR=\"${UKUI_ETC_XDG_DIR}\"" "UKUI_DATA_DIR=\"${UKUI_DATA_DIR}\"" "UKUI_INSTALL_PREFIX=\"${CMAKE_INSTALL_PREFIX}\"" #"UKUI_VERSION=\"${UKUI_VERSION}\"" #"COMPILE_LIBUKUI" #"QT_USE_QSTRINGBUILDER" #"QT_NO_CAST_FROM_ASCII" #"QT_NO_CAST_TO_ASCII" #"QT_NO_URL_CAST_FROM_STRING" #"QT_NO_CAST_FROM_BYTEARRAY" #"$<$:QT_NO_DEBUG_OUTPUT>" #"$<$:QT_NO_WARNING_OUTPUT>" ) install(TARGETS ${PROJECT} RUNTIME DESTINATION bin) install(FILES ${CONFIG_FILES} DESTINATION ${CMAKE_INSTALL_DATADIR}/ukui) install(FILES ${PUB_HEADERS} DESTINATION include/ukui) install(FILES ../man/ukui-panel.1 DESTINATION "${CMAKE_INSTALL_MANDIR}/man1" COMPONENT Runtime ) install(FILES resources/ukui-panel.desktop DESTINATION "/etc/xdg/autostart/" COMPONENT Runtime ) install(DIRECTORY ./img/ DESTINATION "${PACKAGE_DATA_DIR}/panel/img" ) install(FILES resources/ukui-panel_zh_CN.qm resources/ukui-panel_zh_CN.ts DESTINATION "${PACKAGE_DATA_DIR}/panel/resources" COMPONENT Runtime ) install(FILES resources/org.ukui.panel.settings.gschema.xml DESTINATION "/usr/share/glib-2.0/schemas" COMPONENT Runtime ) ukui-panel/panel/customstyle.h0000644000175000017500000001744613633355350015435 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include /*! * \brief The CustomStyle class * \details * 自定义QStyle * 基于QProxyStyle,默认使用QProxyStyle的实例绘制控件,你需要针对某一个控件重新实现若干对应的接口。 * QProxyStyle可以从现有的qt style实例化,我们只需要知道这个style的名字即可。 * 这种做法带来了不错的扩展性和自由度,因为我们不需要将某个style的代码直接引入我们的项目中, * 也能够“继承”这个style类进行二次开发。 * * 下面的方法展现了QStyle的所有的接口,使用QStyle进行控件的绘制使得qt应用能够进行风格的切换, * 从而达到不修改项目源码却对应用外观产生巨大影响的效果。 * * \note * 需要注意QStyle与QSS并不兼容,因为QSS本身其实上也是QStyle的一种实现,对一个控件而言,本身理论上只能 * 在同一时间调用唯一一个QStyle进行绘制。 */ class CustomStyle : public QProxyStyle { Q_OBJECT public: explicit CustomStyle(const QString &proxyStyleName = "windows", QObject *parent = nullptr); ~CustomStyle(); /*! * \brief drawComplexControl * \param control 比如ScrollBar,对应CC枚举类型 * \param option * \param painter * \param widget * \details * drawComplexControl用于绘制具有子控件的复杂控件,它本身一般不直接绘制控件, * 而是通过QStyle的其它方法将复杂控件分解成子控件再调用其它的draw方法绘制。 * 如果你需要重新实现一个复杂控件的绘制方法,首先考虑的应该是在不改变它原有的绘制流程的情况下, * 对它调用到的其它方法进行重写。 * * 如果你不想使用原有的绘制流程,那你需要重写这个接口,然后自己实现一切, * 包括背景的绘制,子控件的位置和状态计算,子控件的绘制等。 * 所以,你需要对这个控件有足够的了解之后再尝试直接重写这个接口。 */ virtual void drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = nullptr) const; /*! * \brief drawControl * \param element 比如按钮,对应CE枚举类型 * \param option * \param painter * \param widget * \details * drawControl用于绘制基本控件元素,它本身一般只负责绘制控件的一部分或者一层。 * 如果你想要知道控件具体如何绘制,你需要同时研究这个控件的源码和QStyle中的源码, * 因为它们都有可能改变控件的绘制流程。 * * QStyle一般会遵循QCommonStyle的绘制流程,QCommenStyle是大部分主流style的最基类, * 它本身不能完全称之为一个主题,如果你直接使用它,你的控件将不能被正常绘制,因为它有可能只是 * 在特定的时候执行了特定却未实现的绘制方法,它更像一个框架或者规范。 */ virtual void drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const; virtual void drawItemPixmap(QPainter *painter, const QRect &rectangle, int alignment, const QPixmap &pixmap) const; virtual void drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, bool enabled, const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const; /*! * \brief drawPrimitive * \param element 背景绘制,对应PE枚举类型 * \param option * \param painter * \param widget * \details * drawPrimitive用于绘制控件背景,比如按钮和菜单的背景, * 我们一般需要判断控件的状态来绘制不同的背景, * 比如按钮的hover和点击效果。 */ virtual void drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const; virtual QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const; virtual QStyle::SubControl hitTestComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, const QPoint &position, const QWidget *widget = nullptr) const; virtual QRect itemPixmapRect(const QRect &rectangle, int alignment, const QPixmap &pixmap) const; virtual QRect itemTextRect(const QFontMetrics &metrics, const QRect &rectangle, int alignment, bool enabled, const QString &text) const; //virtual int layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation, const QStyleOption *option, const QWidget *widget); virtual int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option = nullptr, const QWidget *widget = nullptr) const; /*! * \brief polish * \param widget * \details * polish用于对widget进行预处理,一般我们可以在polish中修改其属性, * 另外,polish是对动画和特效实现而言十分重要的一个方法, * 通过polish我们能够使widget和特效和动画形成对应关系。 */ virtual void polish(QWidget *widget); virtual void polish(QApplication *application); virtual void polish(QPalette &palette); virtual void unpolish(QWidget *widget); virtual void unpolish(QApplication *application); virtual QSize sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget = nullptr) const; virtual QIcon standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const; virtual QPalette standardPalette() const; /*! * \brief styleHint * \param hint 对应的枚举是SH * \param option * \param widget * \param returnData * \return * \details * styleHint比较特殊,通过它我们能够改变一些控件的绘制流程或者方式,比如说QMenu是否可以滚动。 */ virtual int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr, const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const; /*! * \brief subControlRect * \param control * \param option * \param subControl * \param widget * \return * \details * subControlRect返回子控件的位置和大小信息,这个方法一般在内置流程中调用, * 如果我们要重写某个绘制方法,可能需要用到它 */ virtual QRect subControlRect(QStyle::ComplexControl control, const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget = nullptr) const; /*! * \brief subElementRect * \param element * \param option * \param widget * \return * \details * 与subControlRect类似 */ virtual QRect subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget = nullptr) const; signals: public slots: }; #endif // CUSTOMSTYLE_H ukui-panel/panel/ukuipanelglobals.h0000644000175000017500000000232513633355350016371 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2013 LXQt team * Authors: * Hong Jen Yee (PCMan) * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef __UKUI_PANEL_GLOBALS_H__ #define __UKUI_PANEL_GLOBALS_H__ #include #ifdef COMPILE_UKUI_PANEL #define UKUI_PANEL_API Q_DECL_EXPORT #else #define UKUI_PANEL_API Q_DECL_IMPORT #endif #endif // __UKUI_PANEL_GLOBALS_H__ ukui-panel/panel/comm_func.cpp0000644000175000017500000004655013632320722015333 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "comm_func.h" #ifndef _GNU_SOURCE #define _GNU_SOURCE //for strcasestr #endif #include #include #include #include #include #include #include #include #include #include // for opendir(), readdir(), closedir() #include // for stat() #include #include #include #include #include #include #define BUF_LEN 128 #define BUFF_SIZE (512) bool getRunCmdOutput(const char *command, char *output, int max_size) { FILE *stream; if ((stream = popen(command, "r" )) == NULL) return false; if (fread(output, sizeof(char), max_size, stream) <= 0) { pclose(stream); return false; } pclose(stream); return true; } void startChildApp(const char *app_exe,char *argv_exec[]) { /* exec command */ pid_t child_pid; child_pid = fork(); if (child_pid < 0) { perror("fork"); } else if (child_pid == 0) { /* child process */ pid_t grandchild_pid; grandchild_pid = fork(); if (grandchild_pid < 0) { perror("fork"); _exit(1); } else if (grandchild_pid == 0) { /* grandchild process */ execvp(app_exe, argv_exec); perror("execvp"); _exit(1); } else { _exit(0); } } else { waitpid(child_pid,NULL,0); } } //QString->char * void save_q_string_2_m_string(QString q_string, char **m_buf) { int len; std::string tmp_str; char *m_buf_tmp; tmp_str = q_string.toStdString(); len = tmp_str.length() + 1; if ((m_buf_tmp = (char *)malloc(len)) == NULL) return; memset(m_buf_tmp, 0, len); memcpy(m_buf_tmp, tmp_str.c_str(), len); if (*m_buf) free(*m_buf); *m_buf = m_buf_tmp; } //QString 转wchar_t* const wchar_t* qstring2wchar_t(QString str) { //create variable to hold converted QString wchar_t *someVar=new wchar_t[str.size()+1]; //copy QString to allocated variable str.toWCharArray(someVar); //set last caharacter to null terminator someVar[str.size()]=L'\0'; //create another variable wchar_t *anotherVar=new wchar_t[str.size()+1]; //copy above allocated variable to this one wcscpy(anotherVar, someVar); return anotherVar; } QString wchar2string(const wchar_t* wchar_str) { return QString::fromWCharArray(wchar_str); } //.时间戳转格式化 QString time_2_string(time_t t) { QString tmp; struct tm *p; p=gmtime(&t); char s[100]={0}; strftime(s, sizeof(s), "%Y-%m-%d ", p); // printf("%d: %s\n", (int)t, s); tmp = s; return tmp; } //格式化转时间戳 long int string_2_time(char *str_time) { struct tm stm; int iY, iM, iD, iH, iMin, iS; memset(&stm,0,sizeof(stm)); iY = atoi(str_time); iM = atoi(str_time+5); iD = atoi(str_time+8); iH = atoi(str_time+11); iMin = atoi(str_time+14); iS = atoi(str_time+17); stm.tm_year=iY-1900; stm.tm_mon=iM-1; stm.tm_mday=iD; stm.tm_hour=iH; stm.tm_min=iMin; stm.tm_sec=iS; /*printf("%d-%0d-%0d %0d:%0d:%0d\n", iY, iM, iD, iH, iMin, iS);*/ return mktime(&stm); } bool getReadFileContent(const char *file_path, char *output, int max_size) { FILE *stream; if ((stream = fopen(file_path, "r" )) == NULL) return false; if (fread(output, sizeof(char), max_size, stream) <= 0) { fclose(stream); return false; } fclose(stream); return true; } char* getOsVersion() { static char buf[BUF_LEN]={0}; char os_buf[BUF_LEN]={0}; char platform_buf[BUF_LEN]={0}; bool rst; char *cmd = "cat /etc/os-release | grep -i PRETTY_NAME | awk -F'=' '{print $2}'"; rst = getRunCmdOutput(cmd, os_buf, BUF_LEN); if(rst) { char *cmd_platform = "uname -i"; rst = getRunCmdOutput(cmd_platform, platform_buf, BUF_LEN); } if(rst) { int len = strlen(os_buf); os_buf[len-1] = '\0'; sprintf(buf, "%s_%s", os_buf,platform_buf); } buf[strlen(buf)-1] = '\0'; for(int i=0;i2){ for(int i=0;iexists(toDir); if(!dirExist) createDir->mkdir(toDir); QFile *createFile = new QFile; bool fileExist = createFile->exists(toDir+fileName); if (fileExist){ if(coverFileIfExist){ createFile->remove(toDir+fileName); } }//end if if(!QFile::copy(sourceDir+fileName, toDir+fileName)) { return false; } return true; } /** qCopyDirectory -- 拷贝目录 fromDir : 源目录 toDir : 目标目录 bCoverIfFileExists : ture:同名时覆盖 false:同名时返回false,终止拷贝 返回: ture拷贝成功 false:拷贝未完成 */ bool qCopyDirectory(const QDir& fromDir, const QDir& toDir, bool bCoverIfFileExists) { QDir formDir_ = fromDir; QDir toDir_ = toDir; if(!toDir_.exists()) { if(!toDir_.mkdir(toDir_.absolutePath())) { return false; } } QFileInfoList fileInfoList = formDir_.entryInfoList(); for(QFileInfo fileInfo:qAsConst(fileInfoList)) { if(fileInfo.fileName() == "." || fileInfo.fileName() == "..") continue; //拷贝子目录 if(fileInfo.isDir()) { //递归调用拷贝 if(!qCopyDirectory(QDir(fileInfo.filePath()), QDir(toDir_.filePath(fileInfo.fileName())),bCoverIfFileExists)) { return false; } } //拷贝子文件 else { if(bCoverIfFileExists && toDir_.exists(fileInfo.fileName())) { toDir_.remove(fileInfo.fileName()); } if(!QFile::copy(fileInfo.filePath(), toDir_.filePath(fileInfo.fileName()))) { return false; } } } return true; } //是不是数字 static int IsNumeric(const char* ccharptr_CharacterList) { for ( ; *ccharptr_CharacterList; ccharptr_CharacterList++) if (*ccharptr_CharacterList < '0' || *ccharptr_CharacterList > '9') return 0; // false return 1; // true } /*! * \brief getPidByName * \param the name of process * \return success: the pid of the process failed: -1(the process is not exist) -2(access /proc error) */ pid_t getPidByName(const char* processName) { QDir procDir("/proc/"); int pid = 0; bool findPid = false; QStringList dirLists = procDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); for(auto & dir : qAsConst(dirLists)) { bool ok; pid = dir.toInt(&ok, 10); if(ok == false) continue; QFile procFile("/proc/" + dir + "/status"); if(!procFile.open(QIODevice::ReadOnly | QIODevice::Text)) { fprintf(stderr, "read proc status failed\n"); continue; } QTextStream in(&procFile); bool findName = false; QString line = in.readLine(); while(!line.isNull()) { QStringList strs = line.split('\t'); if(!findName && strs.size() > 1 && strs.at(0) == "Name:"){ if(strs.at(1) != QString(processName)) break; else findName = true; } if(strs.size() > 1 && strs.at(0) == "State:") { if(strs.at(1).split(' ').at(0)!="Z") findPid = true; else break; } line = in.readLine(); } procFile.close(); if(findPid) break; } fprintf(stderr, "%s:%d\n", processName, pid); return pid; } /// \brief get_total_mem 获取总的内存大小 /// /// \return int get_total_mem() { const char *file = "/proc/meminfo"; char line_buff[128] = {0}; FILE *fp = NULL; char p_name[32] = {0}; unsigned int total_mem; if((fp = fopen(file, "r")) == NULL) return -1; fgets(line_buff, sizeof(line_buff), fp); sscanf(line_buff, "%s %u", p_name, &total_mem); //printf("%s: %u\n", p_name, total_mem); fclose(fp); return total_mem; } /// \brief get_process_mem 获取进程占用的内存 /// /// \param pid 进程ID /// /// \return 进程占用的内存 int get_process_mem(pid_t pid) { char file[64] = {0}; FILE *fp = NULL; char p_name[32] = {0}; char line_buff[128] = {0}; unsigned int process_mem; sprintf(file, "/proc/%d/status", (unsigned int)pid); if((fp = fopen(file, "r")) == NULL) return -1; for(int i = 0; i< 20; i++) fgets(line_buff, sizeof(line_buff), fp); fgets(line_buff, sizeof(line_buff), fp); sscanf(line_buff, "%s %u", p_name, &process_mem); //printf("%s: %u\n", p_name, process_mem); fclose(fp); return process_mem; } /// \brief get_total_cpu_accurancy 获取总的CPU使用量 /// /// \return int get_total_cpu_accurancy() { const char* file = "/proc/stat"; FILE *fp = NULL; char line_buff[512] = {0}; char str[32] = {0}; char *pch = NULL; int num[10] = {0}; int sum = 0, i = 0; if((fp = fopen(file, "r")) == NULL) return -1; fgets(line_buff, sizeof(line_buff), fp); pch = strtok(line_buff, " "); while(pch != NULL) { sprintf(str, "%s", pch); if(IsNumeric(str)) num[i++] = atoi(str); pch = strtok(NULL, " "); } for(i = 0; i<9; i++) sum += num[i]; //printf("%d\n", sum); fclose(fp); return sum; } /// \brief get_process_cpu_accurancy 获取进程的CPU使用量 /// /// \param pid 进程ID /// /// \return int get_process_cpu_accurancy(pid_t pid) { char file[64] = {0}; FILE *fp = NULL; char buff[512] = {0}; char str[32] = {0}; char *pch = NULL; int i = 0, sum = 0; int num[4] = {0}; sprintf(file, "/proc/%d/stat", pid); if((fp = fopen(file, "r")) == NULL) return -1; fgets(buff, sizeof(buff), fp); pch = strtok(buff, " "); while(pch != NULL) { i++; if(i>=14 && i<=17) { sprintf(str, "%s", pch); num[i-14] = atoi(str); } pch = strtok(NULL, " "); } for(i = 0; i<4; i++) { printf("%d,", num[i]); sum += num[i]; } printf("\n"); //printf("%d\n", sum); fclose(fp); return sum; } /// \brief get_cpu_num 获取逻辑CPU个数 /// /// \return int get_cpu_num() { const char *file = "/proc/cpuinfo"; FILE *fp = NULL; char line_buff[128] = {0}; int num = 0; if((fp = fopen(file, "r")) == NULL) return -1; while(fgets(line_buff, sizeof(line_buff), fp) != NULL) { if(strstr(line_buff, "processor") != NULL) { //sscanf(line_buff, "%s %s : %d", tmp, tmp, &cores_num); //return cores_num; num++; } } fclose(fp); return num; } /// \brief get_pmem 获取进程的内存占用率 /// /// \param pid 进程ID /// /// \return 成功,返回内存占用率;失败,返回-1 float get_pmem(pid_t pid) { int p_mem = get_process_mem(pid); int t_mem = get_total_mem(); if(p_mem < 0 || t_mem < 0) return -1; return 100.0 * p_mem / t_mem; } /// \brief get_pcpu 获取进程CPU占用率 /// /// \param pid 进程ID /// /// \return 成功,返回CPU占用率;失败,返回-1 float get_pcpu(pid_t pid) { int process_cpu1, process_cpu2; int total_cpu1, total_cpu2; int cpu_num = get_cpu_num(); if(cpu_num < 0) return -1; process_cpu1 = get_process_cpu_accurancy(pid); total_cpu1 = get_total_cpu_accurancy(); if(process_cpu1 < 0 || total_cpu1 < 0) return -1; usleep(1000000); process_cpu2 = get_process_cpu_accurancy(pid); total_cpu2 = get_total_cpu_accurancy(); if(process_cpu2 < 0 || total_cpu2 < 0) return -1; return 100.0 * cpu_num * (process_cpu2 - process_cpu1) / (total_cpu2 - total_cpu1); } ukui-panel/panel/ukuipanellayout.h0000644000175000017500000000557013632320722016262 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPanelLAYOUT_H #define UKUIPanelLAYOUT_H #include #include #include #include #include "iukuipanel.h" #include "ukuipanelglobals.h" class MoveInfo; class QMouseEvent; class QEvent; class Plugin; class LayoutItemGrid; class UKUI_PANEL_API UKUIPanelLayout : public QLayout { Q_OBJECT public: explicit UKUIPanelLayout(QWidget *parent); ~UKUIPanelLayout(); void addItem(QLayoutItem *item); QLayoutItem *itemAt(int index) const; QLayoutItem *takeAt(int index); int count() const; void moveItem(int from, int to, bool withAnimation=false); QSize sizeHint() const; //QSize minimumSize() const; void setGeometry(const QRect &geometry); bool isHorizontal() const; void invalidate(); int lineCount() const; void setLineCount(int value); int lineSize() const; void setLineSize(int value); IUKUIPanel::Position position() const { return mPosition; } void setPosition(IUKUIPanel::Position value); /*! \brief Force the layout to re-read items/plugins "static" configuration */ void rebuild(); static bool itemIsSeparate(QLayoutItem *item); signals: void pluginMoved(Plugin * plugin); public slots: void startMovePlugin(); void finishMovePlugin(); void moveUpPlugin(Plugin * plugin); void addPlugin(Plugin * plugin); private: mutable QSize mMinPluginSize; LayoutItemGrid *mLeftGrid; LayoutItemGrid *mRightGrid; IUKUIPanel::Position mPosition; bool mAnimate; void setGeometryHoriz(const QRect &geometry); void setGeometryVert(const QRect &geometry); void globalIndexToLocal(int index, LayoutItemGrid **grid, int *gridIndex); void globalIndexToLocal(int index, LayoutItemGrid **grid, int *gridIndex) const; void setItemGeometry(QLayoutItem *item, const QRect &geometry, bool withAnimation); }; #endif // UKUIPanelLAYOUT_H ukui-panel/panel/main.cpp0000644000175000017500000000451313640356061014306 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuipanelapplication.h" #include #include #include #include #include #include /*! The ukui-panel is the panel of UKUI. Usage: ukui-panel [CONFIG_ID] CONFIG_ID Section name in config file ~/.config/ukui/panel.conf (default main) */ int main(int argc, char *argv[]) { UKUIPanelApplication app(argc, argv); app.setAttribute(Qt::AA_UseHighDpiPixmaps, true); //Singleton QStringList homePath = QStandardPaths::standardLocations(QStandardPaths::HomeLocation); QString lockPath = homePath.at(0) + "/.config/ukui-panel"; int fd = open(lockPath.toUtf8().data(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (fd < 0) { exit(1); } if (lockf(fd, F_TLOCK, 0)) { syslog(LOG_ERR, "Can't lock single file, ukui-panel is already running!"); qDebug()<<"Can't lock single file, ukui-panel is already running!"; exit(0); } //tanslate QString locale = QLocale::system().name(); QTranslator translator; if (locale == "zh_CN"){ if (translator.load("ukui-panel_zh_CN.qm", "/usr/share/ukui-panel/panel/resources/")) app.installTranslator(&translator); else qDebug() << "Load translations file" << locale << "failed!"; } return app.exec(); } ukui-panel/panel/ukuipanelapplication.h0000644000175000017500000001536113632320722017247 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPanelAPPLICATION_H #define UKUIPanelAPPLICATION_H //#include #include "common/ukuiapplication.h" #include "iukuipanelplugin.h" class QScreen; class UKUIPanel; class UKUIPanelApplicationPrivate; /*! * \brief The UKUIPanelApplication class inherits from UKUi::Application and * is therefore the QApplication that we will create and execute in our * main()-function. * * UKUIPanelApplication itself is not a visible panel, rather it is only * the container which holds the visible panels. These visible panels are * UKUIPanel objects which are stored in mPanels. This approach enables us * to have more than one panel (for example one panel at the top and one * panel at the bottom of the screen) without additional effort. */ class UKUIPanelApplication : public UKUi::Application { Q_OBJECT public: /*! * \brief Creates a new UKUIPanelApplication with the given command line * arguments. Performs the following steps: * 1. Initializes the UKUi::Application, sets application name and version. * 2. Handles command line arguments. Currently, the only cmdline argument * is -c = -config = -configfile which chooses a different config file * for the UKUi::Settings. * 3. Creates the UKUi::Settings. * 4. Connects QCoreApplication::aboutToQuit to cleanup(). * 5. Calls addPanel() for each panel found in the config file. If there is * none, adds a new panel. * \param argc * \param argv */ explicit UKUIPanelApplication(int& argc, char** argv); ~UKUIPanelApplication(); void setIconTheme(const QString &iconTheme); void updateStylesheet(QString themeName); /*! * \brief Determines the number of UKUIPanel objects * \return the current number of UKUIPanel objects */ int count() const { return mPanels.count(); } /*! * \brief Checks if a given Plugin is running and has the * IUKUIPanelPlugin::SingleInstance flag set. As Plugins are added to * UKUIPanel instances, this method only iterates over these UKUIPanel * instances and lets them check the conditions. * \param pluginId Plugin Identifier which is the basename of the .desktop * file that specifies the plugin. * \return true if the Plugin is running and has the * IUKUIPanelPlugin::SingleInstance flag set, false otherwise. */ bool isPluginSingletonAndRunnig(QString const & pluginId) const; public slots: /*! * \brief Adds a new UKUIPanel which consists of the following steps: * 1. Create id/name. * 2. Create the UKUIPanel: call addPanel(name). * 3. Update the config file (add the new panel id to the list of panels). * 4. Show the panel configuration dialog so that the user can add plugins. * * This method will create a new UKUIPanel with a new name and add this * to the config file. So this should only be used while the application * is running and the user decides to add a new panel. At application * startup, addPanel() should be used instead. * * \note This slot will be used from the UKUIPanel right-click menu. As we * can only add new panels from a visible panel, we should never run * lxqt-panel without an UKUIPanel. Without a panel, we have just an * invisible application. */ void addNewPanel(); signals: /*! * \brief Signal that re-emits the signal pluginAdded() from UKUIPanel. */ void pluginAdded(); /*! * \brief Signal that re-emits the signal pluginRemoved() from UKUIPanel. */ void pluginRemoved(); private: /*! * \brief Holds all the instances of UKUIPanel. */ QList mPanels; /*! * \brief The global icon theme used by all apps (except for panels perhaps). */ QString mGlobalIconTheme; /*! * \brief Creates a new UKUIPanel with the given name and connects the * appropriate signals and slots. * This method can be used at application startup. * \param name Name of the UKUIPanel as it is used in the config file. * \return The newly created UKUIPanel. */ UKUIPanel* addPanel(const QString &name); private slots: /*! * \brief Removes the given UKUIPanel which consists of the following * steps: * 1. Remove the panel from mPanels. * 2. Remove the panel from the config file. * 3. Schedule the QObject for deletion: QObject::deleteLater(). * \param panel UKUIPanel instance that should be removed. */ void removePanel(UKUIPanel* panel); /*! * \brief Connects the QScreen::destroyed signal of a new screen to * the screenDestroyed() slot so that we can handle this screens' * destruction as soon as it happens. * \param newScreen The QScreen that was created and added. */ void handleScreenAdded(QScreen* newScreen); /*! * \brief Handles screen destruction. This is a workaround for a Qt bug. * For further information, see the implementation notes. * \param screenObj The QScreen that was destroyed. */ void screenDestroyed(QObject* screenObj); /*! * \brief Reloads the panels. This is the second part of the workaround * mentioned above. */ void reloadPanelsAsNeeded(); /*! * \brief Deletes all UKUIPanel instances that are stored in mPanels. */ void cleanup(); private: /*! * \brief mSettings is the UKUi::Settings object that is used for the * current instance of ukui-panel. Normally, this refers to the config file * $HOME/.config/ukui/panel.conf (on Unix systems). This behaviour can be * changed with the -c command line option. */ UKUIPanelApplicationPrivate *const d_ptr; Q_DECLARE_PRIVATE(UKUIPanelApplication) Q_DISABLE_COPY(UKUIPanelApplication) }; #endif // UKUIPanelAPPLICATION_H ukui-panel/panel/ukuicontrolstyle.cpp0000644000175000017500000000413713642614010017014 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include UKUiMenu::UKUiMenu(){ } UKUiMenu::~UKUiMenu(){ } void UKUiMenu::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); p.setBrush(QBrush(Qt::red)); p.setPen(Qt::black); p.drawRoundedRect(opt.rect,6,6); // p.drawText(rect(), opt. Qt::AlignCenter,); style()->drawPrimitive(QStyle::PE_PanelMenu, &opt, &p, this); } UkuiToolButton::UkuiToolButton(){} UkuiToolButton::~UkuiToolButton(){} void UkuiToolButton::paintTooltipStyle() { //设置QToolTip颜色 QPalette palette = QToolTip::palette(); palette.setColor(QPalette::Inactive,QPalette::ToolTipBase,Qt::black); //设置ToolTip背景色 palette.setColor(QPalette::Inactive,QPalette::ToolTipText, Qt::white); //设置ToolTip字体色 QToolTip::setPalette(palette); // QFont font("Segoe UI", -1, 50); // font.setPixelSize(12); // QToolTip::setFont(font); //设置ToolTip字体 } UKUiFrame::UKUiFrame(){ } UKUiFrame::~UKUiFrame(){ } void UKUiFrame::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); p.setBrush(QBrush(QColor(0x13,0x14,0x14,0xb2))); p.setPen(Qt::NoPen); p.setRenderHint(QPainter::Antialiasing); p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, this); } ukui-panel/panel/plugin.cpp0000644000175000017500000004347713633070712014672 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "plugin.h" #include "iukuipanelplugin.h" #include "pluginsettings_p.h" #include "ukuipanel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include "common/ukuisettings.h" //#include #include "../panel/common/ukuitranslator.h" #include // statically linked built-in plugins #if defined(WITH_DESKTOPSWITCH_PLUGIN) #include "../plugin-desktopswitch/desktopswitch.h" // desktopswitch extern void * loadPluginTranslation_desktopswitch_helper; #endif #if defined(WITH_MAINMENU_PLUGIN) #include "../plugin-mainmenu/ukuimainmenu.h" // mainmenu extern void * loadPluginTranslation_mainmenu_helper; #endif #if defined(WITH_QUICKLAUNCH_PLUGIN) #include "../plugin-quicklaunch/ukuiquicklaunchplugin.h" // quicklaunch extern void * loadPluginTranslation_quicklaunch_helper; #endif #if defined(WITH_SHOWDESKTOP_PLUGIN) #include "../plugin-showdesktop/showdesktop.h" // showdesktop extern void * loadPluginTranslation_showdesktop_helper; #endif #if defined(WITH_SPACERX_PLUGIN) #include "../plugin-spacerx/spacerx.h" // spacerx extern void * loadPluginTranslation_spacerx_helper; #endif #if defined(WITH_SPACER_PLUGIN) #include "../plugin-spacer/spacer.h" // spacer extern void * loadPluginTranslation_spacer_helper; #endif #if defined(WITH_STATUSNOTIFIER_PLUGIN) #include "../plugin-statusnotifier/statusnotifier.h" // statusnotifier extern void * loadPluginTranslation_statusnotifier_helper; #endif #if defined(WITH_TASKBAR_PLUGIN) #include "../plugin-taskbar/ukuitaskbarplugin.h" // taskbar extern void * loadPluginTranslation_taskbar_helper; #endif #if defined(WITH_TRAY_PLUGIN) #include "../plugin-tray/ukuitrayplugin.h" // tray extern void * loadPluginTranslation_tray_helper; #endif #if defined(WITH_WORLDCLOCK_PLUGIN) #include "../plugin-worldclock/ukuiworldclock.h" // worldclock extern void * loadPluginTranslation_worldclock_helper; #endif #if defined(WITH_CALENDAR_PLUGIN) #include "../plugin-calendar/ukuicalendar.h" // indicatorCalendar extern void * loadPluginTranslation_calendar_helper; #endif #if defined(WITH_STARTMENU_PLUGIN) #include "../plugin-startmenu/startmenu.h" // startmenu extern void * loadPluginTranslation_startmenu_helper; #endif #if defined(WITH_SEGMENTATION_PLUGIN) #include "../plugin-segmentation/segmentation.h" // startmenu extern void * loadPluginTranslation_segmentation_helper; #endif #if defined(WITH_NIGHTMODE_PLUGIN) #include "../plugin-nightmode/nightmode.h" // startmenu extern void * loadPluginTranslation_nightmode_helper; #endif QColor Plugin::mMoveMarkerColor= QColor(255, 0, 0, 255); /************************************************ ************************************************/ Plugin::Plugin(const UKUi::PluginInfo &desktopFile, UKUi::Settings *settings, const QString &settingsGroup,UKUIPanel *panel) : QFrame(panel), mDesktopFile(desktopFile), mPluginLoader(0), mPlugin(0), mPluginWidget(0), mAlignment(AlignLeft), mPanel(panel) { mSettings = PluginSettingsFactory::create(settings, settingsGroup); setWindowTitle(desktopFile.name()); mName = desktopFile.name(); QStringList dirs; dirs << QProcessEnvironment::systemEnvironment().value("UKUIPanel_PLUGIN_PATH").split(":"); dirs << PLUGIN_DIR; bool found = false; if(IUKUIPanelPluginLibrary const * pluginLib = findStaticPlugin(desktopFile.id())) { // this is a static plugin found = true; loadLib(pluginLib); } else { // this plugin is a dynamically loadable module QString baseName = QString("lib%1.so").arg(desktopFile.id()); for(const QString &dirName : qAsConst(dirs)) { QFileInfo fi(QDir(dirName), baseName); if (fi.exists()) { found = true; if (loadModule(fi.absoluteFilePath())) break; } } } if (!isLoaded()) { if (!found) qWarning() << QString("Plugin %1 not found in the").arg(desktopFile.id()) << dirs; return; } setObjectName(mPlugin->themeId() + "Plugin"); // plugin handle for easy context menu setProperty("NeedsHandle", mPlugin->flags().testFlag(IUKUIPanelPlugin::NeedsHandle)); QString s = mSettings->value("alignment").toString(); // Retrun default value if (s.isEmpty()) { mAlignment = (mPlugin->flags().testFlag(IUKUIPanelPlugin::PreferRightAlignment)) ? Plugin::AlignRight : Plugin::AlignLeft; } else { mAlignment = (s.toUpper() == "RIGHT") ? Plugin::AlignRight : Plugin::AlignLeft; } if (mPluginWidget) { QGridLayout* layout = new QGridLayout(this); layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); setLayout(layout); layout->addWidget(mPluginWidget, 0, 0); } saveSettings(); // delay the connection to settingsChanged to avoid conflicts // while the plugin is still being initialized connect(mSettings, &PluginSettings::settingsChanged, this, &Plugin::settingsChanged); } /************************************************ ************************************************/ Plugin::~Plugin() { delete mPlugin; delete mPluginLoader; delete mSettings; } void Plugin::setAlignment(Plugin::Alignment alignment) { mAlignment = alignment; saveSettings(); } /************************************************ ************************************************/ namespace { //helper types for static plugins storage & binary search typedef std::unique_ptr plugin_ptr_t; typedef std::tuple plugin_tuple_t; //NOTE: Please keep the plugins sorted by name while adding new plugins. //NOTE2: we need to reference some (dummy) symbol from (autogenerated) UKUiPluginTranslationLoader.cpp // to be not stripped (as unused/unreferenced) in static linking time static plugin_tuple_t const static_plugins[] = { #if defined(WITH_CALENDAR_PLUGIN) std::make_tuple(QLatin1String("calendar"), plugin_ptr_t{new IndicatorCalendarPluginLibrary}, loadPluginTranslation_calendar_helper),// desktopswitch #endif #if defined(WITH_DESKTOPSWITCH_PLUGIN) std::make_tuple(QLatin1String("desktopswitch"), plugin_ptr_t{new DesktopSwitchPluginLibrary}, loadPluginTranslation_desktopswitch_helper),// desktopswitch #endif #if defined(WITH_MAINMENU_PLUGIN) std::make_tuple(QLatin1String("mainmenu"), plugin_ptr_t{new UKUiMainMenuPluginLibrary}, loadPluginTranslation_mainmenu_helper),// mainmenu #endif #if defined(WITH_QUICKLAUNCH_PLUGIN) std::make_tuple(QLatin1String("quicklaunch"), plugin_ptr_t{new UKUIQuickLaunchPluginLibrary}, loadPluginTranslation_quicklaunch_helper),// quicklaunch #endif #if defined(WITH_SHOWDESKTOP_PLUGIN) std::make_tuple(QLatin1String("showdesktop"), plugin_ptr_t{new ShowDesktopLibrary}, loadPluginTranslation_showdesktop_helper),// showdesktop #endif #if defined(WITH_SPACERX_PLUGIN) std::make_tuple(QLatin1String("spacerx"), plugin_ptr_t{new SpacerXPluginLibrary}, loadPluginTranslation_spacerx_helper),// spacerx #endif #if defined(WITH_SPACER_PLUGIN) std::make_tuple(QLatin1String("spacer"), plugin_ptr_t{new SpacerPluginLibrary}, loadPluginTranslation_spacer_helper),// spacer #endif #if defined(WITH_STATUSNOTIFIER_PLUGIN) std::make_tuple(QLatin1String("statusnotifier"), plugin_ptr_t{new StatusNotifierLibrary}, loadPluginTranslation_statusnotifier_helper),// statusnotifier #endif #if defined(WITH_TASKBAR_PLUGIN) std::make_tuple(QLatin1String("taskbar"), plugin_ptr_t{new UKUITaskBarPluginLibrary}, loadPluginTranslation_taskbar_helper),// taskbar #endif #if defined(WITH_TRAY_PLUGIN) std::make_tuple(QLatin1String("tray"), plugin_ptr_t{new UKUITrayPluginLibrary}, loadPluginTranslation_tray_helper),// tray #endif #if defined(WITH_WORLDCLOCK_PLUGIN) std::make_tuple(QLatin1String("worldclock"), plugin_ptr_t{new UKUiWorldClockLibrary}, loadPluginTranslation_worldclock_helper),// worldclock #endif #if defined(WITH_CALENDAR_PLUGIN) std::make_tuple(QLatin1String("calendar"), plugin_ptr_t{new UKUICalendarPluginLibrary}, loadPluginTranslation_calendar_helper),// calendar #endif #if defined(WITH_STARTMENU_PLUGIN) std::make_tuple(QLatin1String("startmenu"), plugin_ptr_t{new UKUIStartMenuLibrary}, loadPluginTranslation_startmenu_helper),// startmenu #endif #if defined(WITH_SEGMENTATION_PLUGIN) std::make_tuple(QLatin1String("segmentation"), plugin_ptr_t{new StartMenuLibrary}, loadPluginTranslation_segementation_helper),// startmenu #endif #if defined(WITH_NIGHTMODE_PLUGIN) std::make_tuple(QLatin1String("nightmode"), plugin_ptr_t{new NightModeLibrary}, loadPluginTranslation_nightmode_helper),// nightmode #endif }; static constexpr plugin_tuple_t const * const plugins_begin = static_plugins; static constexpr plugin_tuple_t const * const plugins_end = static_plugins + sizeof (static_plugins) / sizeof (static_plugins[0]); struct assert_helper { assert_helper() { Q_ASSERT(std::is_sorted(plugins_begin, plugins_end , [] (plugin_tuple_t const & p1, plugin_tuple_t const & p2) -> bool { return std::get<0>(p1) < std::get<0>(p2); })); } }; static assert_helper h; } IUKUIPanelPluginLibrary const * Plugin::findStaticPlugin(const QString &libraryName) { // find a static plugin library by name -> binary search plugin_tuple_t const * plugin = std::lower_bound(plugins_begin, plugins_end, libraryName , [] (plugin_tuple_t const & plugin, QString const & name) -> bool { return std::get<0>(plugin) < name; }); if (plugins_end != plugin && libraryName == std::get<0>(*plugin)) return std::get<1>(*plugin).get(); return nullptr; } // load a plugin from a library bool Plugin::loadLib(IUKUIPanelPluginLibrary const * pluginLib) { IUKUIPanelPluginStartupInfo startupInfo; startupInfo.settings = mSettings; startupInfo.desktopFile = &mDesktopFile; startupInfo.ukuiPanel = mPanel; mPlugin = pluginLib->instance(startupInfo); if (!mPlugin) { qWarning() << QString("Can't load plugin \"%1\". Plugin can't build IUKUIPanelPlugin.").arg(mDesktopFile.id()); return false; } mPluginWidget = mPlugin->widget(); if (mPluginWidget) { mPluginWidget->setObjectName(mPlugin->themeId()); watchWidgets(mPluginWidget); } this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); return true; } // load dynamic plugin from a *.so module bool Plugin::loadModule(const QString &libraryName) { mPluginLoader = new QPluginLoader(libraryName); if (!mPluginLoader->load()) { qWarning() << mPluginLoader->errorString(); return false; } QObject *obj = mPluginLoader->instance(); if (!obj) { qWarning() << mPluginLoader->errorString(); return false; } IUKUIPanelPluginLibrary* pluginLib= qobject_cast(obj); if (!pluginLib) { qWarning() << QString("Can't load plugin \"%1\". Plugin is not a IUKUIPanelPluginLibrary.").arg(mPluginLoader->fileName()); delete obj; return false; } return loadLib(pluginLib); } /************************************************ ************************************************/ void Plugin::watchWidgets(QObject * const widget) { // the QWidget might not be fully constructed yet, but we can rely on the isWidgetType() if (!widget->isWidgetType()) return; widget->installEventFilter(this); // watch also children (recursive) for (auto const & child : widget->children()) { watchWidgets(child); } } /************************************************ ************************************************/ void Plugin::unwatchWidgets(QObject * const widget) { widget->removeEventFilter(this); // unwatch also children (recursive) for (auto const & child : widget->children()) { unwatchWidgets(child); } } /************************************************ ************************************************/ void Plugin::settingsChanged() { mPlugin->settingsChanged(); } /************************************************ ************************************************/ void Plugin::saveSettings() { mSettings->setValue("alignment", (mAlignment == AlignLeft) ? "Left" : "Right"); mSettings->setValue("type", mDesktopFile.id()); mSettings->sync(); } /************************************************ ************************************************/ void Plugin::contextMenuEvent(QContextMenuEvent *event) { mPanel->showPopupMenu(this); } /************************************************ ************************************************/ void Plugin::mousePressEvent(QMouseEvent *event) { switch (event->button()) { case Qt::LeftButton: mPlugin->activated(IUKUIPanelPlugin::Trigger); break; case Qt::MidButton: mPlugin->activated(IUKUIPanelPlugin::MiddleClick); break; default: break; } } /************************************************ ************************************************/ void Plugin::mouseDoubleClickEvent(QMouseEvent*) { mPlugin->activated(IUKUIPanelPlugin::DoubleClick); } /************************************************ ************************************************/ void Plugin::showEvent(QShowEvent *) { if (mPluginWidget) mPluginWidget->adjustSize(); } /************************************************ ************************************************/ QMenu *Plugin::popupMenu() const { QString name = this->name().replace("&", "&&"); QMenu* menu = new QMenu(windowTitle()); /* //set top menu selection ,do not delete until you get the ui finish if (mPlugin->flags().testFlag(IUKUIPanelPlugin::HaveConfigDialog)) { QAction* configAction = new QAction( XdgIcon::fromTheme(QLatin1String("preferences-other")), tr("Configure \"%1\"").arg(name), menu); menu->addAction(configAction); connect(configAction, SIGNAL(triggered()), this, SLOT(showConfigureDialog())); } QAction* moveAction = new QAction(XdgIcon::fromTheme("transform-move"), tr("Move \"%1\"").arg(name), menu); menu->addAction(moveAction); connect(moveAction, SIGNAL(triggered()), this, SIGNAL(startMove())); menu->addSeparator(); QAction* removeAction = new QAction( XdgIcon::fromTheme(QLatin1String("list-remove")), tr("Remove \"%1\"").arg(name), menu); menu->addAction(removeAction); connect(removeAction, SIGNAL(triggered()), this, SLOT(requestRemove())); */ return menu; } /************************************************ ************************************************/ bool Plugin::isSeparate() const { return mPlugin->isSeparate(); } /************************************************ ************************************************/ bool Plugin::isExpandable() const { return mPlugin->isExpandable(); } /************************************************ ************************************************/ bool Plugin::eventFilter(QObject * watched, QEvent * event) { switch (event->type()) { case QEvent::DragLeave: emit dragLeft(); break; case QEvent::ChildAdded: watchWidgets(dynamic_cast(event)->child()); break; case QEvent::ChildRemoved: unwatchWidgets(dynamic_cast(event)->child()); break; default: break; } return false; } /************************************************ ************************************************/ void Plugin::realign() { if (mPlugin) mPlugin->realign(); } /************************************************ ************************************************/ void Plugin::showConfigureDialog() { if (!mConfigDialog) mConfigDialog = mPlugin->configureDialog(); if (!mConfigDialog) return; connect(this, &Plugin::destroyed, mConfigDialog.data(), &QWidget::close); mPanel->willShowWindow(mConfigDialog); mConfigDialog->show(); mConfigDialog->raise(); mConfigDialog->activateWindow(); WId wid = mConfigDialog->windowHandle()->winId(); KWindowSystem::activateWindow(wid); KWindowSystem::setOnDesktop(wid, KWindowSystem::currentDesktop()); } /************************************************ ************************************************/ void Plugin::requestRemove() { emit remove(); deleteLater(); } ukui-panel/panel/ukuipanellimits.h0000644000175000017500000000267713632320722016253 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Luís Pereira * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPANELLIMITS_H #define UKUIPANELLIMITS_H #define PANEL_DEFAULT_SIZE 32 #define PANEL_MINIMUM_SIZE 16 #define PANEL_MAXIMUM_SIZE 200 #define PANEL_HIDE_SIZE 4 #define PANEL_DEFAULT_ICON_SIZE 22 #define PANEL_DEFAULT_LINE_COUNT 1 #define PANEL_DEFAULT_BACKGROUND_COLOR "#CCCCCC" #define PANEL_HIDE_DELAY 500 #define PANEL_HIDE_FIRST_TIME (5000 - PANEL_HIDE_DELAY) #define PANEL_SHOW_DELAY 0 #define SETTINGS_SAVE_DELAY 3000 #endif // UKUIPANELLIMITS_H ukui-panel/panel/ukuipanelapplication.cpp0000644000175000017500000003040313632320722017574 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuipanelapplication.h" #include "ukuipanelapplication_p.h" #include "ukuipanel.h" #include "config/configpaneldialog.h" //#include #include "common/ukuisettings.h" #include #include #include #include #include #include #include "comm_func.h" UKUIPanelApplicationPrivate::UKUIPanelApplicationPrivate(UKUIPanelApplication *q) : mSettings(0), q_ptr(q) { } IUKUIPanel::Position UKUIPanelApplicationPrivate::computeNewPanelPosition(const UKUIPanel *p, const int screenNum) { //#define Q_D(Class) Class##Private * const d = d_func() //#define Q_Q(Class) Class * const q = q_func() Q_Q(UKUIPanelApplication); QVector screenPositions(4, false); // false means not occupied for (int i = 0; i < q->mPanels.size(); ++i) { if (p != q->mPanels.at(i)) { // We are not the newly added one if (screenNum == q->mPanels.at(i)->screenNum()) { // Panels on the same screen int p = static_cast (q->mPanels.at(i)->position()); screenPositions[p] = true; // occupied } } } int availablePosition = 0; for (int i = 0; i < 4; ++i) { // Bottom, Top, Left, Right if (!screenPositions[i]) { availablePosition = i; break; } } return static_cast (availablePosition); } UKUIPanelApplication::UKUIPanelApplication(int& argc, char** argv) : UKUi::Application(argc, argv, true), d_ptr(new UKUIPanelApplicationPrivate(this)) { Q_D(UKUIPanelApplication); QCoreApplication::setApplicationName(QLatin1String("ukui-panel")); const QString VERINFO = QStringLiteral(UKUI_PANEL_VERSION "\nlibukui " "" "\nQt " QT_VERSION_STR); QCoreApplication::setApplicationVersion(VERINFO); QCommandLineParser parser; parser.setApplicationDescription(QLatin1String("UKUi Panel")); parser.addHelpOption(); parser.addVersionOption(); QCommandLineOption configFileOption(QStringList() << QLatin1String("c") << QLatin1String("config") << QLatin1String("configfile"), QCoreApplication::translate("main", "Use alternate configuration file."), QCoreApplication::translate("main", "Configuration file")); parser.addOption(configFileOption); parser.process(*this); // QFile::remove(QString(qgetenv("HOME"))+"/.config/ukui/panel.conf"); const QString configFile = parser.value(configFileOption); qDebug()<<"configFile is : "<mSettings = new UKUi::Settings(QLatin1String("panel"), this); } else { qDebug()<<"configFile.is not Empty"<mSettings = new UKUi::Settings(configFile, QSettings::IniFormat, this); } // This is a workaround for Qt 5 bug #40681. const auto allScreens = screens(); for(QScreen* screen : allScreens) { connect(screen, &QScreen::destroyed, this, &UKUIPanelApplication::screenDestroyed); } connect(this, &QGuiApplication::screenAdded, this, &UKUIPanelApplication::handleScreenAdded); connect(this, &QCoreApplication::aboutToQuit, this, &UKUIPanelApplication::cleanup); QStringList panels = d->mSettings->value("panels").toStringList(); // WARNING: Giving a separate icon theme to the panel is wrong and has side effects. // However, it is optional and can be used as the last resort for avoiding a low // contrast in the case of symbolic SVG icons. (The correct way of doing that is // using a Qt widget style that can assign a separate theme/QPalette to the panel.) mGlobalIconTheme = QIcon::themeName(); const QString iconTheme = d->mSettings->value("iconTheme").toString(); if (!iconTheme.isEmpty()) QIcon::setThemeName(iconTheme); if (panels.isEmpty()) { panels << "panel1"; } for(const QString& i : qAsConst(panels)) { addPanel(i); } // updateStylesheet("default"); } void UKUIPanelApplication::updateStylesheet(QString themeName) { // QFile file(QString(PLUGIN_DESKTOPS_DIR)+"/../panel.qss"); // file.open(QFile::ReadOnly); // QTextStream filetext(&file); // QString stylesheet = filetext.readAll(); // this->setStyleSheet(stylesheet); // file.close(); // qDebug()<<"updateStylesheet:"<screenNum(); IUKUIPanel::Position newPanelPosition = d->computeNewPanelPosition(p, screenNum); p->setPosition(screenNum, newPanelPosition, true); QStringList panels = d->mSettings->value("panels").toStringList(); panels << name; d->mSettings->setValue("panels", panels); // Poupup the configuration dialog to allow user configuration right away p->showConfigDialog(); } UKUIPanel* UKUIPanelApplication::addPanel(const QString& name) { Q_D(UKUIPanelApplication); UKUIPanel *panel = new UKUIPanel(name, d->mSettings); mPanels << panel; // reemit signals connect(panel, &UKUIPanel::deletedByUser, this, &UKUIPanelApplication::removePanel); connect(panel, &UKUIPanel::pluginAdded, this, &UKUIPanelApplication::pluginAdded); connect(panel, &UKUIPanel::pluginRemoved, this, &UKUIPanelApplication::pluginRemoved); return panel; } void UKUIPanelApplication::handleScreenAdded(QScreen* newScreen) { // qDebug() << "UKUIPanelApplication::handleScreenAdded" << newScreen; connect(newScreen, &QScreen::destroyed, this, &UKUIPanelApplication::screenDestroyed); } void UKUIPanelApplication::reloadPanelsAsNeeded() { Q_D(UKUIPanelApplication); // NOTE by PCMan: This is a workaround for Qt 5 bug #40681. // Here we try to re-create the missing panels which are deleted in // UKUIPanelApplication::screenDestroyed(). // qDebug() << "UKUIPanelApplication::reloadPanelsAsNeeded()"; const QStringList names = d->mSettings->value("panels").toStringList(); for(const QString& name : names) { bool found = false; for(UKUIPanel* panel : qAsConst(mPanels)) { if(panel->name() == name) { found = true; break; } } if(!found) { // the panel is found in the config file but does not exist, create it. qDebug() << "Workaround Qt 5 bug #40681: re-create panel:" << name; addPanel(name); } } qApp->setQuitOnLastWindowClosed(true); } void UKUIPanelApplication::screenDestroyed(QObject* screenObj) { // NOTE by PCMan: This is a workaround for Qt 5 bug #40681. // With this very dirty workaround, we can fix ukui/ukui bug #204, #205, and #206. // Qt 5 has two new regression bugs which breaks ukui-panel in a multihead environment. // #40681: Regression bug: QWidget::winId() returns old value and QEvent::WinIdChange event is not emitted sometimes. (multihead setup) // #40791: Regression: QPlatformWindow, QWindow, and QWidget::winId() are out of sync. // Explanations for the workaround: // Internally, Qt mantains a list of QScreens and update it when XRandR configuration changes. // When the user turn off an monitor with xrandr --output --off, this will destroy the QScreen // object which represent the output. If the QScreen being destroyed contains our panel widget, // Qt will call QWindow::setScreen(0) on the internal windowHandle() of our panel widget to move it // to the primary screen. However, moving a window to a different screen is more than just changing // its position. With XRandR, all screens are actually part of the same virtual desktop. However, // this is not the case in other setups, such as Xinerama and moving a window to another screen is // not possible unless you destroy the widget and create it again for a new screen. // Therefore, Qt destroy the widget and re-create it when moving our panel to a new screen. // Unfortunately, destroying the window also destroy the child windows embedded into it, // using XEMBED such as the tray icons. (#206) // Second, when the window is re-created, the winId of the QWidget is changed, but Qt failed to // generate QEvent::WinIdChange event so we have no way to know that. We have to set // some X11 window properties using the native winId() to make it a dock, but this stop working // because we cannot get the correct winId(), so this causes #204 and #205. // // The workaround is very simple. Just completely destroy the panel before Qt has a chance to do // QWindow::setScreen() for it. Later, we reload the panel ourselves. So this can bypassing the Qt bugs. QScreen* screen = static_cast(screenObj); bool reloadNeeded = false; qApp->setQuitOnLastWindowClosed(false); for(UKUIPanel* panel : qAsConst(mPanels)) { QWindow* panelWindow = panel->windowHandle(); if(panelWindow && panelWindow->screen() == screen) { // the screen containing the panel is destroyed // delete and then re-create the panel ourselves QString name = panel->name(); panel->saveSettings(false); delete panel; // delete the panel, so Qt does not have a chance to set a new screen to it. mPanels.removeAll(panel); reloadNeeded = true; qDebug() << "Workaround Qt 5 bug #40681: delete panel:" << name; } } if(reloadNeeded) QTimer::singleShot(1000, this, SLOT(reloadPanelsAsNeeded())); else qApp->setQuitOnLastWindowClosed(true); } void UKUIPanelApplication::removePanel(UKUIPanel* panel) { Q_D(UKUIPanelApplication); Q_ASSERT(mPanels.contains(panel)); mPanels.removeAll(panel); QStringList panels = d->mSettings->value("panels").toStringList(); panels.removeAll(panel->name()); d->mSettings->setValue("panels", panels); panel->deleteLater(); } bool UKUIPanelApplication::isPluginSingletonAndRunnig(QString const & pluginId) const { for (auto const & panel : mPanels) if (panel->isPluginSingletonAndRunnig(pluginId)) return true; return false; } // See UKUIPanelApplication::UKUIPanelApplication for why this isn't good. void UKUIPanelApplication::setIconTheme(const QString &iconTheme) { Q_D(UKUIPanelApplication); d->mSettings->setValue("iconTheme", iconTheme == mGlobalIconTheme ? QString() : iconTheme); QString newTheme = iconTheme.isEmpty() ? mGlobalIconTheme : iconTheme; if (newTheme != QIcon::themeName()) { QIcon::setThemeName(newTheme); for(UKUIPanel* panel : qAsConst(mPanels)) { panel->update(); panel->updateConfigDialog(); } } } ukui-panel/panel/common/0000755000175000017500000000000013633355350014145 5ustar fengfengukui-panel/panel/common/ukuiautostartentry.h0000644000175000017500000000765513632320722020333 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright (C) 2012 Alec Moskvin * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIAUTOSTARTENTRY_H #define UKUIAUTOSTARTENTRY_H #include "ukuiglobals.h" #include namespace UKUi { /*! \brief The AutostartEntry class provides an interface for staging configuration of individual autostart items. All changes are made in memory until commit() is called. - "system" file refers to a read-only file in /etc/xdg/autostart (or a directory in $XDG_CONFIG_DIRS) - "local" file refers to the file in user's ~/.config/autostart (or in $XDG_CONFIG_HOME/autostart) When a "local" file has the same name as the "system" file, the local one overrides it. This class tries to ensure that the "local" file is deleted if it's identical to the "system" file. */ class UKUI_API AutostartEntry { public: /*! Constructs an AutostartEntry object for a specific entry. * \param name The name of the autostart desktop file (e.g. "ukui-panel.desktop") */ AutostartEntry(const QString& name); //! \brief Default constructor AutostartEntry(); //! Destructor virtual ~AutostartEntry() { } //! Returns the "active" desktop file const XdgDesktopFile& file() const; //! Returns the name of the autostart entry (e.g. "ukui-panel.desktop") QString name() const; /*! Sets to the specified desktop file. Use this to make modifications. * \param file The desktop file */ void setFile(const XdgDesktopFile& file); /*! Sets whether the item auto-starts * \param enable When false, sets the "Hidden" key which will prevent the item from starting */ void setEnabled(bool enable); //! Returns true if the item will auto-start bool isEnabled() const; /*! Returns true if the entry does not exist, and the object carries no useful information * and can be ignored/deleted. */ bool isEmpty() const { return !mSystem && mLocalState == StateNone; } /*! Write any changes to disk * \return true on success */ bool commit(); protected: //! Returns true if the user's "local" version exists bool isLocal() const { return mLocalState != StateNone && mLocalState != StateDeleted; } /*! Removes the user's "local" version of the file, reverting to system defaults * \return true if there is no "system" version left (i.e. the entry was entirely deleted) */ bool removeLocal(); //! \brief a read-only file in /etc/xdg/autostart (or a directory in $XDG_CONFIG_DIRS) XdgDesktopFile mSystemFile; //! \brief the file in user's ~/.config/autostart (or in $XDG_CONFIG_HOME/autostart) XdgDesktopFile mLocalFile; //! State of the "local" file enum ItemState { StateNone, //! does not exist at all StateDeleted, //! needs to be deleted from disk StateTransient, //! does not yet exist on disk StateModified, //! exists on disk and is modified StateExists //! exists on disk and unmodified } mLocalState; bool mSystem; //! true if the "system" file exists }; } // namespace UKUi #endif // UKUIAUTOSTARTENTRY_H ukui-panel/panel/common/ukuiprogramfinder.h0000644000175000017500000000353313632320722020051 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright (C) 2013 Alec Moskvin * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPROGRAMFINDER_H #define UKUIPROGRAMFINDER_H #include #include "ukuiglobals.h" namespace UKUi { namespace ProgramFinder { /*! * \brief programExists Checks if the program needed to execute the given * command is installed * \param command * \return True if the program exists */ UKUI_API bool programExists(const QString& command); /*! * \brief findPrograms Filters a list of commands (with arguments) based on * which programs are installed * \param commands Commands to check * \return List of commands which are installed */ UKUI_API QStringList findPrograms(const QStringList& commands); /*! * \brief programName Returns the program name given a command * \param command * \return */ UKUI_API QString programName(const QString& command); } } // namespace UKUi #endif // UKUIPROGRAMFINDER_H ukui-panel/panel/common/ukuiapplication.cpp0000644000175000017500000001425013632320722020046 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012-2013 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include #include "ukuiapplication.h" #include "ukuisettings.h" #include using namespace UKUi; #define COLOR_DEBUG "\033[32;2m" #define COLOR_WARN "\033[33;2m" #define COLOR_CRITICAL "\033[31;1m" #define COLOR_FATAL "\033[33;1m" #define COLOR_RESET "\033[0m" #define QAPP_NAME qApp ? qApp->objectName().toUtf8().constData() : "" #include #include #include #include #include #include #include #include #include /*! \brief Log qDebug input to file Used only in pure Debug builds or when is the system environment variable UKUI_DEBUG set */ void dbgMessageOutput(QtMsgType type, const QMessageLogContext &ctx, const QString & msgStr) { Q_UNUSED(ctx) QByteArray msgBuf = msgStr.toUtf8(); const char* msg = msgBuf.constData(); QDir dir(XdgDirs::configHome() + QLatin1String("/ukui")); dir.mkpath(QL1S(".")); const char* typestr; const char* color; switch (type) { case QtDebugMsg: typestr = "Debug"; color = COLOR_DEBUG; break; case QtWarningMsg: typestr = "Warning"; color = COLOR_WARN; break; case QtFatalMsg: typestr = "Fatal"; color = COLOR_FATAL; break; default: // QtCriticalMsg typestr = "Critical"; color = COLOR_CRITICAL; } QByteArray dt = QDateTime::currentDateTime().toString(QL1S("yyyy-MM-dd hh:mm:ss.zzz")).toUtf8(); if (isatty(STDERR_FILENO)) fprintf(stderr, "%s %s(%p) %s: %s%s\n", color, QAPP_NAME, static_cast(qApp), typestr, msg, COLOR_RESET); else fprintf(stderr, "%s(%p) %s: %s\n", QAPP_NAME, static_cast(qApp), typestr, msg); FILE *f = fopen(dir.absoluteFilePath(QL1S("debug.log")).toUtf8().constData(), "a+"); fprintf(f, "%s %s(%p) %s: %s\n", dt.constData(), QAPP_NAME, static_cast(qApp), typestr, msg); fclose(f); if (type == QtFatalMsg) abort(); } Application::Application(int &argc, char** argv) : QApplication(argc, argv) { #ifdef DEBUG qInstallMessageHandler(dbgMessageOutput); #else if (!qEnvironmentVariableIsSet("UKUI_DEBUG")) qInstallMessageHandler(dbgMessageOutput); #endif setWindowIcon(QIcon(QFile::decodeName(UKUI_GRAPHICS_DIR) + QL1S("/ukui_logo.png"))); connect(Settings::globalSettings(), &GlobalSettings::ukuiThemeChanged, this, &Application::updateTheme); updateTheme(); } Application::Application(int &argc, char** argv, bool handleQuitSignals) : Application(argc, argv) { if (handleQuitSignals) { QList signo_list = {SIGINT, SIGTERM, SIGHUP}; connect(this, &Application::unixSignal, [this, signo_list] (int signo) { if (signo_list.contains(signo)) quit(); }); listenToUnixSignals(signo_list); } } void Application::updateTheme() { const QString styleSheetKey = QFileInfo(applicationFilePath()).fileName(); setStyleSheet(ukuiTheme.qss(styleSheetKey)); emit themeChanged(); } namespace { class SignalHandler { public: static void signalHandler(int signo) { const int ret = write(instance->mSignalSock[0], &signo, sizeof (int)); if (sizeof (int) != ret) qCritical("unable to write into socketpair: %s", strerror(errno)); } public: template SignalHandler(Application * app, Lambda signalEmitter) : mSignalSock{-1, -1} { if (0 != socketpair(AF_UNIX, SOCK_STREAM, 0, mSignalSock)) { qCritical("unable to create socketpair for correct signal handling: %s", strerror(errno)); return; } mNotifier.reset(new QSocketNotifier(mSignalSock[1], QSocketNotifier::Read)); QObject::connect(mNotifier.data(), &QSocketNotifier::activated, app, [this, signalEmitter] { int signo = 0; int ret = read(mSignalSock[1], &signo, sizeof (int)); if (sizeof (int) != ret) qCritical("unable to read signal from socketpair, %s", strerror(errno)); signalEmitter(signo); }); } ~SignalHandler() { close(mSignalSock[0]); close(mSignalSock[1]); } void listenToSignals(QList const & signoList) { struct sigaction sa; sa.sa_handler = signalHandler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; for (auto const & signo : signoList) sigaction(signo, &sa, nullptr); } public: static QScopedPointer instance; private: int mSignalSock[2]; QScopedPointer mNotifier; }; QScopedPointer SignalHandler::instance; } void Application::listenToUnixSignals(QList const & signoList) { static QScopedPointer signal_notifier; if (SignalHandler::instance.isNull()) SignalHandler::instance.reset(new SignalHandler{this, [this] (int signo) { emit unixSignal(signo); }}); SignalHandler::instance->listenToSignals(signoList); } ukui-panel/panel/common/ukuisingleapplication.cpp0000644000175000017500000000711113633355350021254 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2014 LXQt team * Authors: * Luís Pereira * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuisingleapplication.h" #include "singleapplicationadaptor.h" #include #include #include #include #include #include using namespace UKUi; SingleApplication::SingleApplication(int &argc, char **argv, StartOptions options) : Application(argc, argv), mActivationWindow(0) { QString service = QString::fromLatin1("org.ukui.%1").arg(QApplication::applicationName()); QDBusConnection bus = QDBusConnection::sessionBus(); if (!bus.isConnected()) { QLatin1String errorMessage("Can't connect to the D-Bus session bus\n" "Make sure the D-Bus daemon is running"); /* ExitOnDBusFailure is the default. Any value other than NoExitOnDBusFailure will be taken as ExitOnDBusFailure (the default). */ if (options == NoExitOnDBusFailure) { qDebug() << Q_FUNC_INFO << errorMessage; return; } else { qCritical() << Q_FUNC_INFO << errorMessage; QTimer::singleShot(0, [this] { exit(1); }); } } bool registered = (bus.registerService(service) == QDBusConnectionInterface::ServiceRegistered); if (registered) { // We are the primary instance SingleApplicationAdaptor *mAdaptor = new SingleApplicationAdaptor(this); QLatin1String objectPath("/"); bus.registerObject(objectPath, mAdaptor, QDBusConnection::ExportAllSlots); } else { // We are the second outstance QDBusMessage msg = QDBusMessage::createMethodCall(service, QStringLiteral("/"), QStringLiteral("org.ukui.SingleApplication"), QStringLiteral("activateWindow")); QDBusConnection::sessionBus().send(msg); QTimer::singleShot(0, [this] { exit(0); }); } } SingleApplication::~SingleApplication() { } void SingleApplication::setActivationWindow(QWidget *w) { mActivationWindow = w; } QWidget *SingleApplication::activationWindow() const { return mActivationWindow; } void SingleApplication::activateWindow() { if (mActivationWindow) { mActivationWindow->show(); WId window = mActivationWindow->effectiveWinId(); KWindowInfo info(window, NET::WMDesktop); int windowDesktop = info.desktop(); if (windowDesktop != KWindowSystem::currentDesktop()) KWindowSystem::setCurrentDesktop(windowDesktop); KWindowSystem::activateWindow(window); } else { qDebug() << Q_FUNC_INFO << "activationWindow not set or null"; } } ukui-panel/panel/common/ukuipowermanager.h0000644000175000017500000000343513632320722017702 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * * Copyright: 2019-2020 UKUI team * Authors: * minglequn * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPOWERMANAGER_H #define UKUIPOWERMANAGER_H #include #include #include "ukuiglobals.h" namespace UKUi { class Power; /*! QAction centric menu aware wrapper around ukuipower */ class UKUI_API PowerManager : public QObject { Q_OBJECT public: PowerManager(QObject * parent, bool skipWarning = false); ~PowerManager(); QList availableActions(); public slots: // power management void suspend(); void hibernate(); void reboot(); void shutdown(); // ukui session void logout(); public: bool skipWarning() const { return m_skipWarning; } private: UKUi::Power * m_power; bool m_skipWarning; private slots: void hibernateFailed(); void suspendFailed(); }; } // namespace UKUi #endif // UKUIPOWERMANAGER_H ukui-panel/panel/common/ukuitranslator.h0000644000175000017500000000470413633355350017412 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2013 LXQt team * Authors: * Alexander Sokoloff Luís Pereira * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITRANSLATOR_H #define UKUITRANSLATOR_H #include #include "ukuiglobals.h" namespace UKUi { /** The Translator class provides internationalization support for application and librarioes. **/ class UKUI_API Translator { public: /** Returns a list of paths that the application will search translations files. **/ static QStringList translationSearchPaths(); /** Sets the list of directories to search translations. All existing paths will be deleted and the path list will consist of the paths given in paths. **/ static void setTranslationSearchPaths(const QStringList &paths); /** Loads translations for application. If applicationName is not specified, then basename of QCoreApplication::applicationFilePath() is used. Returns true if the translation is successfully loaded; otherwise returns false. **/ static bool translateApplication(const QString &applicationName = QString()); /** Loads translations for application. If applicationName is not specified, then basename of QCoreApplication::applicationFilePath() is used. Returns true if the translation is successfully loaded; otherwise returns false. **/ static bool translateLibrary(const QString &libraryName = QString()); static bool translatePlugin(const QString &pluginName, const QString& type); }; } // namespace UKUi #endif // UKUITRANSLATOR_H ukui-panel/panel/common/ukuiconfigdialog.cpp0000644000175000017500000001247513632320722020177 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright (C) 2012 Alec Moskvin * Copyright (C) 2019 minglequn * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuiconfigdialog.h" #include "ukuiconfigdialog_p.h" #include "ui_ukuiconfigdialog.h" #include #include #include "ukuisettings.h" using namespace UKUi; ConfigDialogPrivate::ConfigDialogPrivate(ConfigDialog *q, Settings *settings) : q_ptr(q), mCache(new SettingsCache(settings)), ui(new Ui::ConfigDialog) { init(); } ConfigDialogPrivate::~ConfigDialogPrivate() { delete ui; delete mCache; } void ConfigDialogPrivate::init() { Q_Q(ConfigDialog); ui->setupUi(q); QObject::connect(ui->buttons, &QDialogButtonBox::clicked, [=](QAbstractButton* button) { dialogButtonsAction(button); } ); ui->moduleList->setVisible(false); const QList buttons = ui->buttons->findChildren(); for(QPushButton* button : buttons) button->setAutoDefault(false); } void ConfigDialogPrivate::dialogButtonsAction(QAbstractButton* button) { Q_Q(ConfigDialog); QDialogButtonBox::StandardButton standardButton = ui->buttons->standardButton(button); emit q->clicked(standardButton); if (standardButton == QDialogButtonBox::Reset) { mCache->loadToSettings(); emit q->reset(); } else if(standardButton == QDialogButtonBox::Close) { q->close(); } } void ConfigDialogPrivate::updateIcons() { Q_Q(ConfigDialog); for (int ix = 0; ix < mIcons.size(); ix++) ui->moduleList->item(ix)->setIcon(XdgIcon::fromTheme(mIcons.at(ix))); q->update(); } ConfigDialog::ConfigDialog(const QString& title, Settings* settings, QWidget* parent) : QDialog(parent), mSettings(settings), d_ptr(new ConfigDialogPrivate(this, settings)) { setWindowTitle(title); } void ConfigDialog::setButtons(QDialogButtonBox::StandardButtons buttons) { Q_D(ConfigDialog); d->ui->buttons->setStandardButtons(buttons); const QList b = d->ui->buttons->findChildren(); for(QPushButton* button : b) button->setAutoDefault(false); } void ConfigDialog::enableButton(QDialogButtonBox::StandardButton which, bool enable) { Q_D(ConfigDialog); if (QPushButton* pb = d->ui->buttons->button(which)) pb->setEnabled(enable); } void ConfigDialog::addPage(QWidget* page, const QString& name, const QString& iconName) { addPage(page, name, QStringList() << iconName); } void ConfigDialog::addPage(QWidget* page, const QString& name, const QStringList& iconNames) { Q_D(ConfigDialog); Q_ASSERT(page); if (!page) { return; } /* We set the layout margin to 0. In the default configuration, one page * only, it aligns buttons with the page. In multi-page it saves a little * bit of space, without clutter. */ if (page->layout()) { page->layout()->setMargin(0); } QStringList icons = QStringList(iconNames) << QL1S("application-x-executable"); new QListWidgetItem(XdgIcon::fromTheme(icons), name, d->ui->moduleList); d->mIcons.append(icons); d->ui->stackedWidget->addWidget(page); d->mPages[name] = page; if(d->ui->stackedWidget->count() > 1) { d->ui->moduleList->setVisible(true); d->ui->moduleList->setCurrentRow(0); d->mMaxSize = QSize(qMax(page->geometry().width() + d->ui->moduleList->geometry().width(), d->mMaxSize.width()), qMax(page->geometry().height() + d->ui->buttons->geometry().height(), d->mMaxSize.height())); } else { d->mMaxSize = page->geometry().size(); } resize(d->mMaxSize); } void ConfigDialog::showPage(QWidget* page) { Q_D(ConfigDialog); int index = d->ui->stackedWidget->indexOf(page); if (index < 0) return; d->ui->stackedWidget->setCurrentIndex(index); d->ui->moduleList->setCurrentRow(index); } void ConfigDialog::showPage(const QString &name) { Q_D(ConfigDialog); if (d->mPages.contains(name)) showPage(d->mPages.value(name)); else qWarning("ConfigDialog::showPage: Invalid page name (%s)", name.toLocal8Bit().constData()); } bool ConfigDialog::event(QEvent * event) { Q_D(ConfigDialog); if (QEvent::ThemeChange == event->type()) d->updateIcons(); return QDialog::event(event); } void ConfigDialog::closeEvent(QCloseEvent* event) { Q_UNUSED(event) emit save(); mSettings->sync(); } ConfigDialog::~ConfigDialog() { } ukui-panel/panel/common/ukuigridlayout.h0000644000175000017500000001440313632320722017373 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIGRIDLAYOUT_H #define UKUIGRIDLAYOUT_H #include #include "ukuiglobals.h" #include namespace UKUi { class GridLayoutPrivate; /** The GridLayout class lays out widgets in a grid. **/ class UKUI_API GridLayout: public QLayout { Q_OBJECT public: /** This enum type is used to describe direction for this grid. **/ enum Direction { LeftToRight, ///< The items are first laid out horizontally and then vertically. TopToBottom ///< The items are first laid out vertically and then horizontally. }; /** This enum type is used to describe stretch. It contains one horizontal and one vertical flags that can be combined to produce the required effect. */ enum StretchFlag { NoStretch = 0, ///< No justifies items StretchHorizontal = 1, ///< Justifies items in the available horizontal space StretchVertical = 2 ///< Justifies items in the available vertical space }; Q_DECLARE_FLAGS(Stretch, StretchFlag) /** Constructs a new GridLayout with parent widget, parent. The layout has one row and zero column initially, and will expand to left when new items are inserted. **/ explicit GridLayout(QWidget *parent = 0); /** Destroys the grid layout. The layout's widgets aren't destroyed. **/ ~GridLayout(); void addItem(QLayoutItem *item); QLayoutItem *itemAt(int index) const; QLayoutItem *takeAt(int index); int count() const; void invalidate(); QSize sizeHint() const; void setGeometry(const QRect &geometry); QRect occupiedGeometry() const; /** Returns the number of rows in this grid. **/ int rowCount() const; /** Sets the number of rows in this grid. If value is 0, then rows count will calculated automatically when new items are inserted. In the most cases you should to set fixed number for one thing, or for rows, or for columns. \sa GridLayout::setColumnCount **/ void setRowCount(int value); /** Returns the number of columns in this grid. **/ int columnCount() const; /** Sets the number of columns in this grid. If value is 0, then columns count will calculated automatically when new items are inserted. In the most cases you should to set fixed number for one thing, or for rows, or for columns. \sa GridLayout::setRowCount **/ void setColumnCount(int value); /** Returns the alignment of this grid. \sa GridLayout::Direction **/ Direction direction() const; /** Sets the direction for this grid. \sa GridLayout::Direction **/ void setDirection(Direction value); /** Returns the stretch flags of this grid. \sa GridLayout::StretchFlag **/ Stretch stretch() const; /** Sets the stretch flags for this grid. \sa GridLayout::StretchFlag **/ void setStretch(Stretch value); /** Moves the item at index position \param from to index position \param to. If \param withAnimation set the reordering will be animated **/ void moveItem(int from, int to, bool withAnimation = false); /** Checks if layout is currently animated after the \sa moveItem() invocation. **/ bool animatedMoveInProgress() const; /** Returns the cells' minimum size. By default, this property contains a size with zero width and height. **/ QSize cellMinimumSize() const; /** Sets the minimum size of all cells to minSize pixels. **/ void setCellMinimumSize(QSize minSize); /** Sets the minimum height of the cells to value without changing the width. Provided for convenience. **/ void setCellMinimumHeight(int value); /** Sets the minimum width of the cells to value without changing the heights. Provided for convenience. **/ void setCellMinimumWidth(int value); /** Returns the cells' maximum size. By default, this property contains a size with zero width and height. **/ QSize cellMaximumSize() const; /** Sets the maximum size of all cells to maxSize pixels. **/ void setCellMaximumSize(QSize maxSize); /** Sets the maximum height of the cells to value without changing the width. Provided for convenience. **/ void setCellMaximumHeight(int value); /** Sets the maximum width of the cells to value without changing the heights. Provided for convenience. **/ void setCellMaximumWidth(int value); /** Sets both the minimum and maximum sizes of the cells to size, thereby preventing it from ever growing or shrinking. **/ void setCellFixedSize(QSize size); /** Sets both the minimum and maximum height of the cells to value without changing the width. Provided for convenience. **/ void setCellFixedHeight(int value); /** Sets both the minimum and maximum width of the cells to value without changing the heights. Provided for convenience. **/ void setCellFixedWidth(int value); private: GridLayoutPrivate* const d_ptr; Q_DECLARE_PRIVATE(GridLayout) }; Q_DECLARE_OPERATORS_FOR_FLAGS(GridLayout::Stretch) } // namespace UKUi #endif // UKUIGRIDLAYOUT_H ukui-panel/panel/common/resources/0000755000175000017500000000000013632320722016151 5ustar fengfengukui-panel/panel/common/resources/power.conf0000644000175000017500000000006013632320722020150 0ustar fengfeng[General] monitorOffCommand=xset dpms force off ukui-panel/panel/common/ukuirotatedwidget.h0000644000175000017500000001050713632320722020057 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2013 Razor team * Authors: * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIROTATED_WIDGET_H #define UKUIROTATED_WIDGET_H #include #include "ukuiglobals.h" namespace UKUi { class UKUI_API RotatedWidget: public QWidget { Q_OBJECT Q_PROPERTY(Qt::Corner origin READ origin WRITE setOrigin) Q_PROPERTY(bool transferMousePressEvent READ transferMousePressEvent WRITE setTransferMousePressEvent) Q_PROPERTY(bool transferMouseReleaseEvent READ transferMouseReleaseEvent WRITE setTransferMouseReleaseEvent) Q_PROPERTY(bool transferMouseDoubleClickEvent READ transferMouseDoubleClickEvent WRITE setTransferMouseDoubleClickEvent) Q_PROPERTY(bool transferMouseMoveEvent READ transferMouseMoveEvent WRITE setTransferMouseMoveEvent) #ifndef QT_NO_WHEELEVENT Q_PROPERTY(bool transferWheelEvent READ transferWheelEvent WRITE setTransferWheelEvent) #endif Q_PROPERTY(bool transferEnterEvent READ transferEnterEvent WRITE setTransferEnterEvent) Q_PROPERTY(bool transferLeaveEvent READ transferLeaveEvent WRITE setTransferLeaveEvent) public: explicit RotatedWidget(QWidget &content, QWidget* parent = 0, Qt::WindowFlags f = 0); Qt::Corner origin() const; void setOrigin(Qt::Corner); QWidget * content() const; void adjustContentSize(); virtual QSize minimumSizeHint() const; virtual QSize sizeHint() const; QSize adjustedSize(QSize) const; QPoint adjustedPoint(QPoint) const; bool transferMousePressEvent() const { return mTransferMousePressEvent; } void setTransferMousePressEvent(bool value) { mTransferMousePressEvent = value; } bool transferMouseReleaseEvent() const { return mTransferMouseReleaseEvent; } void setTransferMouseReleaseEvent(bool value) { mTransferMouseReleaseEvent = value; } bool transferMouseDoubleClickEvent() const { return mTransferMouseDoubleClickEvent; } void setTransferMouseDoubleClickEvent(bool value) { mTransferMouseDoubleClickEvent = value; } bool transferMouseMoveEvent() const { return mTransferMouseMoveEvent; } void setTransferMouseMoveEvent(bool value) { mTransferMouseMoveEvent = value; } #ifndef QT_NO_WHEELEVENT bool transferWheelEvent() const { return mTransferWheelEvent; } void setTransferWheelEvent(bool value) { mTransferWheelEvent = value; } #endif bool transferEnterEvent() const { return mTransferEnterEvent; } void setTransferEnterEvent(bool value) { mTransferEnterEvent = value; } bool transferLeaveEvent() const { return mTransferLeaveEvent; } void setTransferLeaveEvent(bool value) { mTransferLeaveEvent = value; } protected: virtual void paintEvent(QPaintEvent *); // Transition event handlers virtual void mousePressEvent(QMouseEvent *); virtual void mouseReleaseEvent(QMouseEvent *); virtual void mouseDoubleClickEvent(QMouseEvent *); virtual void mouseMoveEvent(QMouseEvent *); #ifndef QT_NO_WHEELEVENT virtual void wheelEvent(QWheelEvent *); #endif virtual void enterEvent(QEvent *); virtual void leaveEvent(QEvent *); virtual void resizeEvent(QResizeEvent *); private: QWidget *mContent; Qt::Corner mOrigin; bool mTransferMousePressEvent; bool mTransferMouseReleaseEvent; bool mTransferMouseDoubleClickEvent; bool mTransferMouseMoveEvent; #ifndef QT_NO_WHEELEVENT bool mTransferWheelEvent; #endif bool mTransferEnterEvent; bool mTransferLeaveEvent; }; } // namespace UKUi #endif // UKUIROTATEDWIDGET_H ukui-panel/panel/common/ukuinotification.h0000644000175000017500000001327213632320722017701 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright (C) 2012 Alec Moskvin * * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUINOTIFICATION_H #define UKUINOTIFICATION_H #include #include #include "ukuiglobals.h" namespace UKUi { class NotificationPrivate; /** * \brief Libnotify-style desktop notifications * * Spec: http://developer.gnome.org/notification-spec */ class UKUI_API Notification : public QObject { Q_OBJECT public: /*! * \brief Notification is an object that represents a single notification. * \param summary Summary text briefly describing the notification (required by the spec) */ Notification(const QString& summary = QString(), QObject* parent = 0); ~Notification(); enum CloseReason { //! The notification expired. Expired = 1, //! The notification was dismissed by the user. Dismissed = 2, //! The notification was closed by a call to close(). ForceClosed = 3, //! Undefined/reserved reasons. Unknown = 4 }; enum Urgency { UrgencyLow = 0, UrgencyNormal = 1, UrgencyCritical = 2 }; struct ServerInfo { //! The product name of the server. QString name; //! The vendor name. For example, "ukui.org" QString vendor; //! The server's version number. QString version; //! The specification version the server is compliant with. QString specVersion; }; /*! * \brief Set the summary text briefly describing the notification */ void setSummary(const QString& summary); /*! * \brief Set the detailed body text */ void setBody(const QString& body); /*! * \brief Set an icon to display * \param iconName Name of the icon */ void setIcon(const QString& iconName); /*! * \brief Set action buttons for the notification. Whenever an action is * activated, the actionActivated() signal is emitted with the list * index of the activated action. * \param actions List of action button titles * \param defaultAction Index of the default action which gets activated * when the notification body is clicked * \sa actionActivated() */ void setActions(const QStringList& actions, int defaultAction = -1); /*! * \brief Set the timeout for the notification * \param timeout Milliseconds for timeout, or zero to never time out. */ void setTimeout(int timeout); /*! * \brief Set notification hint. * \note For description of Hints, see http://developer.gnome.org/notification-spec/#hints * \note For D-Bus-to-Qt mappings, see https://qt-project.org/doc/qdbustypesystem.html * \param hint Hint name * \param value The hint data */ void setHint(const QString& hint, const QVariant& value); /*! * \brief Set the "urgency" hint * \param urgency */ void setUrgencyHint(Urgency urgency); /*! * \brief Remove all hints that were set * \sa setHint() */ void clearHints(); /*! * \brief returns a list of optional capabilities supported by the server. * For the list, see http://developer.gnome.org/notification-spec/#commands */ QStringList getCapabilities(); /*! * \brief Returns information about the notifications server */ const ServerInfo serverInfo(); /*! * \brief Convenience function to create and display a notification for the most common * cases. For anything more complex, create a Notification object, set the * desired properties and call update(). (That's what this does internally.) * \sa Notification() */ static void notify(const QString& summary, const QString& body = QString(), const QString& iconName = QString() ); public slots: /*! * \brief Display the notification or update it if it's already visible */ void update(); /*! * \brief Causes a notification to be forcefully closed and removed from the user's view. * It can be used, for example, in the event that what the notification pertains to * is no longer relevant, or to cancel a notification with no expiration time. */ void close(); signals: /*! * \brief Emitted when the notification is closed * \param reason How notification was closed */ void notificationClosed(UKUi::Notification::CloseReason reason); /*! * \brief Emitted when an action button is activated. * \param actionNumber Index of the actions array for the activated button. * \sa setActions() */ void actionActivated(int actionNumber); private: Q_DECLARE_PRIVATE(Notification) NotificationPrivate* const d_ptr; }; } // namespace UKUi #endif // UKUINOTIFICATION_H ukui-panel/panel/common/ukuinotification.cpp0000644000175000017500000001245413632320722020235 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright (C) 2012 Alec Moskvin * Copyright (C) 2019 minglequn * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuinotification.h" #include "ukuinotification_p.h" #include #include using namespace UKUi; Notification::Notification(const QString& summary, QObject* parent) : QObject(parent), d_ptr(new NotificationPrivate(summary, this)) { } Notification::~Notification() { Q_D(Notification); delete d; } void Notification::update() { Q_D(Notification); d->update(); } void Notification::close() { Q_D(Notification); d->close(); } void Notification::setSummary(const QString& summary) { Q_D(Notification); d->mSummary = summary; } void Notification::setBody(const QString& body) { Q_D(Notification); d->mBody = body; } void Notification::setIcon(const QString& iconName) { Q_D(Notification); d->mIconName = iconName; } void Notification::setActions(const QStringList& actions, int defaultAction) { Q_D(Notification); d->setActions(actions, defaultAction); } void Notification::setTimeout(int timeout) { Q_D(Notification); d->mTimeout = timeout; } void Notification::setHint(const QString& hintName, const QVariant& value) { Q_D(Notification); d->mHints.insert(hintName, value); } void Notification::setUrgencyHint(Urgency urgency) { Q_D(Notification); d->mHints.insert(QL1S("urgency"), qvariant_cast(urgency)); } void Notification::clearHints() { Q_D(Notification); d->mHints.clear(); } QStringList Notification::getCapabilities() { Q_D(Notification); return d->mInterface->GetCapabilities().value(); } const Notification::ServerInfo Notification::serverInfo() { Q_D(Notification); return d->serverInfo(); } void Notification::notify(const QString& summary, const QString& body, const QString& iconName) { Notification notification(summary); notification.setBody(body); notification.setIcon(iconName); notification.update(); } NotificationPrivate::NotificationPrivate(const QString& summary, Notification* parent) : mId(0), mSummary(summary), mTimeout(-1), q_ptr(parent) { mInterface = new OrgFreedesktopNotificationsInterface(QL1S("org.freedesktop.Notifications"), QL1S("/org/freedesktop/Notifications"), QDBusConnection::sessionBus(), this); connect(mInterface, &OrgFreedesktopNotificationsInterface::NotificationClosed, this, &NotificationPrivate::notificationClosed); connect(mInterface, &OrgFreedesktopNotificationsInterface::ActionInvoked, this, &NotificationPrivate::handleAction); } NotificationPrivate::~NotificationPrivate() { } void NotificationPrivate::update() { QDBusPendingReply reply = mInterface->Notify(qAppName(), mId, mIconName, mSummary, mBody, mActions, mHints, mTimeout); reply.waitForFinished(); if (!reply.isError()) { mId = reply.value(); } else { if (mHints.contains(QL1S("urgency")) && mHints.value(QL1S("urgency")).toInt() != Notification::UrgencyLow) QMessageBox::information(0, tr("Notifications Fallback"), mSummary + QL1S(" \n\n ") + mBody); } } void NotificationPrivate::setActions(QStringList actions, int defaultAction) { mActions.clear(); mDefaultAction = defaultAction; const int N = actions.size(); for (int ix = 0; ix < N; ix++) { if (ix == defaultAction) mActions.append(QL1S("default")); else mActions.append(QString::number(ix)); mActions.append(actions[ix]); } } const Notification::ServerInfo NotificationPrivate::serverInfo() { Notification::ServerInfo info; info.name = mInterface->GetServerInformation(info.vendor, info.version, info.specVersion); return info; } void NotificationPrivate::handleAction(uint id, QString key) { if (id != mId) return; Q_Q(Notification); qDebug() << "action invoked:" << key; bool ok = true; int keyId; if (key == QL1S("default")) keyId = mDefaultAction; else keyId = key.toInt(&ok); if (ok && keyId >= 0) emit q->actionActivated(keyId); } void NotificationPrivate::close() { mInterface->CloseNotification(mId); mId = 0; } void NotificationPrivate::notificationClosed(uint id, uint reason) { Q_Q(Notification); if (id != 0 && id == mId) { mId = 0; } emit q->notificationClosed(Notification::CloseReason(reason)); } ukui-panel/panel/common/cmake/0000755000175000017500000000000013632320722015217 5ustar fengfengukui-panel/panel/common/cmake/ukui-config.cmake.in0000644000175000017500000000244113632320722021047 0ustar fengfeng# - Finds the ukui package @PACKAGE_INIT@ if (CMAKE_VERSION VERSION_LESS 3.0.2) message(FATAL_ERROR \"@PROJECT_NAME@ requires at least CMake version 3.0.2\") endif() include(CMakeFindDependencyMacro) find_dependency(Qt5Widgets @QT_MINIMUM_VERSION@) find_dependency(Qt5DBus @QT_MINIMUM_VERSION@) find_dependency(Qt5X11Extras @QT_MINIMUM_VERSION@) find_dependency(Qt5LinguistTools @QT_MINIMUM_VERSION@) find_dependency(Qt5Xdg @QTXDG_MINIMUM_VERSION@) find_dependency(KF5WindowSystem) #find_dependency(ukui-build-tools @UKUIBT_MINIMUM_VERSION@) #include(UKUiConfigVars) include(/usr/share/cmake/ukui-build-tools/modules/UKUiConfigVars.cmake) # - Set version informations set(UKUI_MAJOR_VERSION "@UKUI_MAJOR_VERSION@") set(UKUI_MINOR_VERSION "@UKUI_MINOR_VERSION@") set(UKUI_PATCH_VERSION "@UKUI_PATCH_VERSION@") set(UKUI_VERSION "@UKUI_VERSION@") add_definitions("-DUKUI_MAJOR_VERSION=\"${UKUI_MAJOR_VERSION}\"") add_definitions("-DUKUI_MINOR_VERSION=\"${UKUI_MINOR_VERSION}\"") add_definitions("-DUKUI_PATCH_VERSION=\"${UKUI_PATCH_VERSION}\"") add_definitions("-DUKUI_VERSION=\"${UKUI_VERSION}\"") if (NOT TARGET @UKUI_LIBRARY_NAME@) if (POLICY CMP0024) cmake_policy(SET CMP0024 NEW) endif() include("${CMAKE_CURRENT_LIST_DIR}/ukui-targets.cmake") endif() ukui-panel/panel/common/ukuiscreensaver.h0000644000175000017500000000314113632320722017525 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * * Copyright: 2019-2020 UKUI team * Authors: * minglequn * * Copyright (c) 2016 Luís Pereira * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef SCREENSAVER_H #define SCREENSAVER_H #include "ukuiglobals.h" #include #include namespace UKUi { class ScreenSaverPrivate; class UKUI_API ScreenSaver : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(ScreenSaver) Q_DISABLE_COPY(ScreenSaver) public: ScreenSaver(QObject * parent=0); ~ScreenSaver(); QList availableActions(); signals: void activated(); void done(); public slots: void lockScreen(); private: ScreenSaverPrivate* const d_ptr; }; } // namespace UKUi #endif ukui-panel/panel/common/libukui.doxygen0000644000175000017500000000021413632320722017177 0ustar fengfeng/*! \mainpage A minimal shared library for UKUi DE. libukui containing shared classes for UKUi developed by UKUi team and contributors. */ ukui-panel/panel/common/ukuibacklight/0000755000175000017500000000000013633432261016770 5ustar fengfengukui-panel/panel/common/ukuibacklight/virtual_backend.h0000644000175000017500000000252313633432261022300 0ustar fengfeng/* * Copyright (C) 2016 P.L. Lucas * Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __VirtualBackend_H__ #define __VirtualBackend_H__ #include #include "ukuiglobals.h" namespace UKUi { class UKUI_API VirtualBackEnd:public QObject { Q_OBJECT public: VirtualBackEnd(QObject *parent = 0); virtual bool isBacklightAvailable(); virtual bool isBacklightOff(); virtual void setBacklight(int value); virtual int getBacklight(); virtual int getMaxBacklight(); signals: void backlightChanged(int value); }; } // namespace UKUi #endif // __VirtualBackend_H__ ukui-panel/panel/common/ukuibacklight/linux_backend/0000755000175000017500000000000013632320722021573 5ustar fengfengukui-panel/panel/common/ukuibacklight/linux_backend/linuxbackend.cpp0000644000175000017500000000611513632320722024751 0ustar fengfeng/* * Copyright (C) 2016 P.L. Lucas * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "driver/libbacklight_backend.h" #ifdef __cplusplus extern "C" { #endif #include "driver/libbacklight_backend.c" #ifdef __cplusplus } #endif #include "linuxbackend.h" #include #include namespace UKUi { LinuxBackend::LinuxBackend(QObject *parent):VirtualBackEnd(parent) { maxBacklight = ukui_backlight_backend_get_max(); backlightStream = NULL; if( isBacklightAvailable() ) { char *driver = ukui_backlight_backend_get_driver(); fileSystemWatcher = new QFileSystemWatcher(this); fileSystemWatcher->addPath(QString::fromLatin1("/sys/class/backlight/%1/actual_brightness").arg(QL1S(driver))); fileSystemWatcher->addPath(QString::fromLatin1("/sys/class/backlight/%1/brightness").arg(QL1S(driver))); fileSystemWatcher->addPath(QString::fromLatin1("/sys/class/backlight/%1/bl_power").arg(QL1S(driver))); free(driver); actualBacklight = ukui_backlight_backend_get(); connect(fileSystemWatcher, &QFileSystemWatcher::fileChanged, this, &LinuxBackend::fileSystemChanged); } } LinuxBackend::~LinuxBackend() { delete backlightStream; } int LinuxBackend::getBacklight() { actualBacklight = ukui_backlight_backend_get(); return actualBacklight; } int LinuxBackend::getMaxBacklight() { return maxBacklight; } bool LinuxBackend::isBacklightAvailable() { return maxBacklight > 0; } bool LinuxBackend::isBacklightOff() { return ukui_backlight_is_backlight_off() > 0; } void LinuxBackend::setBacklight(int value) { if( ! isBacklightAvailable() ) return; if( backlightStream == NULL ) { FILE *stream = ukui_backlight_backend_get_write_stream(); backlightStream = new QTextStream(stream); // Close stream after 60 seconds QTimer::singleShot(60000, this, SLOT(closeBacklightStream())); } // normalize the value (to work around an issue in QSlider) value = qBound(0, value, maxBacklight); *backlightStream << value << endl; } void LinuxBackend::closeBacklightStream() { if( backlightStream != NULL ) { delete backlightStream; backlightStream = NULL; } } void LinuxBackend::fileSystemChanged(const QString & /*path*/) { int value = actualBacklight; if( value != getBacklight() ) { emit backlightChanged(actualBacklight); } } } // namespace UKUi ukui-panel/panel/common/ukuibacklight/linux_backend/driver/0000755000175000017500000000000013632320722023066 5ustar fengfengukui-panel/panel/common/ukuibacklight/linux_backend/driver/lxqtbacklight_backend.c0000644000175000017500000001270513632320722027547 0ustar fengfeng/* * Copyright (C) 2016 P.L. Lucas * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include "libbacklight_backend.h" #include "libbacklight_backend.c" #define True 1 #define False 0 /**bl_power turn off or turn on backlight. * @param driver is the driver to use * @param value 0 turns on backlight, 4 turns off backlight */ static void set_bl_power(const char *driver, int value) { FILE *out = open_driver_file("bl_power", driver, "w"); if( out != NULL ) { fprintf(out, "%d", value); fclose(out); } } static void set_backlight(const char *driver, int value) { if(value>0) { FILE *out = open_driver_file("brightness", driver, "w"); if( out != NULL ) { fprintf(out, "%d", value); fclose(out); } if(read_bl_power(driver) > 0) set_bl_power(driver, 0); } else { set_bl_power(driver, 4); } } static char *get_driver() { return ukui_backlight_backend_get_driver(); } static void show_blacklight() { char *driver = get_driver(); if( driver == NULL ) { return; } int max_value = read_max_backlight(driver); int actual = read_backlight(driver); printf("%s %d %d\n", driver, max_value, actual); free(driver); } static void change_blacklight(int value, int percent_ok) { char *driver = get_driver(); if( driver == NULL ) { return; } int max_value = read_max_backlight(driver); if(percent_ok) { value = (float)(max_value*value)/100.0; if( value == 0 ) { // avoid switching off backlight but support zero as lowest value value = 1; } } if(value<=max_value && value>0) { set_backlight(driver, value); } free(driver); } static void increases_blacklight() { char *driver = get_driver(); if( driver == NULL ) { return; } int max_value = read_max_backlight(driver); int actual = read_backlight(driver); int incr = max_value/10; if( incr == 0 ) incr = 1; int value = actual + incr; if( value > max_value) value = max_value; if(value0) { set_backlight(driver, value); } free(driver); } static void decreases_blacklight() { char *driver = get_driver(); if( driver == NULL ) { return; } int max_value = read_max_backlight(driver); int actual = read_backlight(driver); int decr = max_value/10; if( decr == 0 ) decr = 1; int value = actual - decr; if( value <= 0 ) value = 1; if(value0) { set_backlight(driver, value); } free(driver); } static void set_backlight_from_stdin() { char *driver = get_driver(); int ok = True, value; int max_value = read_max_backlight(driver); if( driver == NULL ) { return; } while(ok && !feof(stdin)) { ok = scanf("%d", &value); if( ok != EOF && value > 0 && value <= max_value) { set_backlight(driver, value); } } free(driver); } static void help(char *argv0) { printf("%s [backlight-level [ %% ]] [--help]\n" "--help Shows this message.\n" "--show Shows actual brightness level.\n" "--inc Increases actual brightness level.\n" "--dec Decreases actual brightness level.\n" "--stdin Read backlight value from stdin\n" "backlight-level Sets backlight\n" "backlight-level %% Sets backlight from 1%% to 100%%\n" "This tool changes screen backlight.\n" "Example:\n" "%s 10 %% Sets backlight level until 10%%.\n" , argv0, argv0 ); } int main(int argc, char *argv[]) { int value = -1, value_percent_ok = False; int n; for(n=1; n /**Returns actual value of backlight. * -1 will be returned if backlight can not be changed. */ int ukui_backlight_backend_get(); /**Returns maximum value of backlight. * -1 will be returned if backlight can not be changed. */ int ukui_backlight_backend_get_max(); /**Returns a FILE pointer to stream which can be used to write values * of backlight. * int max_backlight = ukui_backlight_backend_get_max(); * if(max_backlight<0) * return; // Backlight can not be controlled. * FILE *fout = ukui_backlight_backend_write_stream(); * fprintf(fout, "%d\n", 3); * fflush(fout); * // ... Do something ... * fprintf(fout, "%d\n", 7); * fclose(fout); * Under Qt you can use QTextStream class: * FILE *fout = ukui_backlight_backend_write_stream(); * QTextStream backlightStream(fout); * backlightStream << 3 << endl; */ FILE *ukui_backlight_backend_get_write_stream(); /**Returns if backlight power is turned off. * @ return 0 backlight off, bigger then 0 backlight on. */ int ukui_backlight_is_backlight_off(); /**Returns the driver. Backlight values are read from /sys/class/backlight/driver/. * Example: * char *driver = ukui_backlight_backend_get_driver(); * printf("%s\n", driver); * free(driver); */ char *ukui_backlight_backend_get_driver(); #ifdef __cplusplus } #endif #endifukui-panel/panel/common/ukuibacklight/linux_backend/driver/CMakeLists.txt0000644000175000017500000000041613632320722025627 0ustar fengfengproject(ukui-backlight_backend) set(C_FILES ukuibacklight_backend.c ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) add_executable(${PROJECT_NAME} ${C_FILES} ) install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) ukui-panel/panel/common/ukuibacklight/linux_backend/driver/libbacklight_backend.c0000644000175000017500000001603313632320722027323 0ustar fengfeng/* * Copyright (C) 2016 P.L. Lucas * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /******************************************************************************** * This library uses Linux /sys/class/backlight files to read and change the * backlight level. * * If screen backlight can be controlled, the Linux kernel will show inside * /sys/class/backlight directory one or more directories. Each directory has * got the following files: * /sys/class/backlight/driver/max_brightness * /sys/class/backlight/driver/actual_brightness * /sys/class/backlight/driver/brightness * /sys/class/backlight/driver/type * /sys/class/backlight/driver/bl_power * * The "max_brightness" file contains the maximum value that can be set to the * backlight level. * * In "brightness" file you can write the value of backlight and the Linux * kernel will set that value. * * The "bl_power" controls if backlight is turn on (0) or turn off (>0). * * You must read actual backlight level from "actual_brightness" file. Never * read the backlight level from "brightness" file. * * The "type" file is the type of control and it can be: * firmware * platform * raw * The firmware control should be preferred to platform control. The platform * control should be preferred to raw control. * If there are several directories in /sys/class/backlight/, you should use * the directory which its "type" file has got the "firmware" value. * * In order to write in /sys/class/backlight/driver/brightness file root * permissions are needed. This library calls to a command line tool called * "ukuibacklight_backend". "ukuibacklight_backend" has a policy in Polkit * in order to write in /sys/class/backlight/driver/brightness file. *******************************************************************************/ #include #include #include #include #include #include #include #include "libbacklight_backend.h" #define True 1 #define False 0 static FILE* open_driver_file(const char *file, const char *driver, const char *mode); static int read_backlight(const char *driver); static int read_max_backlight(const char *driver); static int read_bl_power(const char *driver); static const char *sysfs_backlight_dir = "/sys/class/backlight"; int ukui_backlight_backend_get() { char *driver = ukui_backlight_backend_get_driver(); if( driver == NULL ) { return -1; } int value = read_backlight(driver); free(driver); return value; } int ukui_backlight_backend_get_max() { char *driver = ukui_backlight_backend_get_driver(); if( driver == NULL ) { return -1; } int value = read_max_backlight(driver); int bl_power = read_bl_power(driver); free(driver); return bl_power==0 ? value : -1; } FILE *ukui_backlight_backend_get_write_stream() { FILE *stream = popen("pkexec ukui-backlight_backend --stdin", "w"); return stream; } int ukui_backlight_is_backlight_off() { char *driver = ukui_backlight_backend_get_driver(); if( driver == NULL ) { return -1; } int bl_power = read_bl_power(driver); free(driver); return bl_power; } static int read_int(const char *file, const char *driver) { FILE *in = open_driver_file(file, driver, "r"); if( in == NULL ) { return -1; } int value; int ok = fscanf(in, "%d", &value); fclose(in); if( ok == EOF ) { value = 0; } return value; } static FILE* open_driver_file(const char *file, const char *driver, const char *mode) { char path[PATH_MAX]; int res; res = snprintf(path, PATH_MAX, "%s/%s/%s", sysfs_backlight_dir, driver, file); if( res <= 0 || res >= PATH_MAX ) { path[0] = '\0'; return NULL; } FILE *ret = fopen(path, mode); if( ret == NULL ) { fprintf(stderr, "Couldn't open %s: %s\n", path, strerror(errno)); } return ret; } static int read_backlight(const char *driver) { return read_int("actual_brightness", driver); } static int read_max_backlight(const char *driver) { return read_int("max_brightness", driver); } static int read_bl_power(const char *driver) { return read_int("bl_power", driver); } typedef enum {FIRMWARE, PLATFORM, RAW, OTHER, N_BACKLIGHT} BackligthTypes; char *ukui_backlight_backend_get_driver() { DIR *dirp; struct dirent *dp; char *drivers[N_BACKLIGHT]; char *driver; int n; char type[1024]; for(n=0;nd_name, ".") || !strcmp(dp->d_name, "..") ) continue; driver = dp->d_name; FILE *in = open_driver_file("type", driver, "r"); if( in == NULL ) continue; // the maximum field width does not include '\0'! int ok = fscanf(in, "%1023s", type); fclose(in); if( ok != EOF ) { // firmware control should be preferred to platform control should be preferred to raw control. if( ! strcmp("firmware", type) ) { drivers[FIRMWARE] = strdup(driver); break; } else if( ! strcmp("platform", type) ) drivers[PLATFORM] = strdup(driver); else if( ! strcmp("raw", type) ) drivers[RAW] = strdup(driver); else // Only, firmware, platform and raw are defined, but... drivers[OTHER] = strdup(driver); } } } while (dp != NULL); closedir(dirp); if (errno != 0) { fprintf(stderr, "Error reading directory %s: %s\n", sysfs_backlight_dir, strerror(errno)); } driver = NULL; for(n=0;n #include namespace UKUi { class LinuxBackend:public VirtualBackEnd { Q_OBJECT public: LinuxBackend(QObject *parent = 0); ~LinuxBackend(); bool isBacklightAvailable(); bool isBacklightOff(); void setBacklight(int value); int getBacklight(); int getMaxBacklight(); signals: void backlightChanged(int value); private slots: void closeBacklightStream(); void fileSystemChanged(const QString & path); private: QTextStream *backlightStream; int maxBacklight; int actualBacklight; QFileSystemWatcher *fileSystemWatcher; }; } // namespace UKUi #endif // __LinuxBackend_H__ukui-panel/panel/common/ukuibacklight/virtual_backend.cpp0000644000175000017500000000236513633432261022637 0ustar fengfeng/* * Copyright (C) 2018 P.L. Lucas * Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "virtual_backend.h" namespace UKUi { VirtualBackEnd::VirtualBackEnd(QObject *parent):QObject(parent) { } bool VirtualBackEnd::isBacklightAvailable() { return false; } bool VirtualBackEnd::isBacklightOff() { return false; } void VirtualBackEnd::setBacklight(int /*value*/) { } int VirtualBackEnd::getBacklight() { return -1; } int VirtualBackEnd::getMaxBacklight() { return -1; } } // namespace UKUi ukui-panel/panel/common/ukuisettings.cpp0000644000175000017500000005022413632320722017404 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuisettings.h" #include #include #include #include #include #include #include #include #include #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) #include #endif using namespace UKUi; class UKUi::SettingsPrivate { public: SettingsPrivate(Settings* parent, bool useXdgFallback): mFileChangeTimer(0), mAppChangeTimer(0), mAddWatchTimer(0), mParent(parent) { // HACK: we need to ensure that the user (~/.config/ukui/.conf) // exists to have functional mWatcher if (!mParent->contains(QL1S("__userfile__"))) { mParent->setValue(QL1S("__userfile__"), true); #if defined(WITH_XDG_DIRS_FALLBACK) if (useXdgFallback) { //Note: Qt doesn't support the xdg spec regarding the XDG_CONFIG_DIRS //https://bugreports.qt.io/browse/QTBUG-34919 //(Partial) workaround: if the the user specific config file doesn't exist //we try to find some system-wide configuration file and copy all settings into //the user specific file const QString org = mParent->organizationName(); const QString file_name = QFileInfo{mParent->fileName()}.fileName(); QStringList dirs = XdgDirs::configDirs(); #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) std::reverse(dirs.begin(), dirs.end()); for (auto dir_i = dirs.begin(), dir_e = dirs.end(); dir_i != dir_e; ++dir_i) #else // QT_VERSION for (auto dir_i = dirs.rbegin(), dir_e = dirs.rend(); dir_i != dir_e; ++dir_i) #endif { QDir dir{*dir_i}; if (dir.cd(mParent->organizationName()) && dir.exists(file_name)) { QSettings system_settings{dir.absoluteFilePath(file_name), QSettings::IniFormat}; const QStringList keys = system_settings.allKeys(); for (const QString & key : keys) { mParent->setValue(key, system_settings.value(key)); } } } } #endif mParent->sync(); } mWatcher.addPath(mParent->fileName()); QObject::connect(&(mWatcher), &QFileSystemWatcher::fileChanged, mParent, &Settings::_fileChanged); } QString localizedKey(const QString& key) const; QFileSystemWatcher mWatcher; int mFileChangeTimer; int mAppChangeTimer; int mAddWatchTimer; private: Settings* mParent; }; UKUiTheme* UKUiTheme::mInstance = 0; class UKUi::UKUiThemeData: public QSharedData { public: UKUiThemeData(): mValid(false) {} QString loadQss(const QString& qssFile) const; QString findTheme(const QString &themeName); QString mName; QString mPath; QString mPreviewImg; bool mValid; }; class UKUi::GlobalSettingsPrivate { public: GlobalSettingsPrivate(GlobalSettings *parent): mParent(parent), mThemeUpdated(0ull) { } GlobalSettings *mParent; QString mIconTheme; QString mUKUiTheme; qlonglong mThemeUpdated; }; /************************************************ ************************************************/ Settings::Settings(const QString& module, QObject* parent) : QSettings(QL1S("ukui"), module, parent), d_ptr(new SettingsPrivate(this, true)) { } /************************************************ ************************************************/ Settings::Settings(const QString &fileName, QSettings::Format format, QObject *parent): QSettings(fileName, format, parent), d_ptr(new SettingsPrivate(this, false)) { } /************************************************ ************************************************/ Settings::Settings(const QSettings* parentSettings, const QString& subGroup, QObject* parent): QSettings(parentSettings->organizationName(), parentSettings->applicationName(), parent), d_ptr(new SettingsPrivate(this, false)) { beginGroup(subGroup); } /************************************************ ************************************************/ Settings::Settings(const QSettings& parentSettings, const QString& subGroup, QObject* parent): QSettings(parentSettings.organizationName(), parentSettings.applicationName(), parent), d_ptr(new SettingsPrivate(this, false)) { beginGroup(subGroup); } /************************************************ ************************************************/ Settings::~Settings() { // because in the Settings::Settings(const QString& module, QObject* parent) // constructor there is no beginGroup() called... if (!group().isEmpty()) endGroup(); delete d_ptr; } bool Settings::event(QEvent *event) { if (event->type() == QEvent::UpdateRequest) { // delay the settingsChanged* signal emitting for: // - checking in _fileChanged // - merging emitting the signals if(d_ptr->mAppChangeTimer) killTimer(d_ptr->mAppChangeTimer); d_ptr->mAppChangeTimer = startTimer(100); } else if (event->type() == QEvent::Timer) { const int timer = static_cast(event)->timerId(); killTimer(timer); if (timer == d_ptr->mFileChangeTimer) { d_ptr->mFileChangeTimer = 0; fileChanged(); // invoke the real fileChanged() handler. } else if (timer == d_ptr->mAppChangeTimer) { d_ptr->mAppChangeTimer = 0; // do emit the signals emit settingsChangedByApp(); emit settingsChanged(); } else if (timer == d_ptr->mAddWatchTimer) { d_ptr->mAddWatchTimer = 0; //try to re-add filename for watching addWatchedFile(fileName()); } } return QSettings::event(event); } void Settings::fileChanged() { sync(); emit settingsChangedFromExternal(); emit settingsChanged(); } void Settings::_fileChanged(QString path) { // check if the file isn't changed by our logic // FIXME: this is poor implementation; should we rather compute some hash of values if changed by external? if (0 == d_ptr->mAppChangeTimer) { // delay the change notification for 100 ms to avoid // unnecessary repeated loading of the same config file if // the file is changed for several times rapidly. if(d_ptr->mFileChangeTimer) killTimer(d_ptr->mFileChangeTimer); d_ptr->mFileChangeTimer = startTimer(1000); } addWatchedFile(path); } void Settings::addWatchedFile(QString const & path) { // D*mn! yet another Qt 5.4 regression!!! // See the bug report: https://github.com/ukui/ukui/issues/441 // Since Qt 5.4, QSettings uses QSaveFile to save the config files. // https://github.com/qtproject/qtbase/commit/8d15068911d7c0ba05732e2796aaa7a90e34a6a1#diff-e691c0405f02f3478f4f50a27bdaecde // QSaveFile will save the content to a new temp file, and replace the old file later. // Hence the existing config file is not changed. Instead, it's deleted and then replaced. // This new behaviour unfortunately breaks QFileSystemWatcher. // After file deletion, we can no longer receive any new change notifications. // The most ridiculous thing is, QFileSystemWatcher does not provide a // way for us to know if a file is deleted. WT*? // Luckily, I found a workaround: If the file path no longer exists // in the watcher's files(), this file is deleted. if(!d_ptr->mWatcher.files().contains(path)) // in some situations adding fails because of non-existing file (e.g. editting file in external program) if (!d_ptr->mWatcher.addPath(path) && 0 == d_ptr->mAddWatchTimer) d_ptr->mAddWatchTimer = startTimer(100); } /************************************************ ************************************************/ const GlobalSettings *Settings::globalSettings() { static QMutex mutex; static GlobalSettings *instance = 0; if (!instance) { mutex.lock(); if (!instance) instance = new GlobalSettings(); mutex.unlock(); } return instance; } /************************************************ LC_MESSAGES value Possible keys in order of matching lang_COUNTRY@MODIFIER lang_COUNTRY@MODIFIER, lang_COUNTRY, lang@MODIFIER, lang, default value lang_COUNTRY lang_COUNTRY, lang, default value lang@MODIFIER lang@MODIFIER, lang, default value lang lang, default value ************************************************/ QString SettingsPrivate::localizedKey(const QString& key) const { QString lang = QString::fromLocal8Bit(qgetenv("LC_MESSAGES")); if (lang.isEmpty()) lang = QString::fromLocal8Bit(qgetenv("LC_ALL")); if (lang.isEmpty()) lang = QString::fromLocal8Bit(qgetenv("LANG")); QString modifier = lang.section(QL1C('@'), 1); if (!modifier.isEmpty()) lang.truncate(lang.length() - modifier.length() - 1); QString encoding = lang.section(QL1C('.'), 1); if (!encoding.isEmpty()) lang.truncate(lang.length() - encoding.length() - 1); QString country = lang.section(QL1C('_'), 1); if (!country.isEmpty()) lang.truncate(lang.length() - country.length() - 1); //qDebug() << "LC_MESSAGES: " << getenv("LC_MESSAGES"); //qDebug() << "Lang:" << lang; //qDebug() << "Country:" << country; //qDebug() << "Encoding:" << encoding; //qDebug() << "Modifier:" << modifier; if (!modifier.isEmpty() && !country.isEmpty()) { QString k = QString::fromLatin1("%1[%2_%3@%4]").arg(key, lang, country, modifier); //qDebug() << "\t try " << k << mParent->contains(k); if (mParent->contains(k)) return k; } if (!country.isEmpty()) { QString k = QString::fromLatin1("%1[%2_%3]").arg(key, lang, country); //qDebug() << "\t try " << k << mParent->contains(k); if (mParent->contains(k)) return k; } if (!modifier.isEmpty()) { QString k = QString::fromLatin1("%1[%2@%3]").arg(key, lang, modifier); //qDebug() << "\t try " << k << mParent->contains(k); if (mParent->contains(k)) return k; } QString k = QString::fromLatin1("%1[%2]").arg(key, lang); //qDebug() << "\t try " << k << mParent->contains(k); if (mParent->contains(k)) return k; //qDebug() << "\t try " << key << mParent->contains(key); return key; } /************************************************ ************************************************/ QVariant Settings::localizedValue(const QString& key, const QVariant& defaultValue) const { Q_D(const Settings); return value(d->localizedKey(key), defaultValue); } /************************************************ ************************************************/ void Settings::setLocalizedValue(const QString &key, const QVariant &value) { Q_D(const Settings); setValue(d->localizedKey(key), value); } /************************************************ ************************************************/ UKUiTheme::UKUiTheme(): d(new UKUiThemeData) { } /************************************************ ************************************************/ UKUiTheme::UKUiTheme(const QString &path): d(new UKUiThemeData) { if (path.isEmpty()) return; QFileInfo fi(path); if (fi.isAbsolute()) { d->mPath = path; d->mName = fi.fileName(); d->mValid = fi.isDir(); } else { d->mName = path; d->mPath = d->findTheme(path); d->mValid = !(d->mPath.isEmpty()); } if (QDir(path).exists(QL1S("preview.png"))) d->mPreviewImg = path + QL1S("/preview.png"); } /************************************************ ************************************************/ QString UKUiThemeData::findTheme(const QString &themeName) { if (themeName.isEmpty()) return QString(); QStringList paths; QLatin1String fallback(UKUI_INSTALL_PREFIX); paths << XdgDirs::dataHome(false); paths << XdgDirs::dataDirs(); if (!paths.contains(fallback)) paths << fallback; for(const QString &path : qAsConst(paths)) { QDir dir(QString::fromLatin1("%1/ukui/themes/%2").arg(path, themeName)); if (dir.isReadable()) return dir.absolutePath(); } return QString(); } /************************************************ ************************************************/ UKUiTheme::UKUiTheme(const UKUiTheme &other): d(other.d) { } /************************************************ ************************************************/ UKUiTheme::~UKUiTheme() { } /************************************************ ************************************************/ UKUiTheme& UKUiTheme::operator=(const UKUiTheme &other) { d = other.d; return *this; } /************************************************ ************************************************/ bool UKUiTheme::isValid() const { return d->mValid; } /************************************************ ************************************************/ QString UKUiTheme::name() const { return d->mName; } /************************************************ ************************************************/ QString UKUiTheme::path() const { return d->mPath; } /************************************************ ************************************************/ QString UKUiTheme::previewImage() const { return d->mPreviewImg; } /************************************************ ************************************************/ QString UKUiTheme::qss(const QString& module) const { return d->loadQss(QStringLiteral("%1/%2.qss").arg(d->mPath, module)); } /************************************************ ************************************************/ QString UKUiThemeData::loadQss(const QString& qssFile) const { QFile f(qssFile); if (! f.open(QIODevice::ReadOnly | QIODevice::Text)) { return QString(); } QString qss = QString::fromLocal8Bit(f.readAll()); f.close(); if (qss.isEmpty()) return QString(); // handle relative paths QString qssDir = QFileInfo(qssFile).canonicalPath(); qss.replace(QRegExp(QL1S("url.[ \\t\\s]*"), Qt::CaseInsensitive, QRegExp::RegExp2), QL1S("url(") + qssDir + QL1C('/')); return qss; } /************************************************ ************************************************/ QString UKUiTheme::desktopBackground(int screen) const { QString wallpaperCfgFileName = QString::fromLatin1("%1/wallpaper.cfg").arg(d->mPath); if (wallpaperCfgFileName.isEmpty()) return QString(); QSettings s(wallpaperCfgFileName, QSettings::IniFormat); QString themeDir = QFileInfo(wallpaperCfgFileName).absolutePath(); // There is something strange... If I remove next line the wallpapers array is not found... s.childKeys(); s.beginReadArray(QL1S("wallpapers")); s.setArrayIndex(screen - 1); if (s.contains(QL1S("file"))) return QString::fromLatin1("%1/%2").arg(themeDir, s.value(QL1S("file")).toString()); s.setArrayIndex(0); if (s.contains(QL1S("file"))) return QString::fromLatin1("%1/%2").arg(themeDir, s.value(QL1S("file")).toString()); return QString(); } /************************************************ ************************************************/ const UKUiTheme &UKUiTheme::currentTheme() { static UKUiTheme theme; QString name = Settings::globalSettings()->value(QL1S("theme")).toString(); if (theme.name() != name) { theme = UKUiTheme(name); } return theme; } /************************************************ ************************************************/ QList UKUiTheme::allThemes() { QList ret; QSet processed; QStringList paths; paths << XdgDirs::dataHome(false); paths << XdgDirs::dataDirs(); for(const QString &path : qAsConst(paths)) { QDir dir(QString::fromLatin1("%1/ukui/themes").arg(path)); const QFileInfoList dirs = dir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot); for(const QFileInfo &dir : dirs) { if (!processed.contains(dir.fileName()) && QDir(dir.absoluteFilePath()).exists(QL1S("ukui-panel.qss"))) { processed << dir.fileName(); ret << UKUiTheme(dir.absoluteFilePath()); } } } return ret; } /************************************************ ************************************************/ SettingsCache::SettingsCache(QSettings &settings) : mSettings(settings) { loadFromSettings(); } /************************************************ ************************************************/ SettingsCache::SettingsCache(QSettings *settings) : mSettings(*settings) { loadFromSettings(); } /************************************************ ************************************************/ void SettingsCache::loadFromSettings() { const QStringList keys = mSettings.allKeys(); const int N = keys.size(); for (int i = 0; i < N; ++i) { mCache.insert(keys.at(i), mSettings.value(keys.at(i))); } } /************************************************ ************************************************/ void SettingsCache::loadToSettings() { QHash::const_iterator i = mCache.constBegin(); while(i != mCache.constEnd()) { mSettings.setValue(i.key(), i.value()); ++i; } mSettings.sync(); } /************************************************ ************************************************/ GlobalSettings::GlobalSettings(): Settings(QL1S("ukui")), d_ptr(new GlobalSettingsPrivate(this)) { if (value(QL1S("icon_theme")).toString().isEmpty()) { qWarning() << QString::fromLatin1("Icon Theme not set. Fallbacking to Oxygen, if installed"); const QString fallback(QLatin1String("oxygen")); const QDir dir(QLatin1String(UKUI_DATA_DIR) + QLatin1String("/icons")); if (dir.exists(fallback)) { setValue(QL1S("icon_theme"), fallback); sync(); } else { qWarning() << QString::fromLatin1("Fallback Icon Theme (Oxygen) not found"); } } fileChanged(); } GlobalSettings::~GlobalSettings() { delete d_ptr; } /************************************************ ************************************************/ void GlobalSettings::fileChanged() { Q_D(GlobalSettings); sync(); QString it = value(QL1S("icon_theme")).toString(); if (d->mIconTheme != it) { emit iconThemeChanged(); } QString rt = value(QL1S("theme")).toString(); qlonglong themeUpdated = value(QL1S("__theme_updated__")).toLongLong(); if ((d->mUKUiTheme != rt) || (d->mThemeUpdated != themeUpdated)) { d->mUKUiTheme = rt; emit ukuiThemeChanged(); } emit settingsChangedFromExternal(); emit settingsChanged(); } ukui-panel/panel/common/ukuiplugininfo.cpp0000644000175000017500000001166113632320722017720 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuiplugininfo.h" #include #include #include #include #include #include #include using namespace UKUi; /************************************************ ************************************************/ PluginInfo::PluginInfo(): XdgDesktopFile() { } /************************************************ ************************************************/ bool PluginInfo::load(const QString& fileName) { XdgDesktopFile::load(fileName); mId = QFileInfo(fileName).completeBaseName(); return isValid(); } /************************************************ ************************************************/ bool PluginInfo::isValid() const { return XdgDesktopFile::isValid(); } /************************************************ ************************************************/ QLibrary* PluginInfo::loadLibrary(const QString& libDir) const { const QFileInfo fi = QFileInfo(fileName()); const QString path = fi.canonicalPath(); const QString baseName = value(QL1S("X-UKUi-Library"), fi.completeBaseName()).toString(); const QString soPath = QDir(libDir).filePath(QString::fromLatin1("lib%2.so").arg(baseName)); QLibrary* library = new QLibrary(soPath); if (!library->load()) { qWarning() << QString::fromLatin1("Can't load plugin lib \"%1\"").arg(soPath) << library->errorString(); delete library; return 0; } const QString locale = QLocale::system().name(); QTranslator* translator = new QTranslator(library); translator->load(QString::fromLatin1("%1/%2/%2_%3.qm").arg(path, baseName, locale)); qApp->installTranslator(translator); return library; } /************************************************ ************************************************/ PluginInfoList PluginInfo::search(const QStringList& desktopFilesDirs, const QString& serviceType, const QString& nameFilter) { QList res; QSet processed; for (const QString &desktopFilesDir : desktopFilesDirs) { const QDir dir(desktopFilesDir); const QFileInfoList files = dir.entryInfoList(QStringList(nameFilter), QDir::Files | QDir::Readable); for (const QFileInfo &file : files) { if (processed.contains(file.fileName())) continue; processed << file.fileName(); PluginInfo item; item.load(file.canonicalFilePath()); if (item.isValid() && item.serviceType() == serviceType) res.append(item); } } return res; } /************************************************ ************************************************/ PluginInfoList PluginInfo::search(const QString& desktopFilesDir, const QString& serviceType, const QString& nameFilter) { return search(QStringList(desktopFilesDir), serviceType, nameFilter); } /************************************************ ************************************************/ QDebug operator<<(QDebug dbg, const UKUi::PluginInfo &pluginInfo) { dbg.nospace() << QString::fromLatin1("%1").arg(pluginInfo.id()); return dbg.space(); } /************************************************ ************************************************/ QDebug operator<<(QDebug dbg, const UKUi::PluginInfo * const pluginInfo) { return operator<<(dbg, *pluginInfo); } /************************************************ ************************************************/ QDebug operator<<(QDebug dbg, const PluginInfoList& list) { dbg.nospace() << QL1C('('); for (int i=0; i * Paulo Lieuthier * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuihtmldelegate.h" #include #include #include using namespace UKUi; HtmlDelegate::HtmlDelegate(const QSize iconSize, QObject* parent) : QStyledItemDelegate(parent), mIconSize(iconSize) { } HtmlDelegate::~HtmlDelegate() { } /************************************************ ************************************************/ void HtmlDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { if (!index.isValid()) return; QStyleOptionViewItem options = option; initStyleOption(&options, index); const bool is_right_to_left = Qt::RightToLeft == options.direction; painter->save(); QTextDocument doc; doc.setHtml(options.text); QIcon icon = options.icon; // icon size const QSize iconSize = icon.actualSize(mIconSize); // center the icon vertically QRect iconRect = QRect(8, qMax(options.rect.height() - iconSize.height(), 0) / 2, iconSize.width(), iconSize.height()); if (is_right_to_left) { iconRect.moveLeft(options.rect.left() + options.rect.right() - iconRect.x() - iconRect.width() + 1); } // set doc size // NOTE: Qt has a bug, because of which HTML tags are included in QTextDocument::setTextWidth() // when the text is set by QTextDocument::setHtml(). // As a result, the text height may be a little greater than needed. doc.setTextWidth(options.rect.width() - iconRect.width() - 8 - 8); // 8-px icon-text spacing // draw the item's panel const QWidget* widget = option.widget; QStyle* style = widget ? widget->style() : QApplication::style(); style->drawPrimitive(QStyle::PE_PanelItemViewItem, &options, painter, widget); // paint icon painter->translate(options.rect.left(), options.rect.top()); icon.paint(painter, iconRect); // center the text vertically painter->translate(0, qMax(static_cast(options.rect.height()) - doc.size().height(), 0.0) / 2.0); if (!is_right_to_left) { // shift text right to make icon visible painter->translate((iconRect.right() + 1) + 8, 0); } const QRect clip(0, 0, options.rect.width() - iconRect.width() - 8, options.rect.height()); painter->setClipRect(clip); // set text colors QAbstractTextDocumentLayout::PaintContext ctx; QPalette::ColorGroup colorGroup = (option.state & QStyle::State_Active) ? QPalette::Active : QPalette::Inactive; if (option.state & QStyle::State_Selected) // selected items ctx.palette.setColor(QPalette::Text, option.palette.color(colorGroup, QPalette::HighlightedText)); else // ordinary items and those with an alternate base color (there is no alternate text color) ctx.palette.setColor(QPalette::Text, option.palette.color(colorGroup, QPalette::Text)); ctx.clip = clip; doc.documentLayout()->draw(painter, ctx); painter->restore(); } /************************************************ ************************************************/ QSize HtmlDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { QStyleOptionViewItem options = option; initStyleOption(&options, index); const QSize iconSize = options.icon.actualSize(mIconSize); // 8-px left, top and bottom margins for the icon const QRect iconRect = QRect(8, 8, iconSize.width(), iconSize.height()); const int w = options.rect.width(); QTextDocument doc; doc.setHtml(options.text); if (w > 0) doc.setTextWidth(static_cast(w - (iconRect.right() + 1) - 8)); // 8-px icon-text spacing else doc.adjustSize(); return QSize(w > 0 ? w : iconRect.width() + 8 + qRound(doc.size().width()) + 8, qMax(qRound(doc.size().height() + 8), // 4-px top/bottom text spacing iconSize.height() + 16)); } ukui-panel/panel/common/ukuibacklight.h0000644000175000017500000000271113632320722017137 0ustar fengfeng/* * Copyright (C) 2016 P.L. Lucas * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __Backlight_H__ #define __Backlight_H__ #include #include "ukuiglobals.h" namespace UKUi { class VirtualBackEnd; class UKUI_API Backlight : public QObject { Q_OBJECT public: Backlight(QObject *parent = 0); ~Backlight(); bool isBacklightAvailable(); bool isBacklightOff(); /**Sets backlight level. * @param value backlight level. Negative values turn off backlight. */ void setBacklight(int value); int getBacklight(); int getMaxBacklight(); signals: void backlightChanged(int value); private slots: void backlightChangedSlot(int value); private: VirtualBackEnd *m_backend; }; } // namespace UKUi #endif // __Backlight_H__ukui-panel/panel/common/ukuiscreensaver.cpp0000644000175000017500000001740113632320722020064 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * Copyright (c) 2016 Luís Pereira * Copyright (c) 2012 The Chromium Authors. All rights reserved. * Copyright (c) 2019 minglequn * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include #include "ukuiscreensaver.h" #include "ukuitranslator.h" #include #include #include #include #include #include #include // for Q_DECLARE_TR_FUNCTIONS #include #include // Avoid polluting everything with X11/Xlib.h: typedef struct _XDisplay Display; typedef unsigned long XAtom; typedef unsigned long XID; extern "C" { int XFree(void*); } template struct XObjectDeleter { inline void operator()(void* ptr) const { F(static_cast(ptr)); } }; template > using XScopedPtr = std::unique_ptr; namespace UKUi { static bool GetProperty(XID window, const std::string& property_name, long max_length, Atom* type, int* format, unsigned long* num_items, unsigned char** property); static bool GetIntArrayProperty(XID window, const std::string& property_name, std::vector* value); static bool GetProperty(XID window, const std::string& property_name, long max_length, Atom* type, int* format, unsigned long* num_items, unsigned char** property) { Atom property_atom = XInternAtom(QX11Info::display(), property_name.c_str(), false); unsigned long remaining_bytes = 0; return XGetWindowProperty(QX11Info::display(), window, property_atom, 0, // offset into property data to read max_length, // max length to get False, // deleted AnyPropertyType, type, format, num_items, &remaining_bytes, property); } static bool GetIntArrayProperty(XID window, const std::string& property_name, std::vector* value) { Atom type = None; int format = 0; // size in bits of each item in 'property' unsigned long num_items = 0; unsigned char* properties = NULL; int result = GetProperty(window, property_name, (~0L), // (all of them) &type, &format, &num_items, &properties); XScopedPtr scoped_properties(properties); if (result != Success) return false; if (format != 32) return false; long* int_properties = reinterpret_cast(properties); value->clear(); for (unsigned long i = 0; i < num_items; ++i) { value->push_back(static_cast(int_properties[i])); } return true; } class ScreenSaverPrivate { Q_DECLARE_TR_FUNCTIONS(UKUi::ScreenSaver) Q_DECLARE_PUBLIC(ScreenSaver) ScreenSaver* const q_ptr; public: ScreenSaverPrivate(ScreenSaver *q) : q_ptr(q) {}; void _l_xdgProcess_finished(int, QProcess::ExitStatus); bool isScreenSaverLocked(); QPointer m_xdgProcess; }; void ScreenSaverPrivate::_l_xdgProcess_finished(int err, QProcess::ExitStatus status) { // http://portland.freedesktop.org/xdg-utils-1.1.0-rc1/scripts/xdg-screensaver Q_UNUSED(status) Q_Q(ScreenSaver); if (err == 0) emit q->activated(); else { QMessageBox *box = new QMessageBox; box->setAttribute(Qt::WA_DeleteOnClose); box->setIcon(QMessageBox::Warning); if (err == 1) { box->setWindowTitle(tr("Screen Saver Error")); box->setText(tr("An error occurred starting screensaver. " "Syntax error in xdg-screensaver arguments.")); } else if (err == 3) { box->setWindowTitle(tr("Screen Saver Activation Error")); box->setText(tr("An error occurred starting screensaver. " "Ensure you have xscreensaver installed and running.")); } else if (err == 4) { box->setWindowTitle(tr("Screen Saver Activation Error")); box->setText(tr("An error occurred starting screensaver. " "Action 'activate' failed. " "Ensure you have xscreensaver installed and running.")); } else { box->setWindowTitle(tr("Screen Saver Activation Error")); box->setText(tr("An error occurred starting screensaver. " "Unknown error - undocumented return value from xdg-screensaver: %1.") .arg(err)); } box->exec(); } emit q->done(); } bool ScreenSaverPrivate::isScreenSaverLocked() { XScreenSaverInfo *info = 0; Display *display = QX11Info::display(); XID window = DefaultRootWindow(display); info = XScreenSaverAllocInfo(); XScreenSaverQueryInfo(QX11Info::display(), window, info); const int state = info->state; XFree(info); if (state == ScreenSaverOn) return true; // Ironically, xscreensaver does not conform to the XScreenSaver protocol, so // info.state == ScreenSaverOff or info.state == ScreenSaverDisabled does not // necessarily mean that a screensaver is not active, so add a special check // for xscreensaver. XAtom lock_atom = XInternAtom(display, "LOCK", false); std::vector atom_properties; if (GetIntArrayProperty(window, "_SCREENSAVER_STATUS", &atom_properties) && atom_properties.size() > 0) { if (atom_properties[0] == static_cast(lock_atom)) return true; } return false; } ScreenSaver::ScreenSaver(QObject * parent) : QObject(parent), d_ptr(new ScreenSaverPrivate(this)) { Q_D(ScreenSaver); d->m_xdgProcess = new QProcess(this); connect(d->m_xdgProcess, QOverload::of(&QProcess::finished), [=](int exitCode, QProcess::ExitStatus exitStatus){ d->_l_xdgProcess_finished(exitCode, exitStatus); }); } ScreenSaver::~ScreenSaver() { delete d_ptr; } QList ScreenSaver::availableActions() { QList ret; QAction * act; act = new QAction(XdgIcon::fromTheme(QL1S("system-lock-screen"), QL1S("lock")), tr("Lock Screen"), this); connect(act, &QAction::triggered, this, &ScreenSaver::lockScreen); ret.append(act); return ret; } void ScreenSaver::lockScreen() { Q_D(ScreenSaver); if (!d->isScreenSaverLocked()) d->m_xdgProcess->start(QL1S("xdg-screensaver"), QStringList() << QL1S("lock")); } } // namespace UKUi #include "moc_ukuiscreensaver.cpp" ukui-panel/panel/common/ukuitranslator.cpp0000644000175000017500000001206713633355350017746 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2013 LXQt team * Authors: * Alexander Sokoloff Luís Pereira * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuitranslator.h" #include #include #include #include #include #include #include #include #include using namespace UKUi; bool translate(const QString &name, const QString &owner = QString()); /************************************************ ************************************************/ QStringList *getSearchPaths() { static QStringList *searchPath = 0; if (searchPath == 0) { searchPath = new QStringList(); *searchPath << XdgDirs::dataDirs(QL1C('/') + QL1S(UKUI_RELATIVE_SHARE_TRANSLATIONS_DIR)); *searchPath << QL1S(UKUI_SHARE_TRANSLATIONS_DIR); searchPath->removeDuplicates(); } return searchPath; } /************************************************ ************************************************/ QStringList UKUi::Translator::translationSearchPaths() { return *(getSearchPaths()); } /************************************************ ************************************************/ void Translator::setTranslationSearchPaths(const QStringList &paths) { QStringList *p = getSearchPaths(); p->clear(); *p << paths; } /************************************************ ************************************************/ bool translate(const QString &name, const QString &owner) { const QString locale = QLocale::system().name(); QTranslator *appTranslator = new QTranslator(qApp); QStringList *paths = getSearchPaths(); for(const QString &path : qAsConst(*paths)) { QStringList subPaths; if (!owner.isEmpty()) { subPaths << path + QL1C('/') + owner + QL1C('/') + name; } else { subPaths << path + QL1C('/') + name; subPaths << path; } for(const QString &p : qAsConst(subPaths)) { if (appTranslator->load(name + QL1C('_') + locale, p)) { QCoreApplication::installTranslator(appTranslator); return true; } else if (locale == QLatin1String("C") || locale.startsWith(QLatin1String("en"))) { // English is the default. Even if there isn't an translation // file, we return true. It's translated anyway. delete appTranslator; return true; } } } // If we got here, no translation was loaded. appTranslator has no use. delete appTranslator; return false; } /************************************************ ************************************************/ bool Translator::translateApplication(const QString &applicationName) { const QString locale = QLocale::system().name(); QTranslator *qtTranslator = new QTranslator(qApp); if (qtTranslator->load(QL1S("qt_") + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { qApp->installTranslator(qtTranslator); } else { delete qtTranslator; } if (!applicationName.isEmpty()) return translate(applicationName); else return translate(QFileInfo(QCoreApplication::applicationFilePath()).baseName()); } /************************************************ ************************************************/ bool Translator::translateLibrary(const QString &libraryName) { static QSet loadedLibs; if (loadedLibs.contains(libraryName)) return true; loadedLibs.insert(libraryName); return translate(libraryName); } bool Translator::translatePlugin(const QString &pluginName, const QString& type) { static QSet loadedPlugins; const QString fullName = type % QL1C('/') % pluginName; if (loadedPlugins.contains(fullName)) return true; loadedPlugins.insert(pluginName); return translate(pluginName, type); } static void loadSelfTranslation() { Translator::translateLibrary(QLatin1String("libukui")); } Q_COREAPP_STARTUP_FUNCTION(loadSelfTranslation) ukui-panel/panel/common/ukuiapplication.h0000644000175000017500000000523713632320722017520 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012-2013 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIAPPLICATION_H #define UKUIAPPLICATION_H #include #include #include "ukuiglobals.h" namespace UKUi { /*! \brief UKUi wrapper around QApplication. * It loads various UKUi related stuff by default (window icon, icon theme...) * * \note This wrapper is intended to be used only inside UKUi project. Using it * in external application will automatically require linking to various * UKUi libraries. * */ class UKUI_API Application : public QApplication { Q_OBJECT public: /*! Construct a UKUi application object. * \param argc standard argc as in QApplication * \param argv standard argv as in QApplication */ Application(int &argc, char **argv); /*! Construct a UKUi application object. * \param argc standard argc as in QApplication * \param argv standard argv as in QApplication * \param handleQuitSignals flag if signals SIGINT, SIGTERM, SIGHUP should be handled internaly (\sa quit() application) */ Application(int &argc, char **argv, bool handleQuitSignals); virtual ~Application() {} /*! Install UNIX signal handler for signals defined in \param signalList * Upon receiving of any of this signals the \sa unixSignal signal is emitted */ void listenToUnixSignals(QList const & signolList); private slots: void updateTheme(); signals: void themeChanged(); /*! Signal is emitted upon receival of registered unix signal * \param signo the received unix signal number */ void unixSignal(int signo); }; #if defined(ukuiApp) #undef ukuiApp #endif #define ukuiApp (static_cast(qApp)) } // namespace UKUi #endif // UKUIAPPLICATION_H ukui-panel/panel/common/ukuiautostartentry.cpp0000644000175000017500000000623513632320722020657 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright (C) 2012 Alec Moskvin * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuiautostartentry.h" #include #include #include using namespace UKUi; AutostartEntry::AutostartEntry() : mLocalState(StateNone), mSystem(false) { } AutostartEntry::AutostartEntry(const QString& name): mLocalState(StateNone), mSystem(false) { const QStringList& dirs = XdgDirs::autostartDirs(); for (const QString& dir : dirs) { const QString path = QString::fromLatin1("%1/%2").arg(dir, name); if (QFile(path).exists()) { mSystemFile.load(path); mSystem = true; break; } } const QString path = QString::fromLatin1("%1/%2").arg(XdgDirs::autostartHome(), name); if (QFile(path).exists()) { mLocalFile.load(path); mLocalState = StateExists; } } void AutostartEntry::setFile(const XdgDesktopFile& file) { const bool local = isLocal(); if (mSystem && local && file == mSystemFile) { removeLocal(); } else { if (local) mLocalState = StateModified; else mLocalState = StateTransient; mLocalFile = file; } } bool AutostartEntry::removeLocal() { if (!isLocal()) return false; if (mLocalState == StateTransient) mLocalState = StateNone; else mLocalState = StateDeleted; return !mSystem; } const XdgDesktopFile& AutostartEntry::file() const { return isLocal() ? mLocalFile : mSystemFile; } QString AutostartEntry::name() const { return QFileInfo(file().fileName()).fileName(); } void AutostartEntry::setEnabled(bool enable) { XdgDesktopFile f = file(); if (enable) f.removeEntry(QL1S("Hidden")); else f.setValue(QL1S("Hidden"), true); setFile(f); } bool AutostartEntry::isEnabled() const { return !isEmpty() && !file().value(QL1S("Hidden"), false).toBool(); } bool AutostartEntry::commit() { if (mLocalState == StateDeleted) { mLocalState = StateNone; return QFile::remove(mLocalFile.fileName()); } else if (mLocalState == StateModified || mLocalState == StateTransient) { mLocalState = StateExists; return mLocalFile.save(XdgAutoStart::localPath(mLocalFile)); } return true; } ukui-panel/panel/common/ukuinotification_p.h0000644000175000017500000000347313632320722020222 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright (C) 2012 Alec Moskvin * Copyright (C) 2019 minglequn * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUINOTIFICATION_P_H #define UKUINOTIFICATION_P_H #include "ukuinotification.h" #include "notifications_interface.h" namespace UKUi { class NotificationPrivate : public QObject { Q_OBJECT public: NotificationPrivate(const QString& summary, Notification* parent); ~NotificationPrivate(); void update(); void close(); void setActions(QStringList actions, int defaultAction); const Notification::ServerInfo serverInfo(); public slots: void handleAction(uint id, QString key); void notificationClosed(uint, uint); private: OrgFreedesktopNotificationsInterface* mInterface; uint mId; QString mSummary; QString mBody; QString mIconName; QStringList mActions; QVariantMap mHints; int mDefaultAction; int mTimeout; Notification* const q_ptr; Q_DECLARE_PUBLIC(Notification) }; } // namespace UKUi #endif // UKUINOTIFICATION_P_H ukui-panel/panel/common/ukuisingleapplication.h0000644000175000017500000001117513633355350020726 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2014 LXQt team * Authors: * Luís Pereira * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUISINGLEAPPLICATION_H #define UKUISINGLEAPPLICATION_H #include "ukuiapplication.h" class QWidget; namespace UKUi { /*! \class SingleApplication * \brief The SingleApplication class provides an single instance Application. * * This class allows the user to create applications where only one instance * is allowed to be running at an given time. If the user tries to launch * another instance, the already running instance will be activated instead. * * The user has to set the activation window with setActivationWindow. If it * doesn't the second instance will quietly exit without activating the first * instance window. In any case only one instance is allowed. * * These classes depend on D-Bus and KF5::WindowSystem * * \code * * // Original code * int main(int argc, char **argv) * { * UKUi::Application app(argc, argv); * * MainWidget w; * w.show(); * * return app.exec(); * } * * // Using the library * int main(int argc, char **argv) * { * UKUi::SingleApplication app(argc, argv); * * MainWidget w; * app.setActivationWindow(&w); * w.show(); * * return app.exec(); * } * \endcode * \sa SingleApplication */ class UKUI_API SingleApplication : public Application { Q_OBJECT public: /*! * \brief Options to control the D-Bus failure related application behaviour * * By default (ExitOnDBusFailure) if an instance can't connect to the D-Bus * session bus, that instance calls ::exit(1). Not even the first instance * will run. Connecting to the D-Bus session bus is an condition to * guarantee that only one instance will run. * * If an user wants to allow an application to run without D-Bus, it must * use the NoExitOnDBusFailure option. * * ExitOnDBusFailure is the default. */ enum StartOptions { /** Exit if the connection to the D-Bus session bus fails. * It's the default */ ExitOnDBusFailure, /** Don't exit if the connection to the D-Bus session bus fails.*/ NoExitOnDBusFailure }; Q_ENUM(StartOptions) /*! * \brief Construct a UKUi SingleApplication object. * \param argc standard argc as in QApplication * \param argv standard argv as in QApplication * \param options Control the on D-Bus failure application behaviour * * \sa StartOptions. */ SingleApplication(int &argc, char **argv, StartOptions options = ExitOnDBusFailure); virtual ~SingleApplication(); /*! * \brief Sets the activation window. * \param w activation window. * * Sets the activation window of this application to w. The activation * window is the widget that will be activated by \a activateWindow(). * * \sa activationWindow() \sa activateWindow(); */ void setActivationWindow(QWidget *w); /*! * \brief Gets the current activation window. * \return The current activation window. * * \sa setActivationWindow(); */ QWidget *activationWindow() const; public Q_SLOTS: /*! * \brief Activates this application activation window. * * Changes to the desktop where this applications is. It then de-minimizes, * raises and activates the application's activation window. * If no activation window has been set, this function does nothing. * * \sa setActivationWindow(); */ void activateWindow(); private: QWidget *mActivationWindow; }; #if defined(ukuiSingleApp) #undef ukuiSingleApp #endif #define ukuiSingleApp (static_cast(qApp)) } // namespace UKUi #endif // UKUISINGLEAPPLICATION_H ukui-panel/panel/common/ukuiplugininfo.h0000644000175000017500000000763613632320722017374 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPLUGININFO_H #define UKUIPLUGININFO_H #include #include #include #include #include #include "ukuiglobals.h" #include class QLibrary; namespace UKUi { /*! Every plugin needs a .desktop file that describes it. The basename of this file must be same as the basename of the plugin library. ukuipanel_clock2.desktop file [Desktop Entry] Type=Service ServiceTypes=UKUiPanel/Plugin Name=Clock Comment=Clock and calendar PluginInfo class gives the interface for reading the values from the plugin .desktop file. This is a pure virtual class, you must implement libraryDir(), translationDir(), and instance() methods. */ class UKUI_API PluginInfo: public XdgDesktopFile { public: /// Constructs a PluginInfo object for accessing the info stored in the .desktop file. explicit PluginInfo(); //! Reimplemented from XdgDesktopFile. virtual bool load(const QString& fileName); //! Reimplemented from XdgDesktopFile. //PluginInfo& operator=(const PluginInfo& other); //! Returns identification string of this plugin, identified plugin type. Now id is part of the filename. QString id() const { return mId; } //! This function is provided for convenience. It's equivalent to calling value("ServiceTypes").toString(). QString serviceType() const { return value(QL1S("ServiceTypes")).toString(); } //! Reimplemented from XdgDesktopFile. virtual bool isValid() const; /*! Loads the library and returns QLibrary object if the library was loaded successfully; otherwise returns 0. @parm libDir directory where placed the plugin .so file. */ QLibrary* loadLibrary(const QString& libDir) const; /*! Returns a list of PluginInfo objects for the matched files in the directories. @param desktopFilesDirs - scanned directories names. @param serviceType - type of the plugin, for example "UKUiPanel/Plugin". @param nameFilter - wildcard filter that understands * and ? wildcards. If the same filename is located under multiple directories only the first file should be used. */ static QList search(const QStringList& desktopFilesDirs, const QString& serviceType, const QString& nameFilter = QLatin1String("*")); /// This function is provided for convenience. It's equivalent to new calling search(QString(desktopFilesDir), serviceType, nameFilter) static QList search(const QString& desktopFilesDir, const QString& serviceType, const QString& nameFilter = QLatin1String("*")); private: QString mId; }; typedef QList PluginInfoList; } // namespace UKUi QDebug operator<<(QDebug dbg, const UKUi::PluginInfo& pi); QDebug operator<<(QDebug dbg, const UKUi::PluginInfo* const pi); QDebug operator<<(QDebug dbg, const UKUi::PluginInfoList& list); QDebug operator<<(QDebug dbg, const UKUi::PluginInfoList* const pluginInfoList); #endif // UKUIPLUGININFO_H ukui-panel/panel/common/ukuiconfigdialog.h0000644000175000017500000000614013632320722017634 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright (C) 2012 Alec Moskvin * Copyright (C) 2019 minglequn * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUICONFIGDIALOG_H #define UKUICONFIGDIALOG_H #include #include #include #include #include "ukuiglobals.h" namespace Ui { class ConfigDialog; } namespace UKUi { class Settings; class ConfigDialogPrivate; class UKUI_API ConfigDialog : public QDialog { Q_OBJECT Q_DECLARE_PRIVATE(ConfigDialog) public: explicit ConfigDialog(const QString& title, Settings* settings, QWidget* parent = 0); ~ConfigDialog(); /*! * Sets buttons in button bar */ void setButtons(QDialogButtonBox::StandardButtons buttons); /*! * Enable/disable a standard button if it exists */ void enableButton(QDialogButtonBox::StandardButton which, bool enable); /*! * Add a page to the configure dialog */ void addPage(QWidget* page, const QString& name, const QString& iconName = QLatin1String("application-x-executable")); /*! * Add a page to the configure dialog, attempting several alternative icons to find one in the theme */ void addPage(QWidget* page, const QString& name, const QStringList& iconNames); /*! * Show page containing the widget in parameter */ void showPage(QWidget *page); /*! * \brief Shows the given page * \param name The page to be shown. */ void showPage(const QString &name); signals: /*! * This signal is emitted when the user pressed the "Reset" button. * Settings should be re-read and the widgets should be set accordingly. */ void reset(); /*! * This is emitted whenever the window is closed and settings need to be saved. * It is only necessary if additional actions need to be performed - Settings are handled automatically. */ void save(); /*! * This is emitted when some button in the buttonbar is clicked. */ void clicked(QDialogButtonBox::StandardButton); protected: Settings* mSettings; virtual bool event(QEvent * event) override; virtual void closeEvent(QCloseEvent* event) override; private: Q_DISABLE_COPY(ConfigDialog) QScopedPointer const d_ptr; }; } // namespace UKUi #endif // UKUICONFIGDIALOG_H ukui-panel/panel/common/CMakeLists.txt0000644000175000017500000002150613632320722016703 0ustar fengfeng set(UKUIBT_MINIMUM_VERSION "0.6.0") set(KF5_MINIMUM_VERSION "5.36.0") set(QT_MINIMUM_VERSION "5.7.1") set(QTXDG_MINIMUM_VERSION "3.3.1") # Major UKUi Version, belong to all components set(UKUI_MAJOR_VERSION 0) # Minor UKUi Version, belong to all components set(UKUI_MINOR_VERSION 14) # # Patch Version, belong *only* to the component # UKUi is 0.13 - libukui is at patch version 0 # The official UKUi version will follow libukui. # # In a perfect world all components would have the same major- and minor- and # patch-version as libukui - in real life it will be fine if every component # has it's own patch version within a major/minor life cyle. # set(UKUI_PATCH_VERSION 1) set(UKUI_VERSION ${UKUI_MAJOR_VERSION}.${UKUI_MINOR_VERSION}.${UKUI_PATCH_VERSION}) option(UPDATE_TRANSLATIONS "Update source translation translations/*.ts files" OFF) #find_package(ukui-build-tools ${UKUIBT_MINIMUM_VERSION} REQUIRED) #find_package(Qt5 ${QT_MINIMUM_VERSION} CONFIG REQUIRED Widgets DBus X11Extras LinguistTools) #find_package(Qt5Xdg ${QTXDG_MINIMUM_VERSION} REQUIRED) #find_package(KF5WindowSystem ${KF5_MINIMUM_VERSION} REQUIRED) #find_package(PolkitQt5-1 REQUIRED) #find_package(X11 REQUIRED) message(STATUS "Building ${PROJECT_NAME} with Qt ${Qt5Core_VERSION}") include(CMakePackageConfigHelpers) include(GNUInstallDirs) # Standard directories for installation #add_subdirectory(ukuibacklight/linux_backend/driver) set(UKUI_PKG_CONFIG_DESCRIPTION "Shared library for UKUi applications") set(HEADERS ukuihtmldelegate.h ukuisettings.h ukuiplugininfo.h ukuipowermanager.h ukuiscreensaver.h ukuiapplication.h ukuisingleapplication.h ukuitranslator.h ukuiprogramfinder.h configdialog/ukuiconfigdialog.h configdialog/ukuiconfigdialogcmdlineoptions.h configdialog/ukuipageselectwidget.h ukuipower/ukuipower.h ukuinotification.h ukuiautostartentry.h ukuigridlayout.h ukuirotatedwidget.h ukuiglobals.h ukuibacklight.h #ukuibacklight/virtual_backend.h #ukuibacklight/linux_backend/linuxbackend.h ) set(PUBLIC_CLASSES HtmlDelegate Settings PluginInfo PowerManager ScreenSaver Application SingleApplication Translator ProgramFinder ConfigDialog ConfigDialogCmdLineOptions PageSelectWidget Power Notification AutostartEntry GridLayout RotatedWidget Globals Backlight ) set(SOURCES ukuihtmldelegate.cpp ukuiplugininfo.cpp ukuipowermanager.cpp ukuisettings.cpp ukuiscreensaver.cpp ukuiapplication.cpp ukuisingleapplication.cpp ukuitranslator.cpp ukuiprogramfinder.cpp configdialog/ukuiconfigdialog.cpp configdialog/ukuiconfigdialogcmdlineoptions.cpp configdialog/ukuipageselectwidget.cpp ukuipower/ukuipower.cpp ukuipower/ukuipowerproviders.cpp ukuiautostartentry.cpp ukuinotification.cpp ukuigridlayout.cpp ukuirotatedwidget.cpp ukuibacklight.cpp ukuibacklight/virtual_backend.cpp ukuibacklight/linux_backend/linuxbackend.cpp ) set(MOCS ukuihtmldelegate.h ukuipowermanager.h ukuisettings.h ukuiscreensaver.h ukuiapplication.h ukuibacklight.h configdialog/ukuiconfigdialog.h configdialog/ukuiconfigdialog_p.h configdialog/ukuipageselectwidget.h ukuinotification.h ukuinotification_p.h ukuipower/ukuipower.h ukuipower/ukuipowerproviders.h ukuigridlayout.h ukuirotatedwidget.h ukuibacklight/virtual_backend.h ukuibacklight/linux_backend/linuxbackend.h ) set(FORMS configdialog/ukuiconfigdialog.ui ) set(POLKIT_FILES "${CMAKE_CURRENT_BINARY_DIR}/org.ukui.backlight.pkexec.policy" ) # Build Polkit file configure_file ( polkit/org.ukui.backlight.pkexec.policy.in "${CMAKE_CURRENT_BINARY_DIR}/org.ukui.backlight.pkexec.policy" ) file(GLOB UKUI_CONFIG_FILES resources/*.conf) QT5_ADD_DBUS_INTERFACE(DBUS_INTERFACE_SRCS dbus/org.freedesktop.Notifications.xml notifications_interface ) QT5_ADD_DBUS_ADAPTOR(DBUS_ADAPTOR_SRCS dbus/org.ukui.SingleApplication.xml ukuisingleapplication.h UKUi::SingleApplication ) set_property(SOURCE ${DBUS_INTERFACE_SRCS} ${DBUS_ADAPTOR_SRCS} PROPERTY SKIP_AUTOGEN ON) list(APPEND SOURCES "${DBUS_INTERFACE_SRCS}" "${DBUS_ADAPTOR_SRCS}") # KF5WindowSystem is missing here. KF5WindowSystem doesn't provide an .pc file. set(UKUI_PKG_CONFIG_REQUIRES "Qt5Xdg >= ${QTXDG_MINIMUM_VERSION}, Qt5Widgets >= ${QT_MINIMUM_VERSION}, Qt5Xml >= ${QT_MINIMUM_VERSION}, Qt5DBus >= ${QT_MINIMUM_VERSION}, Qt5X11Extras >= ${QT_MINIMUM_VERSION}") # Standard directories for installation include(../../cmake/ukui-build-tools/modules/UKUiPreventInSourceBuilds.cmake) include(../../cmake/ukui-build-tools/modules/UKUiCompilerSettings.cmake) include(../../cmake/ukui-build-tools/modules/UKUiCreatePkgConfigFile.cmake) include(../../cmake/ukui-build-tools/modules/UKUiCreatePortableHeaders.cmake) include(../../cmake/ukui-build-tools/modules/UKUiConfigVars.cmake) set(UKUI_INTREE_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/include") set(UKUI_INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}/${UKUI_LIBRARY_NAME}") set(UKUI_INSTALL_CMAKE_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/cmake") ## Translations #include(../cmake/ukui-build-tools/modules/UKUiTranslateTs.cmake) #ukui_translate_ts(QM_FILES # UPDATE_TRANSLATIONS # ${UPDATE_TRANSLATIONS} # SOURCES # ${SRCS} # ${FORMS} # INSTALL_DIR # "${UKUI_TRANSLATIONS_DIR}/${PROJECT_NAME}" #) message(STATUS "") message(STATUS "libukui version: ${UKUI_VERSION}") message(STATUS "") # Copy public headers foreach(h ${HEADERS}) get_filename_component(bh ${h} NAME) configure_file(${h} "${UKUI_INTREE_INCLUDE_DIR}/UKUi/${bh}" COPYONLY) endforeach() # Create the portable headers ukui_create_portable_headers(INTREE_PORTABLE_HEADERS NAME_PREFIX "ukui" OUTPUT_DIR "${UKUI_INTREE_INCLUDE_DIR}/UKUi" HEADER_NAMES ${PUBLIC_CLASSES} ) #check_portable_headers(H_FILES ${PUB_HDRS} LINKS "${INTREE_PORTABLE_HEADERS}") #************************************************ # Create in-tree build infrastructure #************************************************ set(CFG_UKUI_TARGETS_FILE "${UKUI_INTREE_TARGETS_FILE}") configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ukui-config.cmake.in" "${CMAKE_BINARY_DIR}/${UKUI_LIBRARY_NAME}-config.cmake" INSTALL_DESTINATION "neverland" # required, altough we don't install it ) #************************************************ # Create installable build infrastructure #************************************************ set(CFG_UKUI_TARGETS_FILE "${UKUI_INSTALL_CMAKE_DIR}/${UKUI_LIBRARY_NAME}/${UKUI_LIBRARY_NAME}-targets.cmake") configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ukui-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/install/${UKUI_LIBRARY_NAME}-config.cmake" INSTALL_DESTINATION "${UKUI_INSTALL_CMAKE_DIR}/${UKUI_LIBRARY_NAME}" ) write_basic_package_version_file( "${CMAKE_BINARY_DIR}/${UKUI_LIBRARY_NAME}-config-version.cmake" VERSION ${UKUI_VERSION} COMPATIBILITY AnyNewerVersion ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/install/${UKUI_LIBRARY_NAME}-config.cmake" "${CMAKE_BINARY_DIR}/${UKUI_LIBRARY_NAME}-config-version.cmake" DESTINATION "${UKUI_INSTALL_CMAKE_DIR}/${UKUI_LIBRARY_NAME}" COMPONENT Devel ) #install(EXPORT # ${UKUI_LIBRARY_NAME}-targets # DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${UKUI_LIBRARY_NAME}" # COMPONENT Devel #) if (Qt5Core_VERSION VERSION_LESS "5.9.0") if (NOT DEFINED WITH_XDG_DIRS_FALLBACK) set(WITH_XDG_DIRS_FALLBACK ON) endif () elseif (WITH_XDG_DIRS_FALLBACK) set(WITH_XDG_DIRS_FALLBACK OFF) message(WARNING "Disabling requested WITH_XDG_DIRS_FALLBACK workaround, as proper implementation is in Qt from v5.9.0") endif () if (WITH_XDG_DIRS_FALLBACK) message(STATUS "Building with homemade QSettings XDG fallback workaround") target_compile_definitions(${UKUI_LIBRARY_NAME} PRIVATE "WITH_XDG_DIRS_FALLBACK" ) endif () #install(FILES # ${PUB_HDRS} # DESTINATION "${UKUI_INSTALL_INCLUDE_DIR}/UKUi" # COMPONENT Devel #) #install(FILES # ${INTREE_PORTABLE_HEADERS} # DESTINATION "${UKUI_INSTALL_INCLUDE_DIR}/UKUi" # COMPONENT Devel #) #install(FILES ${UKUI_CONFIG_FILES} # DESTINATION "${CMAKE_INSTALL_FULL_DATADIR}/ukui" # COMPONENT Runtime #) #install(FILES ${POLKIT_FILES} DESTINATION "${POLKITQT-1_POLICY_FILES_INSTALL_DIR}") #************************************************ # Create and install pkgconfig file #************************************************ ukui_create_pkgconfig_file( PACKAGE_NAME ${UKUI_LIBRARY_NAME} DESCRIPTIVE_NAME ${UKUI_LIBRARY_NAME} DESCRIPTION ${UKUI_PKG_CONFIG_DESCRIPTION} INCLUDEDIRS ${UKUI_LIBRARY_NAME} REQUIRES ${UKUI_PKG_CONFIG_REQUIRES} VERSION ${UKUI_VERSION} INSTALL ) #************************************************ ukui-panel/panel/common/ukuibacklight.cpp0000644000175000017500000000322513632320722017473 0ustar fengfeng/* * Copyright (C) 2016 P.L. Lucas * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "ukuibacklight.h" #include "ukuibacklight/virtual_backend.h" #include "ukuibacklight/linux_backend/linuxbackend.h" namespace UKUi { Backlight::Backlight(QObject *parent):QObject(parent) { m_backend = (VirtualBackEnd *) new LinuxBackend(this); connect(m_backend, &VirtualBackEnd::backlightChanged, this, &Backlight::backlightChangedSlot); } Backlight::~Backlight() { delete m_backend; } int Backlight::getBacklight() { return m_backend->getBacklight(); } int Backlight::getMaxBacklight() { return m_backend->getMaxBacklight(); } bool Backlight::isBacklightAvailable() { return m_backend->isBacklightAvailable(); } bool Backlight::isBacklightOff() { return m_backend->isBacklightOff(); } void Backlight::setBacklight(int value) { m_backend->setBacklight(value); } void Backlight::backlightChangedSlot(int value) { emit backlightChanged(value); } } // namespace UKUi ukui-panel/panel/common/ukuipowermanager.cpp0000644000175000017500000001427513632320722020241 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * * Copyright: 2019-2020 UKUI team * Authors: * minglequn * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuipowermanager.h" #include "ukuipower/ukuipower.h" #include #include #include #include #include #include "ukuitranslator.h" #include "ukuiglobals.h" #include "ukuisettings.h" #include namespace UKUi { class UKUI_API MessageBox: public QMessageBox { Q_DECLARE_TR_FUNCTIONS(UKUi::MessageBox) public: explicit MessageBox(QWidget *parent = 0): QMessageBox(parent) {} static QWidget *parentWidget() { const QWidgetList widgets = QApplication::topLevelWidgets(); if (widgets.count()) return widgets.at(0); else return 0; } static bool question(const QString& title, const QString& text) { MessageBox msgBox(parentWidget()); msgBox.setWindowTitle(title); msgBox.setText(text); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); return (msgBox.exec() == QMessageBox::Yes); } static void warning(const QString& title, const QString& text) { Q_UNUSED(title) Q_UNUSED(text) QMessageBox::warning(parentWidget(), tr("UKUi Power Manager Error"), tr("Hibernate failed.")); } protected: virtual void resizeEvent(QResizeEvent* event) { Q_UNUSED(event) const QRect screen = QApplication::desktop()->screenGeometry(); move((screen.width() - this->width()) / 2, (screen.height() - this->height()) / 2); } }; PowerManager::PowerManager(QObject * parent, bool skipWarning) : QObject(parent), m_skipWarning(skipWarning) { m_power = new Power(this); // connect(m_power, SIGNAL(suspendFail()), this, SLOT(suspendFailed())); // connect(m_power, SIGNAL(hibernateFail()), this, SLOT(hibernateFailed())); // connect(m_power, SIGNAL(monitoring(const QString &)), // this, SLOT(monitoring(const QString&))); QString sessionConfig(QFile::decodeName(qgetenv("UKUI_SESSION_CONFIG"))); Settings settings(sessionConfig.isEmpty() ? QL1S("session") : sessionConfig); m_skipWarning = settings.value(QL1S("leave_confirmation")).toBool() ? false : true; } PowerManager::~PowerManager() { // delete m_power; } QList PowerManager::availableActions() { QList ret; QAction * act; // TODO/FIXME: icons if (m_power->canHibernate()) { act = new QAction(XdgIcon::fromTheme(QL1S("system-suspend-hibernate")), tr("Hibernate"), this); connect(act, &QAction::triggered, this, &PowerManager::hibernate); ret.append(act); } if (m_power->canSuspend()) { act = new QAction(XdgIcon::fromTheme(QL1S("system-suspend")), tr("Suspend"), this); connect(act, &QAction::triggered, this, &PowerManager::suspend); ret.append(act); } if (m_power->canReboot()) { act = new QAction(XdgIcon::fromTheme(QL1S("system-reboot")), tr("Reboot"), this); connect(act, &QAction::triggered, this, &PowerManager::reboot); ret.append(act); } if (m_power->canShutdown()) { act = new QAction(XdgIcon::fromTheme(QL1S("system-shutdown")), tr("Shutdown"), this); connect(act, &QAction::triggered, this, &PowerManager::shutdown); ret.append(act); } if (m_power->canLogout()) { act = new QAction(XdgIcon::fromTheme(QL1S("system-log-out")), tr("Logout"), this); connect(act, &QAction::triggered, this, &PowerManager::logout); ret.append(act); } return ret; } void PowerManager::suspend() { if (m_skipWarning || MessageBox::question(tr("UKUi Session Suspend"), tr("Do you want to really suspend your computer?

Suspends the computer into a low power state. System state is not preserved if the power is lost."))) { m_power->suspend(); } } void PowerManager::hibernate() { if (m_skipWarning || MessageBox::question(tr("UKUi Session Hibernate"), tr("Do you want to really hibernate your computer?

Hibernates the computer into a low power state. System state is preserved if the power is lost."))) { m_power->hibernate(); } } void PowerManager::reboot() { if (m_skipWarning || MessageBox::question(tr("UKUi Session Reboot"), tr("Do you want to really restart your computer? All unsaved work will be lost..."))) { m_power->reboot(); } } void PowerManager::shutdown() { if (m_skipWarning || MessageBox::question(tr("UKUi Session Shutdown"), tr("Do you want to really switch off your computer? All unsaved work will be lost..."))) { m_power->shutdown(); } } void PowerManager::logout() { if (m_skipWarning || MessageBox::question(tr("UKUi Session Logout"), tr("Do you want to really logout? All unsaved work will be lost..."))) { m_power->logout(); } } void PowerManager::hibernateFailed() { MessageBox::warning(tr("UKUi Power Manager Error"), tr("Hibernate failed.")); } void PowerManager::suspendFailed() { MessageBox::warning(tr("UKUi Power Manager Error"), tr("Suspend failed.")); } } // namespace UKUi ukui-panel/panel/common/polkit/0000755000175000017500000000000013632320722015441 5ustar fengfengukui-panel/panel/common/polkit/org.ukui.backlight.pkexec.policy.in0000644000175000017500000000121713632320722024240 0ustar fengfeng Authentication is required to Change Brightness battery no no yes ${CMAKE_INSTALL_PREFIX}/bin/ukui-backlight_backend ukui-panel/panel/common/ukuisettings.h0000644000175000017500000001522713632320722017055 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUISETTINGS_H #define UKUISETTINGS_H #include #include #include #include "ukuiglobals.h" class QEvent; namespace UKUi { class SettingsPrivate; class GlobalSettings; /*! \brief User settings handling */ class UKUI_API Settings : public QSettings { Q_OBJECT public: /*! \brief Constructs a Settings object for accessing settings of the module called module, and with parent parent. Settings can be accessed using the standard interface provided by QSettings, but it also provides some convenience functions and signals. \param module a base name of the config file. It's a name without the extension. For example: if you want to open settings for panel create it as Settings("panel"). The function will create all parent directories necessary to create the file. \param parent It's no need to delete this class manually if it's set. */ explicit Settings(const QString& module, QObject* parent = 0); //explicit Settings(QObject* parent=0); explicit Settings(const QSettings* parentSettings, const QString& subGroup, QObject* parent=0); explicit Settings(const QSettings& parentSettings, const QString& subGroup, QObject* parent=0); Settings(const QString &fileName, QSettings::Format format, QObject *parent = 0); ~Settings(); static const GlobalSettings *globalSettings(); /*! Returns the localized value for key. In the desktop file keys may be postfixed by [LOCALE]. If the localized value doesn't exist, returns non lokalized value. If non localized value doesn't exist, returns defaultValue. LOCALE must be of the form lang_COUNTRY.ENCODING@MODIFIER, where _COUNTRY, .ENCODING, and @MODIFIER may be omitted. If no default value is specified, a default QVariant is returned. */ QVariant localizedValue(const QString& key, const QVariant& defaultValue = QVariant()) const; /*! Sets the value of setting key to value. If a localized version of the key already exists, the previous value is overwritten. Otherwise, it overwrites the the un-localized version. */ void setLocalizedValue(const QString &key, const QVariant &value); signals: /*! /brief signal for backward compatibility (emitted whenever settingsChangedFromExternal() or settingsChangedByApp() is emitted) */ void settingsChanged(); /*! /brief signal emitted when the settings file is changed by external application */ void settingsChangedFromExternal(); /*! /brief signal emitted when any setting is changed by this object */ void settingsChangedByApp(); protected: bool event(QEvent *event); protected slots: /*! Called when the config file is changed */ virtual void fileChanged(); private slots: void _fileChanged(QString path); private: void addWatchedFile(QString const & path); private: Q_DISABLE_COPY(Settings) SettingsPrivate* const d_ptr; Q_DECLARE_PRIVATE(Settings) }; class UKUiThemeData; /*! \brief QSS theme handling */ class UKUI_API UKUiTheme { public: /// Constructs a null theme. UKUiTheme(); /*! Constructs an theme from the dir with the given path. If path not absolute (i.e. the theme name only) the relevant dir must be found relative to the $XDG_DATA_HOME + $XDG_DATA_DIRS directories. */ UKUiTheme(const QString &path); /// Constructs a copy of other. This is very fast. UKUiTheme(const UKUiTheme &other); UKUiTheme& operator=(const UKUiTheme &other); ~UKUiTheme(); /// Returns the name of the theme. QString name() const; QString path() const; QString previewImage() const; /// Returns true if this theme is valid; otherwise returns false. bool isValid() const; /*! \brief Returns StyleSheet text (not file name, but real text) of the module called module. Paths in url() C/QSS functions are parsed to be real values for the theme, relative to full path */ QString qss(const QString& module) const; /*! \brief A full path to image used as a wallpaper \param screen is an ID of the screen like in Qt. -1 means default (any) screen. Any other value greater than -1 is the exact screen (in dualhead). In themes the index starts from 1 (ix 1 means 1st screen). \retval QString a file name (including path). */ QString desktopBackground(int screen=-1) const; /// Returns the current ukui theme. static const UKUiTheme ¤tTheme(); /// Returns the all themes found in the system. static QList allThemes(); private: static UKUiTheme* mInstance; QSharedDataPointer d; }; /*! A global pointer referring to the unique UKUiTheme object. It is equivalent to the pointer returned by the UKUiTheme::instance() function. Only one theme object can be created. !*/ #define ukuiTheme UKUiTheme::currentTheme() class UKUI_API SettingsCache { public: explicit SettingsCache(QSettings &settings); explicit SettingsCache(QSettings *settings); virtual ~SettingsCache() {} void loadFromSettings(); void loadToSettings(); private: QSettings &mSettings; QHash mCache; }; class GlobalSettingsPrivate; class GlobalSettings: public Settings { Q_OBJECT public: GlobalSettings(); ~GlobalSettings(); signals: /// Signal emitted when the icon theme has changed. void iconThemeChanged(); /// Signal emitted when the ukui theme has changed. void ukuiThemeChanged(); protected slots: void fileChanged(); private: GlobalSettingsPrivate* const d_ptr; Q_DECLARE_PRIVATE(GlobalSettings) }; } // namespace UKUi #endif // UKUISETTINGS_H ukui-panel/panel/common/ukuirotatedwidget.cpp0000644000175000017500000001636413632320722020421 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2013 Razor team * Authors: * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuirotatedwidget.h" #include #include #include #include #ifndef QT_NO_WHEELEVENT #include #endif #include using namespace UKUi; RotatedWidget::RotatedWidget(QWidget &content, QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f) , mContent(&content) , mOrigin(Qt::TopLeftCorner) , mTransferMousePressEvent(false) , mTransferMouseReleaseEvent(false) , mTransferMouseDoubleClickEvent(false) , mTransferMouseMoveEvent(false) #ifndef QT_NO_WHEELEVENT , mTransferWheelEvent(false) #endif , mTransferEnterEvent(false) , mTransferLeaveEvent(false) { mContent->setParent(this); } Qt::Corner RotatedWidget::origin() const { return mOrigin; } void RotatedWidget::setOrigin(Qt::Corner newOrigin) { if (mOrigin != newOrigin) { if (mOrigin == Qt::TopLeftCorner) mContent->hide(); mOrigin = newOrigin; adjustContentSize(); update(); if (mOrigin == Qt::TopLeftCorner) mContent->show(); } } QWidget * RotatedWidget::content() const { return mContent; } void RotatedWidget::adjustContentSize() { mContent->adjustSize(); const QSize before = size(); adjustSize(); if (before != size()) updateGeometry(); } QSize RotatedWidget::adjustedSize(QSize size) const { switch (mOrigin) { case Qt::TopLeftCorner: case Qt::BottomRightCorner: break; case Qt::TopRightCorner: case Qt::BottomLeftCorner: size.transpose(); break; } return size; } QPoint RotatedWidget::adjustedPoint(QPoint point) const { switch (mOrigin) { case Qt::TopLeftCorner: case Qt::BottomRightCorner: break; case Qt::TopRightCorner: case Qt::BottomLeftCorner: point = QPoint(point.y(), point.x()); break; } return point; } QSize RotatedWidget::minimumSizeHint() const { return adjustedSize(mContent->minimumSizeHint()); } QSize RotatedWidget::sizeHint() const { return adjustedSize(mContent->sizeHint()); } void RotatedWidget::paintEvent(QPaintEvent */*event*/) { if (mOrigin == Qt::TopLeftCorner) return; const QSize sz = mContent->size(); QPainter painter(this); QTransform transform; QPoint originPoint; switch (mOrigin) { case Qt::TopLeftCorner: // transform.rotate(0.0); // originPoint = QPoint(0.0, 0.0); break; case Qt::TopRightCorner: transform.rotate(90.0); originPoint = QPoint(0.0, -sz.height()); break; case Qt::BottomRightCorner: transform.rotate(180.0); originPoint = QPoint(-sz.width(), -sz.height()); break; case Qt::BottomLeftCorner: transform.rotate(270.0); originPoint = QPoint(-sz.width(), 0.0); break; } painter.setTransform(transform); mContent->render(&painter, originPoint, QRegion(), RenderFlags(DrawChildren)); } void RotatedWidget::mousePressEvent(QMouseEvent *event) { if (!mTransferMousePressEvent) { event->ignore(); return; } static bool cascadeCall = false; if (cascadeCall) return; cascadeCall = true; QMouseEvent contentEvent(event->type(), adjustedPoint(event->pos()), event->globalPos(), event->button(), event->buttons(), event->modifiers()); QApplication::sendEvent(mContent, &contentEvent); cascadeCall = false; } void RotatedWidget::mouseReleaseEvent(QMouseEvent *event) { if (!mTransferMouseReleaseEvent) { event->ignore(); return; } static bool cascadeCall = false; if (cascadeCall) return; cascadeCall = true; QMouseEvent contentEvent(event->type(), adjustedPoint(event->pos()), event->globalPos(), event->button(), event->buttons(), event->modifiers()); QApplication::sendEvent(mContent, &contentEvent); cascadeCall = false; } void RotatedWidget::mouseDoubleClickEvent(QMouseEvent *event) { if (!mTransferMouseDoubleClickEvent) { event->ignore(); return; } static bool cascadeCall = false; if (cascadeCall) return; cascadeCall = true; QMouseEvent contentEvent(event->type(), adjustedPoint(event->pos()), event->globalPos(), event->button(), event->buttons(), event->modifiers()); QApplication::sendEvent(mContent, &contentEvent); cascadeCall = false; } void RotatedWidget::mouseMoveEvent(QMouseEvent *event) { if (!mTransferMouseMoveEvent) { event->ignore(); return; } static bool cascadeCall = false; if (cascadeCall) return; cascadeCall = true; QMouseEvent contentEvent(event->type(), adjustedPoint(event->pos()), event->globalPos(), event->button(), event->buttons(), event->modifiers()); QApplication::sendEvent(mContent, &contentEvent); cascadeCall = false; } #ifndef QT_NO_WHEELEVENT void RotatedWidget::wheelEvent(QWheelEvent *event) { if (!mTransferWheelEvent) { event->ignore(); return; } static bool cascadeCall = false; if (cascadeCall) return; cascadeCall = true; QWheelEvent contentEvent(adjustedPoint(event->pos()), event->globalPos(), event->delta(), event->buttons(), event->modifiers(), event->orientation()); QApplication::sendEvent(mContent, &contentEvent); cascadeCall = false; } #endif void RotatedWidget::enterEvent(QEvent *event) { if (!mTransferEnterEvent) { event->ignore(); return; } static bool cascadeCall = false; if (cascadeCall) return; cascadeCall = true; QApplication::sendEvent(mContent, event); cascadeCall = false; } void RotatedWidget::leaveEvent(QEvent *event) { if (!mTransferLeaveEvent) { event->ignore(); return; } static bool cascadeCall = false; if (cascadeCall) return; cascadeCall = true; QApplication::sendEvent(mContent, event); cascadeCall = false; } void RotatedWidget::resizeEvent(QResizeEvent *event) { static bool cascadeCall = false; if (cascadeCall) return; cascadeCall = true; QResizeEvent contentEvent(adjustedSize(event->size()), adjustedSize(event->oldSize())); QApplication::sendEvent(mContent, &contentEvent); cascadeCall = false; } ukui-panel/panel/common/configdialog/0000755000175000017500000000000013632320722016564 5ustar fengfengukui-panel/panel/common/configdialog/ukuipageselectwidget.cpp0000644000175000017500000001375513632320722023521 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuipageselectwidget.h" #include #include #include #include #include using namespace UKUi; class PageSelectWidgetItemDelegate: public QStyledItemDelegate { public: explicit PageSelectWidgetItemDelegate(PageSelectWidget *parent = 0); QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; private: PageSelectWidget* mView; }; /************************************************ ************************************************/ PageSelectWidgetItemDelegate::PageSelectWidgetItemDelegate(PageSelectWidget *parent): QStyledItemDelegate(parent), mView(parent) { } /************************************************ ************************************************/ QSize PageSelectWidgetItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { QVariant value = index.data(Qt::SizeHintRole); if (value.isValid()) return qvariant_cast(value); //all items should have unified width QStyleOptionViewItem opt = option; initStyleOption(&opt, index); const QWidget *widget = option.widget; QStyle *style = widget ? widget->style() : QApplication::style(); QSize size = style->sizeFromContents(QStyle::CT_ItemViewItem, &opt, QSize(), widget); //NOTE: this margin logic follows code in QCommonStylePrivate::viewItemLayout() const int margin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, option.widget) + 1; // Find the extra vertical gap by subtracting the height of the text when wrapped within // the default size from the height of the text when wrapped within our max. width. const QRect R1 = mView->fontMetrics().boundingRect(QRect(0, 0, size.width() - 2 * margin, 0), Qt::AlignLeft | Qt::TextWordWrap, opt.text); const QRect R2 = mView->fontMetrics().boundingRect(QRect(0, 0, mView->getWrappedTextWidth(), 0), Qt::AlignLeft | Qt::TextWordWrap, opt.text); // compensate for the vertical gap size.rheight() -= qAbs(R1.height() - R2.height()); //considering the icon size too size.setWidth(qMax(mView->maxTextWidth(), option.decorationSize.width())); // adding the margin is good but not necessary because it is already added size.rwidth() += 2 * margin; size.rheight() += margin; // only at the bottom return size; } /************************************************ ************************************************/ PageSelectWidget::PageSelectWidget(QWidget *parent) : QListWidget(parent) , mMaxTextWidth(0) { mWrappedTextWidth = fontMetrics().averageCharWidth() * 13; // max. 13 characters setSelectionRectVisible(false); setViewMode(IconMode); setSpacing(2); setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); setWordWrap(true); setDragEnabled(NoDragDrop); setEditTriggers(NoEditTriggers); setTextElideMode(Qt::ElideNone); setContentsMargins(0, 0, 0, 0); setItemDelegate(new PageSelectWidgetItemDelegate(this)); connect(model(), &QAbstractItemModel::rowsInserted, this, &PageSelectWidget::updateMaxTextWidth); connect(model(), &QAbstractItemModel::rowsRemoved, this, &PageSelectWidget::updateMaxTextWidth); connect(model(), &QAbstractItemModel::dataChanged, this, &PageSelectWidget::updateMaxTextWidth); } /************************************************ ************************************************/ PageSelectWidget::~PageSelectWidget() { } /************************************************ ************************************************/ int PageSelectWidget::maxTextWidth() const { return mMaxTextWidth; } /************************************************ ************************************************/ QSize PageSelectWidget::viewportSizeHint() const { const int spacing2 = spacing() * 2; QSize size{sizeHintForColumn(0) + spacing2, (sizeHintForRow(0) + spacing2) * count()}; if (verticalScrollBar()->isVisible()) size.rwidth() += verticalScrollBar()->sizeHint().width(); return size; } /************************************************ ************************************************/ QSize PageSelectWidget::minimumSizeHint() const { return QSize{0, 0}; } /************************************************ ************************************************/ void PageSelectWidget::updateMaxTextWidth() { for(int i = count() - 1; 0 <= i; --i) { const QRect r = fontMetrics().boundingRect(QRect(0, 0, mWrappedTextWidth, 0), Qt::AlignLeft | Qt::TextWordWrap, item(i)->text()); mMaxTextWidth = qMax(mMaxTextWidth, r.width()); } } /************************************************ ************************************************/ bool PageSelectWidget::event(QEvent * event) { if (QEvent::StyleChange == event->type()) updateMaxTextWidth(); return QListWidget::event(event); } ukui-panel/panel/common/configdialog/ukuiconfigdialog.cpp0000644000175000017500000001252213632320722022615 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright (C) 2012 Alec Moskvin * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuiconfigdialog.h" #include "ukuiconfigdialog_p.h" #include "ui_ukuiconfigdialog.h" #include #include #include "../ukuisettings.h" using namespace UKUi; ConfigDialogPrivate::ConfigDialogPrivate(ConfigDialog *q, Settings *settings) : q_ptr(q), mCache(new SettingsCache(settings)), ui(new Ui::ConfigDialog) { init(); } ConfigDialogPrivate::~ConfigDialogPrivate() { delete ui; delete mCache; } void ConfigDialogPrivate::init() { Q_Q(ConfigDialog); ui->setupUi(q); QObject::connect(ui->buttons, &QDialogButtonBox::clicked, [=](QAbstractButton* button) { dialogButtonsAction(button); } ); ui->moduleList->setVisible(false); const QList buttons = ui->buttons->findChildren(); for(QPushButton* button : buttons) button->setAutoDefault(false); } void ConfigDialogPrivate::dialogButtonsAction(QAbstractButton* button) { Q_Q(ConfigDialog); QDialogButtonBox::StandardButton standardButton = ui->buttons->standardButton(button); emit q->clicked(standardButton); if (standardButton == QDialogButtonBox::Reset) { mCache->loadToSettings(); emit q->reset(); } else if(standardButton == QDialogButtonBox::Close) { q->close(); } } void ConfigDialogPrivate::updateIcons() { Q_Q(ConfigDialog); for (int ix = 0; ix < mIcons.size(); ix++) ui->moduleList->item(ix)->setIcon(XdgIcon::fromTheme(mIcons.at(ix))); q->update(); } ConfigDialog::ConfigDialog(const QString& title, Settings* settings, QWidget* parent) : QDialog(parent), mSettings(settings), d_ptr(new ConfigDialogPrivate(this, settings)) { setWindowTitle(title); } void ConfigDialog::setButtons(QDialogButtonBox::StandardButtons buttons) { Q_D(ConfigDialog); d->ui->buttons->setStandardButtons(buttons); const QList b = d->ui->buttons->findChildren(); for(QPushButton* button : b) button->setAutoDefault(false); } void ConfigDialog::enableButton(QDialogButtonBox::StandardButton which, bool enable) { Q_D(ConfigDialog); if (QPushButton* pb = d->ui->buttons->button(which)) pb->setEnabled(enable); } void ConfigDialog::addPage(QWidget* page, const QString& name, const QString& iconName) { addPage(page, name, QStringList() << iconName); } void ConfigDialog::addPage(QWidget* page, const QString& name, const QStringList& iconNames) { Q_D(ConfigDialog); Q_ASSERT(page); if (!page) { return; } /* We set the layout margin to 0. In the default configuration, one page * only, it aligns buttons with the page. In multi-page it saves a little * bit of space, without clutter. */ if (page->layout()) { page->layout()->setMargin(0); } QStringList icons = QStringList(iconNames) << QL1S("application-x-executable"); new QListWidgetItem(XdgIcon::fromTheme(icons), name, d->ui->moduleList); d->mIcons.append(icons); d->ui->stackedWidget->addWidget(page); d->mPages[name] = page; if(d->ui->stackedWidget->count() > 1) { d->ui->moduleList->setVisible(true); d->ui->moduleList->setCurrentRow(0); d->mMaxSize = QSize(qMax(page->geometry().width() + d->ui->moduleList->geometry().width(), d->mMaxSize.width()), qMax(page->geometry().height() + d->ui->buttons->geometry().height(), d->mMaxSize.height())); } else { d->mMaxSize = page->geometry().size(); } resize(d->mMaxSize); } void ConfigDialog::showPage(QWidget* page) { Q_D(ConfigDialog); int index = d->ui->stackedWidget->indexOf(page); if (index < 0) return; d->ui->stackedWidget->setCurrentIndex(index); d->ui->moduleList->setCurrentRow(index); } void ConfigDialog::showPage(const QString &name) { Q_D(ConfigDialog); if (d->mPages.contains(name)) showPage(d->mPages.value(name)); else qWarning("ConfigDialog::showPage: Invalid page name (%s)", name.toLocal8Bit().constData()); } bool ConfigDialog::event(QEvent * event) { Q_D(ConfigDialog); if (QEvent::ThemeChange == event->type()) d->updateIcons(); return QDialog::event(event); } void ConfigDialog::closeEvent(QCloseEvent* event) { Q_UNUSED(event) emit save(); mSettings->sync(); } ConfigDialog::~ConfigDialog() { } ukui-panel/panel/common/configdialog/ukuipageselectwidget.h0000644000175000017500000000326213632320722023156 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPAGESELECTWIDGET_H #define UKUIPAGESELECTWIDGET_H #include "../ukuiglobals.h" #include namespace UKUi { class UKUI_API PageSelectWidget : public QListWidget { Q_OBJECT public: explicit PageSelectWidget(QWidget *parent = 0); virtual ~PageSelectWidget(); int maxTextWidth() const; bool event(QEvent * event) override; int getWrappedTextWidth() const { return mWrappedTextWidth; } protected: QSize viewportSizeHint() const override; QSize minimumSizeHint() const override; protected slots: void updateMaxTextWidth(); private: int mMaxTextWidth; int mWrappedTextWidth; }; } // namespace UKUi #endif // PAGESELECTWIDGET_H ukui-panel/panel/common/configdialog/ukuiconfigdialog.ui0000644000175000017500000000416413632320722022453 0ustar fengfeng ConfigDialog 0 0 272 231 Dialog Qt::ScrollBarAlwaysOff QAbstractScrollArea::AdjustToContents -1 Qt::Horizontal QDialogButtonBox::Close|QDialogButtonBox::Reset UKUi::PageSelectWidget QListWidget

common/configdialog/ukuipageselectwidget.h
moduleList buttons moduleList currentRowChanged(int) stackedWidget setCurrentIndex(int) 150 123 344 117 ukui-panel/panel/common/configdialog/ukuiconfigdialogcmdlineoptions.cpp0000644000175000017500000000344413632320722025570 0ustar fengfeng/* * Copyright (C) 2018 Luís Pereira * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ #include "ukuiconfigdialogcmdlineoptions.h" #include namespace UKUi { class Q_DECL_HIDDEN ConfigDialogCmdLineOptionsPrivate { public: QString mPage; }; ConfigDialogCmdLineOptions::ConfigDialogCmdLineOptions() : d(new ConfigDialogCmdLineOptionsPrivate) { } ConfigDialogCmdLineOptions::~ConfigDialogCmdLineOptions() { } bool ConfigDialogCmdLineOptions::setCommandLine(QCommandLineParser *parser) { Q_ASSERT(parser); if (!parser) return false; return parser->addOption(QCommandLineOption{QStringList{QL1S("s"), QL1S("show-page")}, QCoreApplication::tr("Choose the page to be shown."), QL1S("name")}); } void ConfigDialogCmdLineOptions::process(QCommandLineParser &parser) { if (parser.isSet(QL1S("show-page"))) { d->mPage = parser.value(QL1S("show-page")); } } QString ConfigDialogCmdLineOptions::page() const { return d->mPage; } } // UKUi namespace ukui-panel/panel/common/configdialog/ukuiconfigdialog_p.h0000644000175000017500000000316013632320722022577 0ustar fengfeng/* * Copyright (C) 2012 Alec Moskvin * Copyright (C) 2018 Luís Pereira * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef UKUICONFIGDIALOG_P_H #define UKUICONFIGDIALOG_P_H #include #include #include #include namespace Ui { class ConfigDialog; } class QAbstractButton; namespace UKUi { class ConfigDialog; class Settings; class SettingsCache; class Q_DECL_HIDDEN ConfigDialogPrivate { Q_DECLARE_PUBLIC(ConfigDialog) ConfigDialog* const q_ptr; public: ConfigDialogPrivate(ConfigDialog *q, Settings* settings); ~ConfigDialogPrivate(); void init(); void dialogButtonsAction(QAbstractButton* button); void updateIcons(); SettingsCache* mCache; QList mIcons; QSize mMaxSize; Ui::ConfigDialog* ui; QHash mPages; }; } // namespace UKUi #endif // UKUICONFIGDIALOG_P_H ukui-panel/panel/common/configdialog/ukuiconfigdialog.h0000644000175000017500000000616213632320722022265 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright (C) 2012 Alec Moskvin * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUICONFIGDIALOG_H #define UKUICONFIGDIALOG_H #include #include #include #include #include "../ukuiglobals.h" namespace Ui { class ConfigDialog; } namespace UKUi { class Settings; class ConfigDialogPrivate; class UKUI_API ConfigDialog : public QDialog { Q_OBJECT Q_DECLARE_PRIVATE(ConfigDialog) public: explicit ConfigDialog(const QString& title, Settings* settings, QWidget* parent = 0); ~ConfigDialog(); /*! * Sets buttons in button bar */ void setButtons(QDialogButtonBox::StandardButtons buttons); /*! * Enable/disable a standard button if it exists */ void enableButton(QDialogButtonBox::StandardButton which, bool enable); /*! * Add a page to the configure dialog */ void addPage(QWidget* page, const QString& name, const QString& iconName = QLatin1String("application-x-executable")); /*! * Add a page to the configure dialog, attempting several alternative icons to find one in the theme */ void addPage(QWidget* page, const QString& name, const QStringList& iconNames); /*! * Show page containing the widget in parameter */ void showPage(QWidget *page); /*! * \brief Shows the given page * \param name The page to be shown. */ void showPage(const QString &name); signals: /*! * This signal is emitted when the user pressed the "Reset" button. * Settings should be re-read and the widgets should be set accordingly. */ void reset(); /*! * This is emitted whenever the window is closed and settings need to be saved. * It is only necessary if additional actions need to be performed - Settings are handled automatically. */ void save(); /*! * This is emitted when some button in the buttonbar is clicked. */ void clicked(QDialogButtonBox::StandardButton); protected: Settings* mSettings; virtual bool event(QEvent * event) override; virtual void closeEvent(QCloseEvent* event) override; private: Q_DISABLE_COPY(ConfigDialog) QScopedPointer const d_ptr; }; } // namespace UKUi #endif // UKUICONFIGDIALOG_H ukui-panel/panel/common/configdialog/ukuiconfigdialogcmdlineoptions.h0000644000175000017500000000305613632320722025234 0ustar fengfeng/* * Copyright (C) 2018 Luís Pereira * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef UKUICONFIGDIALOGCMDLINEOPTIONS_H #define UKUICONFIGDIALOGCMDLINEOPTIONS_H #include "../ukuiglobals.h" #include #include class QCommandLineParser; namespace UKUi { class ConfigDialogCmdLineOptionsPrivate; class UKUI_API ConfigDialogCmdLineOptions { public: ConfigDialogCmdLineOptions(); ~ConfigDialogCmdLineOptions(); bool setCommandLine(QCommandLineParser *parser); void process(QCommandLineParser &parser); QString page() const; private: Q_DISABLE_COPY(ConfigDialogCmdLineOptions) QScopedPointer const d; }; } // UKUi namespace #endif // UKUICONFIGDIALOGCMDLINEOPTIONS_H ukui-panel/panel/common/ukuiprogramfinder.cpp0000644000175000017500000000420313632320722020377 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright (C) 2013 Alec Moskvin * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuiprogramfinder.h" #include #include #include using namespace UKUi; UKUI_API bool ProgramFinder::programExists(const QString& command) { const QString program = programName(command); if (program[0] == QL1C('/')) { QFileInfo fi(program); return fi.isExecutable() && fi.isFile(); } const QString path = QFile::decodeName(qgetenv("PATH")); const QStringList dirs = path.split(QL1C(':'), QString::SkipEmptyParts); for (const QString& dirName : dirs) { const QFileInfo fi(QDir(dirName), program); if (fi.isExecutable() && fi.isFile()) return true; } return false; } UKUI_API QStringList ProgramFinder::findPrograms(const QStringList& commands) { QStringList availPrograms; for (const QString& program : commands) if (programExists(program)) availPrograms.append(program); return availPrograms; } UKUI_API QString ProgramFinder::programName(const QString& command) { wordexp_t we; if (wordexp(command.toLocal8Bit().constData(), &we, WRDE_NOCMD) == 0) if (we.we_wordc > 0) return QString::fromLocal8Bit(we.we_wordv[0]); return QString(); } ukui-panel/panel/common/dbus/0000755000175000017500000000000013632320722015074 5ustar fengfengukui-panel/panel/common/dbus/org.ukui.SingleApplication.xml0000644000175000017500000000041613632320722022766 0ustar fengfeng ukui-panel/panel/common/dbus/org.freedesktop.Notifications.xml0000644000175000017500000000476113632320722023537 0ustar fengfeng ukui-panel/panel/common/ukuihtmldelegate.h0000644000175000017500000000315013632320722017644 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * Paulo Lieuthier * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIHTMLDELEGATE_H #define UKUIHTMLDELEGATE_H #include #include #include "ukuiglobals.h" namespace UKUi { class UKUI_API HtmlDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit HtmlDelegate(const QSize iconSize, QObject* parent = 0); virtual ~HtmlDelegate(); virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; private: QSize mIconSize; }; } #endif ukui-panel/panel/common/ukuipower/0000755000175000017500000000000013632320722016171 5ustar fengfengukui-panel/panel/common/ukuipower/ukuipower.h0000644000175000017500000001025513632320722020377 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019-2020 UKUI team * Authors: * minglequn * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPOWER_H #define UKUIPOWER_H #include #include #include "../ukuiglobals.h" namespace UKUi { class PowerProvider; /*! Power class provides an interface to control system-wide power and session management. It allows logout from the user session, hibernate, reboot, shutdown and suspend computer. This is a wrapper class. All the real work is done in the PowerWorker classes. */ class UKUI_API Power : public QObject { Q_OBJECT public: /// Power can perform next actions: enum Action{ PowerLogout, /// Close the current user session. PowerHibernate, /// Hibernate the comupter PowerReboot, /// Reboot the computer PowerShutdown, /// Shutdown the computer PowerSuspend, /// Suspend the computer PowerMonitorOff /// Turn off the monitor(s) }; /*! * Constructs the Power object. * \param useUkuiSessionProvider indicates if the DBus methods * provided by ukui-session should be considered. This is useful to * avoid recursion if the ukui-session wants to provide some of the * methods by itself with internal use of this object. */ explicit Power(bool useUkuiSessionProvider, QObject *parent = nullptr); /// Constructs a Power with using the ukui-session provider. explicit Power(QObject *parent = nullptr); /// Destroys the object. virtual ~Power(); /// Returns true if the Power can perform action. bool canAction(Action action) const; //! This function is provided for convenience. It's equivalent to calling canAction(PowerLogout). bool canLogout() const; //! This function is provided for convenience. It's equivalent to calling canAction(PowerHibernate). bool canHibernate() const; //! This function is provided for convenience. It's equivalent to calling canAction(PowerReboot). bool canReboot() const; //! This function is provided for convenience. It's equivalent to calling canAction(PowerShutdown). bool canShutdown() const; //! This function is provided for convenience. It's equivalent to calling canAction(PowerSuspend). bool canSuspend() const; //! This function is provided for convenience. It's equivalent to calling canAction(PowerMonitorOff). bool canMonitorOff() const; public slots: /// Performs the requested action. bool doAction(Action action); //! This function is provided for convenience. It's equivalent to calling doAction(PowerLogout). bool logout(); //! This function is provided for convenience. It's equivalent to calling doAction(PowerHibernate). bool hibernate(); //! This function is provided for convenience. It's equivalent to calling doAction(PowerReboot). bool reboot(); //! This function is provided for convenience. It's equivalent to calling doAction(PowerShutdown). bool shutdown(); //! This function is provided for convenience. It's equivalent to calling doAction(PowerSuspend). bool suspend(); //! This function is provided for convenience. It's equivalent to calling doAction(PowerMonitorOff). bool monitorOff(); private: QList mProviders; }; } // namespace UKUi #endif // UKUIPOWER_H ukui-panel/panel/common/ukuipower/ukuipowerproviders.cpp0000644000175000017500000004426413632320722022677 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * Petr Vanek * * Copyright: 2019-2020 UKUI team * Authors: * minglequn * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuipowerproviders.h" #include #include #include #include "ukuinotification.h" #include // for kill() #define UPOWER_SERVICE "org.freedesktop.UPower" #define UPOWER_PATH "/org/freedesktop/UPower" #define UPOWER_INTERFACE UPOWER_SERVICE #define CONSOLEKIT_SERVICE "org.freedesktop.ConsoleKit" #define CONSOLEKIT_PATH "/org/freedesktop/ConsoleKit/Manager" #define CONSOLEKIT_INTERFACE "org.freedesktop.ConsoleKit.Manager" #define SYSTEMD_SERVICE "org.freedesktop.login1" #define SYSTEMD_PATH "/org/freedesktop/login1" #define SYSTEMD_INTERFACE "org.freedesktop.login1.Manager" #define UKUI_SERVICE "org.ukui.session" #define UKUI_PATH "/UKUiSession" #define UKUI_INTERFACE "org.ukui.session" #define PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties" using namespace UKUi; /************************************************ Helper func ************************************************/ void printDBusMsg(const QDBusMessage &msg) { qWarning() << "** Dbus error **************************"; qWarning() << "Error name " << msg.errorName(); qWarning() << "Error msg " << msg.errorMessage(); qWarning() << "****************************************"; } /************************************************ Helper func ************************************************/ static bool dbusCall(const QString &service, const QString &path, const QString &interface, const QDBusConnection &connection, const QString & method, PowerProvider::DbusErrorCheck errorCheck = PowerProvider::CheckDBUS ) { QDBusInterface dbus(service, path, interface, connection); if (!dbus.isValid()) { qWarning() << "dbusCall: QDBusInterface is invalid" << service << path << interface << method; if (errorCheck == PowerProvider::CheckDBUS) { Notification::notify( QObject::tr("Power Manager Error"), QObject::tr("QDBusInterface is invalid") + QL1S("\n\n") + service + QL1C(' ') + path + QL1C(' ') + interface + QL1C(' ') + method, QL1S("ukui-logo.png")); } return false; } QDBusMessage msg = dbus.call(method); if (!msg.errorName().isEmpty()) { printDBusMsg(msg); if (errorCheck == PowerProvider::CheckDBUS) { Notification::notify( QObject::tr("Power Manager Error (D-BUS call)"), msg.errorName() + QL1S("\n\n") + msg.errorMessage(), QL1S("ukui-logo.png")); } } // If the method no returns value, we believe that it was successful. return msg.arguments().isEmpty() || msg.arguments().constFirst().isNull() || msg.arguments().constFirst().toBool(); } /************************************************ Helper func Just like dbusCall(), except that systemd returns a string instead of a bool, and it takes an "interactivity boolean" as an argument. ************************************************/ static bool dbusCallSystemd(const QString &service, const QString &path, const QString &interface, const QDBusConnection &connection, const QString &method, bool needBoolArg, PowerProvider::DbusErrorCheck errorCheck = PowerProvider::CheckDBUS ) { QDBusInterface dbus(service, path, interface, connection); if (!dbus.isValid()) { qWarning() << "dbusCall: QDBusInterface is invalid" << service << path << interface << method; if (errorCheck == PowerProvider::CheckDBUS) { Notification::notify( QObject::tr("Power Manager Error"), QObject::tr("QDBusInterface is invalid") + QL1S("\n\n") + service + QL1C(' ') + path + QL1C(' ')+ interface + QL1C(' ') + method, QL1S("ukui-logo.png")); } return false; } QDBusMessage msg = dbus.call(method, needBoolArg ? QVariant(true) : QVariant()); if (!msg.errorName().isEmpty()) { printDBusMsg(msg); if (errorCheck == PowerProvider::CheckDBUS) { Notification::notify( QObject::tr("Power Manager Error (D-BUS call)"), msg.errorName() + QL1S("\n\n") + msg.errorMessage(), QL1S("ukui-logo.png")); } } // If the method no returns value, we believe that it was successful. if (msg.arguments().isEmpty() || msg.arguments().constFirst().isNull()) return true; QString response = msg.arguments().constFirst().toString(); qDebug() << "systemd:" << method << "=" << response; return response == QL1S("yes") || response == QL1S("challenge"); } /************************************************ Helper func ************************************************/ bool dbusGetProperty(const QString &service, const QString &path, const QString &interface, const QDBusConnection &connection, const QString & property ) { QDBusInterface dbus(service, path, interface, connection); if (!dbus.isValid()) { qWarning() << "dbusGetProperty: QDBusInterface is invalid" << service << path << interface << property; // Notification::notify(QObject::tr("UKUi Power Manager"), // "ukui-logo.png", // QObject::tr("Power Manager Error"), // QObject::tr("QDBusInterface is invalid")+ "\n\n" + service +" " + path +" " + interface +" " + property); return false; } QDBusMessage msg = dbus.call(QL1S("Get"), dbus.interface(), property); if (!msg.errorName().isEmpty()) { printDBusMsg(msg); // Notification::notify(QObject::tr("UKUi Power Manager"), // "ukui-logo.png", // QObject::tr("Power Manager Error (Get Property)"), // msg.errorName() + "\n\n" + msg.errorMessage()); } return !msg.arguments().isEmpty() && msg.arguments().constFirst().value().variant().toBool(); } /************************************************ PowerProvider ************************************************/ PowerProvider::PowerProvider(QObject *parent): QObject(parent) { } PowerProvider::~PowerProvider() { } /************************************************ UPowerProvider ************************************************/ UPowerProvider::UPowerProvider(QObject *parent): PowerProvider(parent) { } UPowerProvider::~UPowerProvider() { } bool UPowerProvider::canAction(Power::Action action) const { QString command; QString property; switch (action) { case Power::PowerHibernate: property = QL1S("CanHibernate"); command = QL1S("HibernateAllowed"); break; case Power::PowerSuspend: property = QL1S("CanSuspend"); command = QL1S("SuspendAllowed"); break; default: return false; } return dbusGetProperty( // Whether the system is able to hibernate. QL1S(UPOWER_SERVICE), QL1S(UPOWER_PATH), QL1S(PROPERTIES_INTERFACE), QDBusConnection::systemBus(), property ) && dbusCall( // Check if the caller has (or can get) the PolicyKit privilege to call command. QL1S(UPOWER_SERVICE), QL1S(UPOWER_PATH), QL1S(UPOWER_INTERFACE), QDBusConnection::systemBus(), command, // canAction should be always silent because it can freeze // g_main_context_iteration Qt event loop in QMessageBox // on panel startup if there is no DBUS running. PowerProvider::DontCheckDBUS ); } bool UPowerProvider::doAction(Power::Action action) { QString command; switch (action) { case Power::PowerHibernate: command = QL1S("Hibernate"); break; case Power::PowerSuspend: command = QL1S("Suspend"); break; default: return false; } return dbusCall(QL1S(UPOWER_SERVICE), QL1S(UPOWER_PATH), QL1S(UPOWER_INTERFACE), QDBusConnection::systemBus(), command ); } /************************************************ ConsoleKitProvider ************************************************/ ConsoleKitProvider::ConsoleKitProvider(QObject *parent): PowerProvider(parent) { } ConsoleKitProvider::~ConsoleKitProvider() { } bool ConsoleKitProvider::canAction(Power::Action action) const { QString command; switch (action) { case Power::PowerReboot: command = QL1S("CanReboot"); break; case Power::PowerShutdown: command = QL1S("CanPowerOff"); break; case Power::PowerHibernate: command = QL1S("CanHibernate"); break; case Power::PowerSuspend: command = QL1S("CanSuspend"); break; default: return false; } return dbusCallSystemd(QL1S(CONSOLEKIT_SERVICE), QL1S(CONSOLEKIT_PATH), QL1S(CONSOLEKIT_INTERFACE), QDBusConnection::systemBus(), command, false, // canAction should be always silent because it can freeze // g_main_context_iteration Qt event loop in QMessageBox // on panel startup if there is no DBUS running. PowerProvider::DontCheckDBUS ); } bool ConsoleKitProvider::doAction(Power::Action action) { QString command; switch (action) { case Power::PowerReboot: command = QL1S("Reboot"); break; case Power::PowerShutdown: command = QL1S("PowerOff"); break; case Power::PowerHibernate: command = QL1S("Hibernate"); break; case Power::PowerSuspend: command = QL1S("Suspend"); break; default: return false; } return dbusCallSystemd(QL1S(CONSOLEKIT_SERVICE), QL1S(CONSOLEKIT_PATH), QL1S(CONSOLEKIT_INTERFACE), QDBusConnection::systemBus(), command, true ); } /************************************************ SystemdProvider http://www.freedesktop.org/wiki/Software/systemd/logind ************************************************/ SystemdProvider::SystemdProvider(QObject *parent): PowerProvider(parent) { } SystemdProvider::~SystemdProvider() { } bool SystemdProvider::canAction(Power::Action action) const { QString command; switch (action) { case Power::PowerReboot: command = QL1S("CanReboot"); break; case Power::PowerShutdown: command = QL1S("CanPowerOff"); break; case Power::PowerSuspend: command = QL1S("CanSuspend"); break; case Power::PowerHibernate: command = QL1S("CanHibernate"); break; default: return false; } return dbusCallSystemd(QL1S(SYSTEMD_SERVICE), QL1S(SYSTEMD_PATH), QL1S(SYSTEMD_INTERFACE), QDBusConnection::systemBus(), command, false, // canAction should be always silent because it can freeze // g_main_context_iteration Qt event loop in QMessageBox // on panel startup if there is no DBUS running. PowerProvider::DontCheckDBUS ); } bool SystemdProvider::doAction(Power::Action action) { QString command; switch (action) { case Power::PowerReboot: command = QL1S("Reboot"); break; case Power::PowerShutdown: command = QL1S("PowerOff"); break; case Power::PowerSuspend: command = QL1S("Suspend"); break; case Power::PowerHibernate: command = QL1S("Hibernate"); break; default: return false; } return dbusCallSystemd(QL1S(SYSTEMD_SERVICE), QL1S(SYSTEMD_PATH), QL1S(SYSTEMD_INTERFACE), QDBusConnection::systemBus(), command, true ); } /************************************************ UKUiProvider ************************************************/ UKUiProvider::UKUiProvider(QObject *parent): PowerProvider(parent) { } UKUiProvider::~UKUiProvider() { } bool UKUiProvider::canAction(Power::Action action) const { QString command; switch (action) { case Power::PowerLogout: command = QL1S("canLogout"); break; case Power::PowerReboot: command = QL1S("canReboot"); break; case Power::PowerShutdown: command = QL1S("canPowerOff"); break; default: return false; } // there can be case when ukuisession-session does not run return dbusCall(QL1S(UKUI_SERVICE), QL1S(UKUI_PATH), QL1S(UKUI_SERVICE), QDBusConnection::sessionBus(), command, PowerProvider::DontCheckDBUS); } bool UKUiProvider::doAction(Power::Action action) { QString command; switch (action) { case Power::PowerLogout: command = QL1S("logout"); break; case Power::PowerReboot: command = QL1S("reboot"); break; case Power::PowerShutdown: command = QL1S("powerOff"); break; default: return false; } return dbusCall(QL1S(UKUI_SERVICE), QL1S(UKUI_PATH), QL1S(UKUI_INTERFACE), QDBusConnection::sessionBus(), command ); } /************************************************ LxSessionProvider ************************************************/ LxSessionProvider::LxSessionProvider(QObject *parent): PowerProvider(parent) { pid = (Q_PID)qgetenv("_LXSESSION_PID").toLong(); } LxSessionProvider::~LxSessionProvider() { } bool LxSessionProvider::canAction(Power::Action action) const { switch (action) { case Power::PowerLogout: return pid != 0; default: return false; } } bool LxSessionProvider::doAction(Power::Action action) { switch (action) { case Power::PowerLogout: if(pid) ::kill(pid, SIGTERM); break; default: return false; } return true; } /************************************************ HalProvider ************************************************/ HalProvider::HalProvider(QObject *parent): PowerProvider(parent) { } HalProvider::~HalProvider() { } bool HalProvider::canAction(Power::Action action) const { Q_UNUSED(action) return false; } bool HalProvider::doAction(Power::Action action) { Q_UNUSED(action) return false; } /************************************************ CustomProvider ************************************************/ CustomProvider::CustomProvider(QObject *parent): PowerProvider(parent), mSettings(QL1S("power")) { } CustomProvider::~CustomProvider() { } bool CustomProvider::canAction(Power::Action action) const { switch (action) { case Power::PowerShutdown: return mSettings.contains(QL1S("shutdownCommand")); case Power::PowerReboot: return mSettings.contains(QL1S("rebootCommand")); case Power::PowerHibernate: return mSettings.contains(QL1S("hibernateCommand")); case Power::PowerSuspend: return mSettings.contains(QL1S("suspendCommand")); case Power::PowerLogout: return mSettings.contains(QL1S("logoutCommand")); case Power::PowerMonitorOff: return mSettings.contains(QL1S("monitorOffCommand")); default: return false; } } bool CustomProvider::doAction(Power::Action action) { QString command; switch(action) { case Power::PowerShutdown: command = mSettings.value(QL1S("shutdownCommand")).toString(); break; case Power::PowerReboot: command = mSettings.value(QL1S("rebootCommand")).toString(); break; case Power::PowerHibernate: command = mSettings.value(QL1S("hibernateCommand")).toString(); break; case Power::PowerSuspend: command = mSettings.value(QL1S("suspendCommand")).toString(); break; case Power::PowerLogout: command = mSettings.value(QL1S("logoutCommand")).toString(); break; case Power::PowerMonitorOff: command = mSettings.value(QL1S("monitorOffCommand")).toString(); break; default: return false; } return QProcess::startDetached(command); } ukui-panel/panel/common/ukuipower/ukuipower.cpp0000644000175000017500000000565713632320722020744 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019-2020 UKUI team * Authors: * minglequn * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuipower.h" #include "ukuipowerproviders.h" #include #include using namespace UKUi; Power::Power(bool useUkuiSessionProvider, QObject * parent /*= nullptr*/) : QObject(parent) { mProviders.append(new CustomProvider(this)); if (useUkuiSessionProvider) mProviders.append(new UKUiProvider(this)); mProviders.append(new SystemdProvider(this)); mProviders.append(new UPowerProvider(this)); mProviders.append(new ConsoleKitProvider(this)); mProviders.append(new LxSessionProvider(this)); } Power::Power(QObject * parent /*= nullptr*/) : Power(true, parent) { } Power::~Power() { } bool Power::canAction(Power::Action action) const { for(const PowerProvider* provider : qAsConst(mProviders)) { if (provider->canAction(action)) return true; } return false; } bool Power::doAction(Power::Action action) { for(PowerProvider* provider : qAsConst(mProviders)) { if (provider->canAction(action) && provider->doAction(action) ) { return true; } } return false; } bool Power::canLogout() const { return canAction(PowerLogout); } bool Power::canHibernate() const { return canAction(PowerHibernate); } bool Power::canReboot() const { return canAction(PowerReboot); } bool Power::canShutdown() const { return canAction(PowerShutdown); } bool Power::canSuspend() const { return canAction(PowerSuspend); } bool Power::canMonitorOff() const { return canAction(PowerMonitorOff); } bool Power::logout() { return doAction(PowerLogout); } bool Power::hibernate() { return doAction(PowerHibernate); } bool Power::reboot() { return doAction(PowerReboot); } bool Power::shutdown() { return doAction(PowerShutdown); } bool Power::suspend() { return doAction(PowerSuspend); } bool Power::monitorOff() { return doAction(PowerMonitorOff); } ukui-panel/panel/common/ukuipower/ukuipowerproviders.h0000644000175000017500000000703413632320722022336 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019-2020 UKUI team * Authors: * minglequn * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPOWER_PROVIDERS_H #define UKUIPOWER_PROVIDERS_H #include #include <../../ukuisettings.h> #include "ukuipower.h" #include // for PID_T namespace UKUi { class PowerProvider: public QObject { Q_OBJECT public: enum DbusErrorCheck { CheckDBUS, DontCheckDBUS }; explicit PowerProvider(QObject *parent = 0); virtual ~PowerProvider(); /*! Returns true if the Power can perform action. This is a pure virtual function, and must be reimplemented in subclasses. */ virtual bool canAction(Power::Action action) const = 0 ; public slots: /*! Performs the requested action. This is a pure virtual function, and must be reimplemented in subclasses. */ virtual bool doAction(Power::Action action) = 0; }; class UPowerProvider: public PowerProvider { Q_OBJECT public: UPowerProvider(QObject *parent = 0); ~UPowerProvider(); bool canAction(Power::Action action) const; public slots: bool doAction(Power::Action action); }; class ConsoleKitProvider: public PowerProvider { Q_OBJECT public: ConsoleKitProvider(QObject *parent = 0); ~ConsoleKitProvider(); bool canAction(Power::Action action) const; public slots: bool doAction(Power::Action action); }; class SystemdProvider: public PowerProvider { Q_OBJECT public: SystemdProvider(QObject *parent = 0); ~SystemdProvider(); bool canAction(Power::Action action) const; public slots: bool doAction(Power::Action action); }; class UKUiProvider: public PowerProvider { Q_OBJECT public: UKUiProvider(QObject *parent = 0); ~UKUiProvider(); bool canAction(Power::Action action) const; public slots: bool doAction(Power::Action action); }; class LxSessionProvider: public PowerProvider { Q_OBJECT public: LxSessionProvider(QObject *parent = 0); ~LxSessionProvider(); bool canAction(Power::Action action) const; public slots: bool doAction(Power::Action action); private: Q_PID pid; }; class HalProvider: public PowerProvider { Q_OBJECT public: HalProvider(QObject *parent = 0); ~HalProvider(); bool canAction(Power::Action action) const; public slots: bool doAction(Power::Action action); }; class CustomProvider: public PowerProvider { Q_OBJECT public: CustomProvider(QObject *parent = 0); ~CustomProvider(); bool canAction(Power::Action action) const; public slots: bool doAction(Power::Action action); private: Settings mSettings; }; } // namespace UKUi #endif // UKUIPOWER_PROVIDERS_H ukui-panel/panel/common/ukuiglobals.h0000644000175000017500000000261113633355350016637 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2013 - LXQt team * Authors: * Hong Jen Yee (PCMan) * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef _UKUI_GLOBALS_H_ #define _UKUI_GLOBALS_H_ #include #ifdef COMPILE_LIBUKUI #define UKUI_API Q_DECL_EXPORT #else #define UKUI_API Q_DECL_IMPORT #endif #ifndef QL1S #define QL1S(x) QLatin1String(x) #endif #ifndef QL1C #define QL1C(x) QLatin1Char(x) #endif #ifndef QSL #define QSL(x) QStringLiteral(x) #endif #ifndef QBAL #define QBAL(x) QByteArrayLiteral(x) #endif #endif // _UKUI_GLOBALS_H_ ukui-panel/panel/common/ukuigridlayout.cpp0000644000175000017500000004345013632320722017732 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuigridlayout.h" #include #include #include #include using namespace UKUi; class UKUi::GridLayoutPrivate { public: GridLayoutPrivate(); ~GridLayoutPrivate(); QList mItems; int mRowCount; int mColumnCount; GridLayout::Direction mDirection; bool mIsValid; QSize mCellSizeHint; QSize mCellMaxSize; int mVisibleCount; GridLayout::Stretch mStretch; bool mAnimate; int mAnimatedItems; //!< counter of currently animated items void updateCache(); int rows() const; int cols() const; void setItemGeometry(QLayoutItem * item, QRect const & geometry); QSize mPrefCellMinSize; QSize mPrefCellMaxSize; QRect mOccupiedGeometry; }; namespace { class ItemMoveAnimation : public QVariantAnimation { public: static void animate(QLayoutItem * item, QRect const & geometry, UKUi::GridLayoutPrivate * layout) { ItemMoveAnimation* animation = new ItemMoveAnimation(item); animation->setStartValue(item->geometry()); animation->setEndValue(geometry); ++layout->mAnimatedItems; connect(animation, &QAbstractAnimation::finished, [layout] { --layout->mAnimatedItems; Q_ASSERT(0 <= layout->mAnimatedItems); }); animation->start(DeleteWhenStopped); } ItemMoveAnimation(QLayoutItem *item) : mItem(item) { setDuration(150); } void updateCurrentValue(const QVariant ¤t) { mItem->setGeometry(current.toRect()); } private: QLayoutItem* mItem; }; } /************************************************ ************************************************/ GridLayoutPrivate::GridLayoutPrivate() { mColumnCount = 0; mRowCount = 0; mDirection = GridLayout::LeftToRight; mIsValid = false; mVisibleCount = 0; mStretch = GridLayout::StretchHorizontal | GridLayout::StretchVertical; mAnimate = false; mAnimatedItems = 0; mPrefCellMinSize = QSize(0,0); mPrefCellMaxSize = QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); } /************************************************ ************************************************/ GridLayoutPrivate::~GridLayoutPrivate() { qDeleteAll(mItems); } /************************************************ ************************************************/ void GridLayoutPrivate::updateCache() { mCellSizeHint = QSize(0, 0); mCellMaxSize = QSize(0, 0); mVisibleCount = 0; const int N = mItems.count(); for (int i=0; i < N; ++i) { QLayoutItem *item = mItems.at(i); if (!item->widget() || item->widget()->isHidden()) continue; int h = qBound(item->minimumSize().height(), item->sizeHint().height(), item->maximumSize().height()); int w = qBound(item->minimumSize().width(), item->sizeHint().width(), item->maximumSize().width()); mCellSizeHint.rheight() = qMax(mCellSizeHint.height(), h); mCellSizeHint.rwidth() = qMax(mCellSizeHint.width(), w); mCellMaxSize.rheight() = qMax(mCellMaxSize.height(), item->maximumSize().height()); mCellMaxSize.rwidth() = qMax(mCellMaxSize.width(), item->maximumSize().width()); mVisibleCount++; #if 0 qDebug() << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"; qDebug() << "item.min" << item->minimumSize().width(); qDebug() << "item.sz " << item->sizeHint().width(); qDebug() << "item.max" << item->maximumSize().width(); qDebug() << "w h" << w << h; qDebug() << "wid.sizeHint" << item->widget()->sizeHint(); qDebug() << "mCellSizeHint:" << mCellSizeHint; qDebug() << "mCellMaxSize: " << mCellMaxSize; qDebug() << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"; #endif } mCellSizeHint.rwidth() = qBound(mPrefCellMinSize.width(), mCellSizeHint.width(), mPrefCellMaxSize.width()); mCellSizeHint.rheight()= qBound(mPrefCellMinSize.height(), mCellSizeHint.height(), mPrefCellMaxSize.height()); mIsValid = !mCellSizeHint.isEmpty(); } /************************************************ ************************************************/ int GridLayoutPrivate::rows() const { if (mRowCount) return mRowCount; if (!mColumnCount) return 1; return ceil(mVisibleCount * 1.0 / mColumnCount); } /************************************************ ************************************************/ int GridLayoutPrivate::cols() const { if (mColumnCount) return mColumnCount; int rows = mRowCount; if (!rows) rows = 1; return ceil(mVisibleCount * 1.0 / rows); } void GridLayoutPrivate::setItemGeometry(QLayoutItem * item, QRect const & geometry) { mOccupiedGeometry |= geometry; if (mAnimate) { ItemMoveAnimation::animate(item, geometry, this); } else { item->setGeometry(geometry); } } /************************************************ ************************************************/ GridLayout::GridLayout(QWidget *parent): QLayout(parent), d_ptr(new GridLayoutPrivate()) { } /************************************************ ************************************************/ GridLayout::~GridLayout() { delete d_ptr; } /************************************************ ************************************************/ void GridLayout::addItem(QLayoutItem *item) { d_ptr->mItems.append(item); } /************************************************ ************************************************/ QLayoutItem *GridLayout::itemAt(int index) const { Q_D(const GridLayout); if (index < 0 || index >= d->mItems.count()) return 0; return d->mItems.at(index); } /************************************************ ************************************************/ QLayoutItem *GridLayout::takeAt(int index) { Q_D(GridLayout); if (index < 0 || index >= d->mItems.count()) return 0; QLayoutItem *item = d->mItems.takeAt(index); return item; } /************************************************ ************************************************/ int GridLayout::count() const { Q_D(const GridLayout); return d->mItems.count(); } /************************************************ ************************************************/ void GridLayout::invalidate() { Q_D(GridLayout); d->mIsValid = false; QLayout::invalidate(); } /************************************************ ************************************************/ int GridLayout::rowCount() const { Q_D(const GridLayout); return d->mRowCount; } /************************************************ ************************************************/ void GridLayout::setRowCount(int value) { Q_D(GridLayout); if (d->mRowCount != value) { d->mRowCount = value; invalidate(); } } /************************************************ ************************************************/ int GridLayout::columnCount() const { Q_D(const GridLayout); return d->mColumnCount; } /************************************************ ************************************************/ void GridLayout::setColumnCount(int value) { Q_D(GridLayout); if (d->mColumnCount != value) { d->mColumnCount = value; invalidate(); } } /************************************************ ************************************************/ GridLayout::Direction GridLayout::direction() const { Q_D(const GridLayout); return d->mDirection; } /************************************************ ************************************************/ void GridLayout::setDirection(GridLayout::Direction value) { Q_D(GridLayout); if (d->mDirection != value) { d->mDirection = value; invalidate(); } } /************************************************ ************************************************/ GridLayout::Stretch GridLayout::stretch() const { Q_D(const GridLayout); return d->mStretch; } /************************************************ ************************************************/ void GridLayout::setStretch(Stretch value) { Q_D(GridLayout); if (d->mStretch != value) { d->mStretch = value; invalidate(); } } /************************************************ ************************************************/ void GridLayout::moveItem(int from, int to, bool withAnimation /*= false*/) { Q_D(GridLayout); d->mAnimate = withAnimation; d->mItems.move(from, to); invalidate(); } /************************************************ ************************************************/ bool GridLayout::animatedMoveInProgress() const { Q_D(const GridLayout); return 0 < d->mAnimatedItems; } /************************************************ ************************************************/ QSize GridLayout::cellMinimumSize() const { Q_D(const GridLayout); return d->mPrefCellMinSize; } /************************************************ ************************************************/ void GridLayout::setCellMinimumSize(QSize minSize) { Q_D(GridLayout); if (d->mPrefCellMinSize != minSize) { d->mPrefCellMinSize = minSize; invalidate(); } } /************************************************ ************************************************/ void GridLayout::setCellMinimumHeight(int value) { Q_D(GridLayout); if (d->mPrefCellMinSize.height() != value) { d->mPrefCellMinSize.setHeight(value); invalidate(); } } /************************************************ ************************************************/ void GridLayout::setCellMinimumWidth(int value) { Q_D(GridLayout); if (d->mPrefCellMinSize.width() != value) { d->mPrefCellMinSize.setWidth(value); invalidate(); } } /************************************************ ************************************************/ QSize GridLayout::cellMaximumSize() const { Q_D(const GridLayout); return d->mPrefCellMaxSize; } /************************************************ ************************************************/ void GridLayout::setCellMaximumSize(QSize maxSize) { Q_D(GridLayout); if (d->mPrefCellMaxSize != maxSize) { d->mPrefCellMaxSize = maxSize; invalidate(); } } /************************************************ ************************************************/ void GridLayout::setCellMaximumHeight(int value) { Q_D(GridLayout); if (d->mPrefCellMaxSize.height() != value) { d->mPrefCellMaxSize.setHeight(value); invalidate(); } } /************************************************ ************************************************/ void GridLayout::setCellMaximumWidth(int value) { Q_D(GridLayout); if (d->mPrefCellMaxSize.width() != value) { d->mPrefCellMaxSize.setWidth(value); invalidate(); } } /************************************************ ************************************************/ void GridLayout::setCellFixedSize(QSize size) { Q_D(GridLayout); if (d->mPrefCellMinSize != size || d->mPrefCellMaxSize != size) { d->mPrefCellMinSize = size; d->mPrefCellMaxSize = size; invalidate(); } } /************************************************ ************************************************/ void GridLayout::setCellFixedHeight(int value) { Q_D(GridLayout); if (d->mPrefCellMinSize.height() != value || d->mPrefCellMaxSize.height() != value) { d->mPrefCellMinSize.setHeight(value); d->mPrefCellMaxSize.setHeight(value); invalidate(); } } /************************************************ ************************************************/ void GridLayout::setCellFixedWidth(int value) { Q_D(GridLayout); if (d->mPrefCellMinSize.width() != value || d->mPrefCellMaxSize.width() != value) { d->mPrefCellMinSize.setWidth(value); d->mPrefCellMaxSize.setWidth(value); invalidate(); } } /************************************************ ************************************************/ QSize GridLayout::sizeHint() const { Q_D(const GridLayout); if (!d->mIsValid) const_cast(d)->updateCache(); return QSize(d->cols() * d->mCellSizeHint.width(), d->rows() * d->mCellSizeHint.height()); } /************************************************ ************************************************/ void GridLayout::setGeometry(const QRect &geometry) { Q_D(GridLayout); const bool visual_h_reversed = parentWidget() && parentWidget()->isRightToLeft(); QLayout::setGeometry(geometry); const QPoint occupied_start = visual_h_reversed ? geometry.topRight() : geometry.topLeft(); d->mOccupiedGeometry.setTopLeft(occupied_start); d->mOccupiedGeometry.setBottomRight(occupied_start); if (!d->mIsValid) d->updateCache(); int y = geometry.top(); int x = geometry.left(); // For historical reasons QRect::right returns left() + width() - 1 // and QRect::bottom() returns top() + height() - 1; // So we use left() + height() and top() + height() // // http://qt-project.org/doc/qt-4.8/qrect.html const int maxX = geometry.left() + geometry.width(); const int maxY = geometry.top() + geometry.height(); const bool stretch_h = d->mStretch.testFlag(StretchHorizontal); const bool stretch_v = d->mStretch.testFlag(StretchVertical); const int cols = d->cols(); int itemWidth = 0; if (stretch_h && 0 < cols) itemWidth = qMin(geometry.width() / cols, d->mCellMaxSize.width()); else itemWidth = d->mCellSizeHint.width(); itemWidth = qBound(qMin(d->mPrefCellMinSize.width(), maxX), itemWidth, d->mPrefCellMaxSize.width()); const int widthRemain = stretch_h && 0 < itemWidth ? geometry.width() % itemWidth : 0; const int rows = d->rows(); int itemHeight = 0; if (stretch_v && 0 < rows) itemHeight = qMin(geometry.height() / rows, d->mCellMaxSize.height()); else itemHeight = d->mCellSizeHint.height(); itemHeight = qBound(qMin(d->mPrefCellMinSize.height(), maxY), itemHeight, d->mPrefCellMaxSize.height()); const int heightRemain = stretch_v && 0 < itemHeight ? geometry.height() % itemHeight : 0; #if 0 qDebug() << "** GridLayout::setGeometry *******************************"; qDebug() << "Geometry:" << geometry; qDebug() << "CellSize:" << d->mCellSizeHint; qDebug() << "Constraints:" << "min" << d->mPrefCellMinSize << "max" << d->mPrefCellMaxSize; qDebug() << "Count" << count(); qDebug() << "Cols:" << d->cols() << "(" << d->mColumnCount << ")"; qDebug() << "Rows:" << d->rows() << "(" << d->mRowCount << ")"; qDebug() << "Stretch:" << "h:" << (d->mStretch.testFlag(StretchHorizontal)) << " v:" << (d->mStretch.testFlag(StretchVertical)); qDebug() << "Item:" << "h:" << itemHeight << " w:" << itemWidth; #endif int remain_height = heightRemain; int remain_width = widthRemain; if (d->mDirection == LeftToRight) { int height = itemHeight + (0 < remain_height-- ? 1 : 0); for (QLayoutItem *item : qAsConst(d->mItems)) { if (!item->widget() || item->widget()->isHidden()) continue; int width = itemWidth + (0 < remain_width-- ? 1 : 0); if (x + width > maxX) { x = geometry.left(); y += height; height = itemHeight + (0 < remain_height-- ? 1 : 0); remain_width = widthRemain; } const int left = visual_h_reversed ? geometry.left() + geometry.right() - x - width + 1 : x; d->setItemGeometry(item, QRect(left, y, width, height)); x += width; } } else { int width = itemWidth + (0 < remain_width-- ? 1 : 0); for (QLayoutItem *item : qAsConst(d->mItems)) { if (!item->widget() || item->widget()->isHidden()) continue; int height = itemHeight + (0 < remain_height-- ? 1 : 0); if (y + height > maxY) { y = geometry.top(); x += width; width = itemWidth + (0 < remain_width-- ? 1 : 0); remain_height = heightRemain; } const int left = visual_h_reversed ? geometry.left() + geometry.right() - x - width + 1 : x; d->setItemGeometry(item, QRect(left, y, width, height)); y += height; } } d->mAnimate = false; } /************************************************ ************************************************/ QRect GridLayout::occupiedGeometry() const { return d_func()->mOccupiedGeometry; } ukui-panel/panel/comm_func.h0000644000175000017500000000425013632320722014767 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef _COMM_FUNC_H_ #define _COMM_FUNC_H_ //放公共功能函数 #include #include #include #include #include #include bool getRunCmdOutput(const char *command, char *output, int max_size); bool getReadFileContent(const char *file_path, char *output, int max_size); bool readSystemInfo(); bool isARM(); char* get_machine_id(); char* getOsVersion(); void startChildApp(const char *app_exe,char *argv_exec[]); const wchar_t* qstring2wchar_t(QString str); QString wchar2string(const wchar_t* wchar_str); void save_q_string_2_m_string(QString q_string, char **m_buf); QString time_2_string(time_t t); long int string_2_time(char *str_time); void deleteDirectory(QFileInfo fileList); void removefilesindir(const QString& path); bool removeDir(const QString & dirName); bool createDir(const char *sPathName); bool copyFileToPath(QString sourceDir ,QString toDir, QString copyFileToPath, bool coverFileIfExist); bool qCopyDirectory(const QDir& fromDir, const QDir& toDir, bool bCoverIfFileExists); char *getLoginCookie(char *userid); int getsrand(); int getPidByName(const char* pName); float get_pmem(pid_t pid); float get_pcpu(pid_t pid); #endif ukui-panel/panel/iukuipanel.h0000644000175000017500000001101713632320722015166 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef IUKUIPanel_H #define IUKUIPanel_H #include #include "ukuipanelglobals.h" class IUKUIPanelPlugin; class QWidget; /** **/ class UKUI_PANEL_API IUKUIPanel { public: /** * @brief Specifies the position of the panel on screen. */ enum Position{ PositionBottom, //!< The bottom side of the screen. PositionTop, //!< The top side of the screen. PositionLeft, //!< The left side of the screen. PositionRight //!< The right side of the screen. }; /** * @brief Returns the position of the panel. Possible values for the * return value are described by the Position enum. */ virtual Position position() const = 0; /** * @brief Returns the edge length of the icons that are shown on the panel * in pixels. The icons are square. */ virtual int iconSize() const = 0; virtual int panelSize() const = 0; /** * @brief Returns the number of lines/rows of this panel. */ virtual int lineCount() const = 0; /** * @brief Helper function for convenient direction/alignment checking. * @return True if the panel is on the top or the bottom of the * screen; otherwise returns false. */ bool isHorizontal() const { return position() == PositionBottom || position() == PositionTop; } /** * @brief Helper method that returns the global screen coordinates of the * panel, so you do not need to use QWidget::mapToGlobal() by yourself. * @return The QRect where the panel is located in global screen * coordinates. */ virtual QRect globalGeometry() const = 0; /** * @brief Helper method for calculating the global screen position of a * popup window with size windowSize. * @param absolutePos Contains the global screen coordinates where the * popup should be appear, i.e. the point where the user has clicked. * @param windowSize The size that the window will occupy. * @return The global screen position where the popup window can be shown. */ virtual QRect calculatePopupWindowPos(const QPoint &absolutePos, const QSize &windowSize) const = 0; /** * @brief Helper method for calculating the global screen position of a * popup window with size windowSize. The parameter plugin should be a * plugin * @param plugin Plugin that the popup window will belong to. The position * will be calculated according to the position of the plugin in the panel. * @param windowSize The size that the window will occupy. * @return The global screen position where the popup window can be shown. */ virtual QRect calculatePopupWindowPos(const IUKUIPanelPlugin *plugin, const QSize &windowSize) const = 0; /*! * \brief By calling this function, a plugin (or any other object) notifies the panel * about showing a (standalone) window/menu -> the panel needs this to avoid "hiding" in case any * standalone window is shown. The widget/window must be shown later than this notification call because * the panel needs to observe its show/hide/close events. * * \param w the window that will be shown * */ virtual void willShowWindow(QWidget * w) = 0; /*! * \brief By calling this function, a plugin notifies the panel about change of it's "static" * configuration * * \param plugin the changed plugin * * \sa IUKUIPanelPlugin::isSeparate(), IUKUIPanelPlugin::isExpandable */ virtual void pluginFlagsChanged(const IUKUIPanelPlugin * plugin) = 0; }; #endif // IUKUIPanel_H ukui-panel/panel/windownotifier.cpp0000644000175000017500000000412413633355350016431 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * Palo Kisa * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "windownotifier.h" #include #include void WindowNotifier::observeWindow(QWidget * w) { //installing the same filter object multiple times doesn't harm w->installEventFilter(this); } bool WindowNotifier::eventFilter(QObject * watched, QEvent * event) { QWidget * widget = qobject_cast(watched); //we're observing only QWidgetw auto it = std::lower_bound(mShownWindows.begin(), mShownWindows.end(), widget); switch (event->type()) { case QEvent::Close: watched->removeEventFilter(this); //no break case QEvent::Hide: Q_ASSERT(mShownWindows.end() != it); mShownWindows.erase(it); if (mShownWindows.isEmpty()) emit lastHidden(); break; case QEvent::Show: { const bool first_shown = mShownWindows.isEmpty(); mShownWindows.insert(it, widget); //we keep the mShownWindows sorted if (first_shown) emit firstShown(); } default: break; } return false; } ukui-panel/panel/pluginsettings.h0000644000175000017500000000515013633610704016103 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * Paulo Lieuthier * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef PLUGIN_SETTINGS_H #define PLUGIN_SETTINGS_H #include #include #include #include "ukuipanelglobals.h" namespace UKUi { class Settings; } class PluginSettingsFactory; class PluginSettingsPrivate; /*! * \brief * Settings for particular plugin. This object/class can be used similarly as \sa QSettings. * Object cannot be constructed direcly (it is the panel's responsibility to construct it for each plugin). * * * \note * We are relying here on so called "back linking" (calling a function defined in executable * back from an external library)... */ class UKUI_PANEL_API PluginSettings : public QObject { Q_OBJECT //for instantiation friend class PluginSettingsFactory; public: ~PluginSettings(); QString group() const; QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const; void setValue(const QString &key, const QVariant &value); void remove(const QString &key); bool contains(const QString &key) const; QList > readArray(const QString &prefix); void setArray(const QString &prefix, const QList > &hashList); void clear(); void sync(); QStringList allKeys() const; QStringList childGroups() const; void beginGroup(const QString &subGroup); void endGroup(); void loadFromCache(); Q_SIGNALS: void settingsChanged(); private: explicit PluginSettings(UKUi::Settings *settings, const QString &group, QObject *parent = nullptr); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(PluginSettings) }; #endif ukui-panel/panel/pluginsettings.cpp0000644000175000017500000001333713633355350016447 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * Paulo Lieuthier * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "pluginsettings.h" #include "pluginsettings_p.h" //#include #include "common/ukuisettings.h" class PluginSettingsPrivate { public: PluginSettingsPrivate(UKUi::Settings* settings, const QString &group) : mSettings(settings) , mOldSettings(settings) , mGroup(group) { } QString prefix() const; inline QString fullPrefix() const { return mGroup + "/" + prefix(); } UKUi::Settings *mSettings; UKUi::SettingsCache mOldSettings; QString mGroup; QStringList mSubGroups; }; QString PluginSettingsPrivate::prefix() const { if (!mSubGroups.empty()) return mSubGroups.join('/'); return QString(); } PluginSettings::PluginSettings(UKUi::Settings* settings, const QString &group, QObject *parent) : QObject(parent) , d_ptr(new PluginSettingsPrivate{settings, group}) { Q_D(PluginSettings); connect(d->mSettings, &UKUi::Settings::settingsChangedFromExternal, this, &PluginSettings::settingsChanged); } QString PluginSettings::group() const { Q_D(const PluginSettings); return d->mGroup; } PluginSettings::~PluginSettings() { } QVariant PluginSettings::value(const QString &key, const QVariant &defaultValue) const { Q_D(const PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); QVariant value = d->mSettings->value(key, defaultValue); d->mSettings->endGroup(); return value; } void PluginSettings::setValue(const QString &key, const QVariant &value) { Q_D(PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); d->mSettings->setValue(key, value); d->mSettings->endGroup(); emit settingsChanged(); } void PluginSettings::remove(const QString &key) { Q_D(PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); d->mSettings->remove(key); d->mSettings->endGroup(); emit settingsChanged(); } bool PluginSettings::contains(const QString &key) const { Q_D(const PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); bool ret = d->mSettings->contains(key); d->mSettings->endGroup(); return ret; } QList > PluginSettings::readArray(const QString& prefix) { Q_D(PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); QList > array; int size = d->mSettings->beginReadArray(prefix); for (int i = 0; i < size; ++i) { d->mSettings->setArrayIndex(i); QMap hash; const auto keys = d->mSettings->childKeys(); for (const QString &key : keys) hash[key] = d->mSettings->value(key); array << hash; } d->mSettings->endArray(); d->mSettings->endGroup(); return array; } void PluginSettings::setArray(const QString &prefix, const QList > &hashList) { Q_D(PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); d->mSettings->beginWriteArray(prefix); int size = hashList.size(); for (int i = 0; i < size; ++i) { d->mSettings->setArrayIndex(i); QMapIterator it(hashList.at(i)); while (it.hasNext()) { it.next(); d->mSettings->setValue(it.key(), it.value()); } } d->mSettings->endArray(); d->mSettings->endGroup(); emit settingsChanged(); } void PluginSettings::clear() { Q_D(PluginSettings); d->mSettings->beginGroup(d->mGroup); d->mSettings->clear(); d->mSettings->endGroup(); emit settingsChanged(); } void PluginSettings::sync() { Q_D(PluginSettings); d->mSettings->beginGroup(d->mGroup); d->mSettings->sync(); d->mOldSettings.loadFromSettings(); d->mSettings->endGroup(); emit settingsChanged(); } QStringList PluginSettings::allKeys() const { Q_D(const PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); QStringList keys = d->mSettings->allKeys(); d->mSettings->endGroup(); return keys; } QStringList PluginSettings::childGroups() const { Q_D(const PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); QStringList groups = d->mSettings->childGroups(); d->mSettings->endGroup(); return groups; } void PluginSettings::beginGroup(const QString &subGroup) { Q_D(PluginSettings); d->mSubGroups.append(subGroup); } void PluginSettings::endGroup() { Q_D(PluginSettings); if (!d->mSubGroups.empty()) d->mSubGroups.removeLast(); } void PluginSettings::loadFromCache() { Q_D(PluginSettings); d->mSettings->beginGroup(d->mGroup); d->mOldSettings.loadToSettings(); d->mSettings->endGroup(); } PluginSettings* PluginSettingsFactory::create(UKUi::Settings *settings, const QString &group, QObject *parent/* = nullptr*/) { return new PluginSettings{settings, group, parent}; } ukui-panel/NEWS0000644000175000017500000000013213633610704012246 0ustar fengfeng### ukui-panel 2.0.0 * fork from lxqt-panel ### ukui-panel 1.0.0 * Initial release. ukui-panel/plugin-segmentation/0000755000175000017500000000000013633355350015547 5ustar fengfengukui-panel/plugin-segmentation/segmentation.h0000644000175000017500000000425613633355350020424 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include "../panel/plugin.h" #include "../panel/ukuipanel.h" //#include "../panel/config/configpaneldialog.h" #include "../panel/config/configpanelwidget.h" #include #define DEFAULT_SHORTCUT "Alt+F1" class Segmentation : public QObject, public IUKUIPanelPlugin { Q_OBJECT public: Segmentation(const IUKUIPanelPluginStartupInfo &startupInfo); ~Segmentation(); virtual QWidget *widget() { return &mButton; } virtual QString themeId() const { return QStringLiteral("segmentation"); } void realign(); virtual IUKUIPanelPlugin::Flags flags() const { return PreferRightAlignment | HaveConfigDialog ; } private: //StartMenuWidget mWidget; //QWidget mWidget; IUKUIPanelPlugin *mPlugin; QToolButton mButton; bool mCapturing; private slots: void captureMouse(); }; class StartMenuLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new Segmentation(startupInfo); } }; #endif ukui-panel/plugin-segmentation/segmentation.cpp0000644000175000017500000001123713633355350020754 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #define DESKTOP_HEIGHT (12) #define DESKTOP_WIDTH (30) Segmentation::Segmentation(const IUKUIPanelPluginStartupInfo &startupInfo) : QObject(), IUKUIPanelPlugin(startupInfo) { mButton.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); mButton.setAutoRaise(true); realign(); mCapturing = false; // connect(&mButton, SIGNAL(clicked()), this, SLOT(captureMouse())); // mButton.setFixedSize(DESKTOP_HEIGHT,DESKTOP_WIDTH); // mButton.setStyleSheet( // //正常状态样式 // "QToolButton{" // /*"background-color:rgba(100,225,100,80%);"//背景色(也可以设置图片)*/ // "qproperty-icon:url(/usr/share/ukui-panel/plugin-segmentation/img/segmentation.svg);" // "qproperty-iconSize:40px 40px;" // "border-style:outset;" //边框样式(inset/outset) // "border-width:0px;" //边框宽度像素 // "border-radius:0px;" //边框圆角半径像素 // "border-color:rgba(255,255,255,30);" //边框颜色 // "font:SimSun 14px;" //字体,字体大小 // "color:rgba(0,0,0,100);" //字体颜色 // "padding:0px;" //填衬 // "border-bottom-style:solid" // "}" // ); } Segmentation::~Segmentation() { } void Segmentation::realign() { if(panel()->isHorizontal()) { mButton.setFixedSize(DESKTOP_HEIGHT,DESKTOP_WIDTH); mButton.setStyleSheet( //正常状态样式 "QToolButton{" /*"background-color:rgba(100,225,100,80%);"//背景色(也可以设置图片)*/ "qproperty-icon:url(/usr/share/ukui-panel/plugin-segmentation/img/segmentation.svg);" "qproperty-iconSize:40px 40px;" "border-style:outset;" //边框样式(inset/outset) "border-width:0px;" //边框宽度像素 "border-radius:0px;" //边框圆角半径像素 "border-color:rgba(255,255,255,30);" //边框颜色 "font:SimSun 14px;" //字体,字体大小 "color:rgba(0,0,0,100);" //字体颜色 "padding:0px;" //填衬 "border-bottom-style:solid" "}" ); } else { mButton.setFixedSize(DESKTOP_WIDTH,DESKTOP_HEIGHT); mButton.setStyleSheet( //正常状态样式 "QToolButton{" /*"background-color:rgba(100,225,100,80%);"//背景色(也可以设置图片)*/ "qproperty-icon:url(/usr/share/ukui-panel/plugin-segmentation/img/segmentationh.svg);" "qproperty-iconSize:40px 40px;" "border-style:outset;" //边框样式(inset/outset) "border-width:0px;" //边框宽度像素 "border-radius:0px;" //边框圆角半径像素 "border-color:rgba(255,255,255,30);" //边框颜色 "font:SimSun 14px;" //字体,字体大小 "color:rgba(0,0,0,100);" //字体颜色 "padding:0px;" //填衬 "border-bottom-style:solid" "}" ); } } void Segmentation::captureMouse() { } ukui-panel/plugin-segmentation/img/0000755000175000017500000000000013632320722016315 5ustar fengfengukui-panel/plugin-segmentation/img/segmentation.svg0000644000175000017500000000076513632320722021543 0ustar fengfeng ukui-panel/plugin-segmentation/img/segmentationh.svg0000644000175000017500000000076513632320722021713 0ustar fengfeng ukui-panel/plugin-segmentation/resources/0000755000175000017500000000000013632320722017553 5ustar fengfengukui-panel/plugin-segmentation/resources/segmentation.desktop.in0000644000175000017500000000016413632320722024251 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Segmentation Comment=Segmentation Icon=segmentation ukui-panel/plugin-segmentation/CMakeLists.txt0000644000175000017500000000072413632320722020304 0ustar fengfengset(PLUGIN "segmentation") set(HEADERS segmentation.h ) set(SOURCES segmentation.cpp ) set(UIS ) set(LIBRARIES Qt5Xdg ) install(FILES img/segmentation.svg img/segmentationh.svg DESTINATION "${PACKAGE_DATA_DIR}/plugin-segmentation/img" COMPONENT Runtime ) set(UKUI_TRANSLATIONS_DAT "/usr/local/share/") file(GLOB UKUI_TRANSLATIONS_SOURCE ${UKUI_TRANSLATIONS_DAT}ukui/translations/ukui-panel/ukui-panel_zh_CN.qm ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel/plugin-tray/0000755000175000017500000000000013643566146014041 5ustar fengfengukui-panel/plugin-tray/xfitman.h0000644000175000017500000000603613632320722015647 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Christopher "VdoP" Regali * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIXFITMAN_H #define UKUIXFITMAN_H #include /** * @file xfitman.h * @author Christopher "VdoP" Regali * @brief handles all of our xlib-calls. */ /** * @brief manages the Xlib apicalls */ class XfitMan { public: XfitMan(); ~XfitMan(); static Atom atom(const char* atomName); void moveWindow(Window _win, int _x, int _y) const; void raiseWindow(Window _wid) const; void resizeWindow(Window _wid, int _width, int _height) const; void closeWindow(Window _wid) const; bool getClientIcon(Window _wid, QPixmap& _pixreturn) const; bool getClientIcon(Window _wid, QIcon *icon) const; void setIconGeometry(Window _wid, QRect* rect = 0) const; QString getWindowTitle(Window _wid) const; QString getApplicationName(Window _wid) const; int clientMessage(Window _wid, Atom _msg, long unsigned int data0, long unsigned int data1 = 0, long unsigned int data2 = 0, long unsigned int data3 = 0, long unsigned int data4 = 0) const; private: /** \warning Do not forget to XFree(result) after data are processed! */ bool getWindowProperty(Window window, Atom atom, // property Atom reqType, // req_type unsigned long* resultLen,// nitems_return unsigned char** result // prop_return ) const; /** \warning Do not forget to XFree(result) after data are processed! */ bool getRootWindowProperty(Atom atom, // property Atom reqType, // req_type unsigned long* resultLen,// nitems_return unsigned char** result // prop_return ) const; Window root; //the actual root window on the used screen }; const XfitMan& xfitMan(); #endif // UKUIXFITMAN_H ukui-panel/plugin-tray/trayappnitify.cpp0000644000175000017500000000000013640356061017424 0ustar fengfengukui-panel/plugin-tray/traystorage.cpp0000644000175000017500000001403713642614010017075 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ /******************************************************************** Inspired by freedesktops tint2 ;) *********************************************************************/ #include #include #include #include #include "trayicon.h" #include "../panel/iukuipanel.h" #include "../panel/common/ukuigridlayout.h" #include "traystorage.h" #include "xfitman.h" #include #include #include #include #include #include #include #undef Bool // defined as int in X11/Xlib.h #include "../panel/iukuipanelplugin.h" #include #include #define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0 #define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1 #define SYSTEM_TRAY_REQUEST_DOCK 0 #define SYSTEM_TRAY_BEGIN_MESSAGE 1 #define SYSTEM_TRAY_CANCEL_MESSAGE 2 #define XEMBED_EMBEDDED_NOTIFY 0 #define XEMBED_MAPPED (1 << 0) TrayStorageStatus storagestatus=HIDE; /************************************************ ************************************************/ TrayStorage::TrayStorage( QWidget *parent): QFrame(parent), mValid(false), mTrayId(0), mDamageEvent(0), mDamageError(0), mIconSize(TRAY_ICON_SIZE_DEFAULT, TRAY_ICON_SIZE_DEFAULT), mDisplay(QX11Info::display()) { mLayout = new UKUi::GridLayout(this); mLayout->setColumnCount(3); mLayout->setRowCount(3); setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 setWindowFlags(/*Qt::FramelessWindowHint |*/ /*Qt::WindowStaysOnTopHint |*/ Qt::ToolTip); _NET_SYSTEM_TRAY_OPCODE = XfitMan::atom("_NET_SYSTEM_TRAY_OPCODE"); } /************************************************ ************************************************/ TrayStorage::~TrayStorage() { stopTrayStorage(); } void TrayStorage::stopTrayStorage() { for (auto & icon : mIcons) disconnect(icon, &QObject::destroyed, this, &TrayStorage::onIconDestroyed); qDeleteAll(mIcons); if (mTrayId) { XDestroyWindow(mDisplay, mTrayId); mTrayId = 0; } mValid = false; } bool TrayStorage::nativeEventFilter(const QByteArray &eventType, void *message, long *) { if (eventType != "xcb_generic_event_t") return false; xcb_generic_event_t* event = static_cast(message); TrayIcon* icon; int event_type = event->response_type & ~0x80; return false; } void TrayStorage::setIconSize(QSize iconSize) { mIconSize = iconSize; unsigned long size = qMin(mIconSize.width(), mIconSize.height()); XChangeProperty(mDisplay, mTrayId, XfitMan::atom("_NET_SYSTEM_TRAY_ICON_SIZE"), XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&size, 1); } /************************************************ ************************************************/ VisualID TrayStorage::getVisual() { VisualID visualId = 0; Display* dsp = mDisplay; XVisualInfo templ; templ.screen=QX11Info::appScreen(); templ.depth=32; templ.c_class=TrueColor; int nvi; XVisualInfo* xvi = XGetVisualInfo(dsp, VisualScreenMask|VisualDepthMask|VisualClassMask, &templ, &nvi); if (xvi) { int i; XRenderPictFormat* format; for (i = 0; i < nvi; i++) { format = XRenderFindVisualFormat(dsp, xvi[i].visual); if (format && format->type == PictTypeDirect && format->direct.alphaMask) { visualId = xvi[i].visualid; break; } } XFree(xvi); } return visualId; } void TrayStorage::onIconDestroyed(QObject * icon) { //in the time QOjbect::destroyed is emitted, the child destructor //is already finished, so the qobject_cast to child will return nullptr in all cases mIcons.removeAll(static_cast(icon)); } /************************************************ ************************************************/ void TrayStorage::mouseReleaseEvent(QMouseEvent *event) { storagestatus = HIDE; this->hide(); update(); QWidget::mouseReleaseEvent(event); } void TrayStorage::mousePressEvent(QMouseEvent *event) { update(); QWidget::mousePressEvent(event); } void TrayStorage::leaveEvent(QEvent *) { // tra= HIDE; } void TrayStorage::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); p.setBrush(QBrush(QColor(0x13,0x14,0x14,0xb2))); p.setPen(Qt::NoPen); p.setRenderHint(QPainter::Antialiasing); // 反锯齿; p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, this); } /* 点击窗口之外的部分隐藏 */ bool TrayStorage:: event(QEvent *event) { if (event->type() == QEvent::ActivationChange) { if (QApplication::activeWindow() != this) { hide(); storagestatus=HIDE; } } return QWidget::event(event); } ukui-panel/plugin-tray/resources/0000755000175000017500000000000013632320722016035 5ustar fengfengukui-panel/plugin-tray/resources/tray.desktop.in0000644000175000017500000000027113632320722021014 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=System tray Comment=Display applications minimized to the system tray. Icon=go-bottom #TRANSLATIONS_DIR=../translations ukui-panel/plugin-tray/ukuitray.cpp0000644000175000017500000006411013643566146016424 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ /******************************************************************** Inspired by freedesktops tint2 ;) *********************************************************************/ /* * Some code in this file is commented but not deleted * because these commented codes are the old loading trayApp * I want to wait until the new version loading trayApp is stable before deleting */ #include #include #include #include #include "trayicon.h" #include "../panel/iukuipanel.h" #include "../panel/common/ukuigridlayout.h" #include "ukuitray.h" #include "xfitman.h" #include #include #include #include #include #include #include #undef Bool // defined as int in X11/Xlib.h #include "../panel/iukuipanelplugin.h" #include "traystorage.h" //#include "../panel/customstyle.h" #include #include #include #define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0 #define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1 #define SYSTEM_TRAY_REQUEST_DOCK 0 #define SYSTEM_TRAY_BEGIN_MESSAGE 1 #define SYSTEM_TRAY_CANCEL_MESSAGE 2 #define XEMBED_EMBEDDED_NOTIFY 0 #define XEMBED_MAPPED (1 << 0) /* qt会将glib里的signals成员识别为宏,所以取消该宏 * 后面如果用到signals时,使用Q_SIGNALS代替即可 **/ #ifdef signals #undef signals #endif extern "C" { #include #include #include } #define KEYBINDINGS_CUSTOM_SCHEMA "org.ukui.panel.tray" #define KEYBINDINGS_CUSTOM_DIR "/org/ukui/tray/keybindings/" #define MAX_CUSTOM_SHORTCUTS 30 #define ACTION_KEY "action" #define RECORD_KEY "record" #define BINDING_KEY "binding" #define NAME_KEY "name" /************************************************ ************************************************/ extern TrayStorageStatus storagestatus; storageBarStatus storagebarstatus; bool flag; UKUITray::UKUITray(IUKUIPanelPlugin *plugin, QWidget *parent): QFrame(parent), mValid(false), mTrayId(0), mDamageEvent(0), mDamageError(0), mIconSize(TRAY_ICON_SIZE_DEFAULT, TRAY_ICON_SIZE_DEFAULT), mPlugin(plugin), mDisplay(QX11Info::display()) { storagebarstatus=ST_HIDE; flag =false; mLayout = new UKUi::GridLayout(this); _NET_SYSTEM_TRAY_OPCODE = XfitMan::atom("_NET_SYSTEM_TRAY_OPCODE"); // Init the selection later just to ensure that no signals are sent until // after construction is done and the creating object has a chance to connect. QTimer::singleShot(0, this, SLOT(startTray())); bt=new QToolButton(); bt->setStyle(new CustomStyle()); bt->setIcon(QIcon("/usr/share/ukui-panel/panel/img/up.svg")); layout()->addWidget(bt); storageFrame=new UKUIStorageFrame; // storageFrame->setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 //setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint| Qt::X11BypassWindowManagerHint); storageLayout=new UKUi::GridLayout(storageFrame); storageLayout->setColumnCount(3); storageLayout->setRowCount(3); // tys= new TrayStorage(); connect(bt,SIGNAL(clicked()),this,SLOT(storageBar())); realign(); } /************************************************ ************************************************/ UKUITray::~UKUITray() { freezeApp(); stopTray(); } void UKUITray::storageBar() { QCursor::pos(); #define STORAGE_POSITION_BOTTOM_X QCursor::pos().x()-120 #define STORAGE_POSITION_BOTTOM_Y QCursor::pos().y()-115 #define STORAGE_POSITION_UP_X QCursor::pos().x()-120 #define STORAGE_POSITION_UP_Y QCursor::pos().y()+20 #define STORAGE_POSITION_LEFT_X QCursor::pos().x()+40 #define STORAGE_POSITION_LEFT_Y QCursor::pos().y()-20 #define STORAGE_POSITION_RIGHT_X QCursor::pos().x()-150 #define STORAGE_POSITION_RIGHT_Y QCursor::pos().y()-70 #define STORAGE_HIGHT 90 #define STORAGE_WIDGH 140 switch (mPlugin->panel()->position()){ case 0: storageFrame->setGeometry(STORAGE_POSITION_BOTTOM_X,STORAGE_POSITION_BOTTOM_Y,STORAGE_WIDGH,STORAGE_HIGHT); break; case 1: storageFrame->setGeometry(STORAGE_POSITION_UP_X,STORAGE_POSITION_UP_Y,STORAGE_WIDGH,STORAGE_HIGHT); break; case 2: storageFrame->setGeometry(STORAGE_POSITION_LEFT_X,STORAGE_POSITION_LEFT_Y,STORAGE_WIDGH,STORAGE_HIGHT); break; case 3: storageFrame->setGeometry(STORAGE_POSITION_RIGHT_X,STORAGE_POSITION_RIGHT_Y,STORAGE_WIDGH,STORAGE_HIGHT); break; default: break; } switch(flag) { case ST_HIDE: storageFrame->show(); flag=true; break; case ST_SHOW: storageFrame->hide(); flag=false; break; default: break; } } /************************************************ ************************************************/ bool UKUITray::nativeEventFilter(const QByteArray &eventType, void *message, long *) { if (eventType != "xcb_generic_event_t") return false; xcb_generic_event_t* event = static_cast(message); TrayIcon* icon; int event_type = event->response_type & ~0x80; switch (event_type) { case ClientMessage: clientMessageEvent(event); break; // case ConfigureNotify: // icon = findIcon(event->xconfigure.window); // if (icon) // icon->configureEvent(&(event->xconfigure)); // break; case DestroyNotify: { unsigned long event_window; event_window = reinterpret_cast(event)->window; icon = findIcon(event_window); if (icon) { icon->windowDestroyed(event_window); mIcons.removeAll(icon); mStorageIcons.removeAll(icon); delete icon; } break; } default: if (event_type == mDamageEvent + XDamageNotify) { xcb_damage_notify_event_t* dmg = reinterpret_cast(event); icon = findIcon(dmg->drawable); if (icon) icon->update(); } break; } return false; } /************************************************ ************************************************/ void UKUITray::realign() { mLayout->setEnabled(false); // set tray apps size ,but it always doesn't work // mIconSize=QSize(mPlugin->panel()->iconSize()/2,mPlugin->panel()->iconSize()/2); IUKUIPanel *panel = mPlugin->panel(); switch(panel->position()) { case 0: mLayout->setRowCount(panel->lineCount()); mLayout->setColumnCount(0); // bt->setIcon(QIcon("/usr/share/ukui-panel/panel/img/up.svg")); break; case 1: mLayout->setRowCount(panel->lineCount()); mLayout->setColumnCount(0); // bt->setIcon(QIcon("/usr/share/ukui-panel/panel/img/up.svg")); break; case 2: mLayout->setColumnCount(panel->lineCount()); mLayout->setRowCount(0); // bt->setIcon(QIcon("/usr/share/ukui-panel/panel/img/up.svg")); break; case 3: mLayout->setColumnCount(panel->lineCount()); mLayout->setRowCount(0); // bt->setIcon(QIcon("/usr/share/ukui-panel/panel/img/up.svg")); break; default: break; } mLayout->setEnabled(true); } /************************************************ ************************************************/ void UKUITray::clientMessageEvent(xcb_generic_event_t *e) { unsigned long opcode; unsigned long message_type; Window id; xcb_client_message_event_t* event = reinterpret_cast(e); uint32_t* data32 = event->data.data32; message_type = event->type; opcode = data32[1]; if(message_type != _NET_SYSTEM_TRAY_OPCODE) return; switch (opcode) { case SYSTEM_TRAY_REQUEST_DOCK: id = data32[2]; if(id){ regulateIcon(&id); } case SYSTEM_TRAY_BEGIN_MESSAGE: case SYSTEM_TRAY_CANCEL_MESSAGE: qDebug() << "we don't show balloon messages."; break; default: // if (opcode == xfitMan().atom("_NET_SYSTEM_TRAY_MESSAGE_DATA")) // qDebug() << "message from dockapp:" << e->data.b; // else // qDebug() << "SYSTEM_TRAY : unknown message type" << opcode; break; } } /************************************************ ************************************************/ TrayIcon* UKUITray::findIcon(Window id) { for(TrayIcon* icon : qAsConst(mIcons) ) { if (icon->iconId() == id || icon->windowId() == id) return icon; } // for(TrayIcon* storageicon :qAsConst(mStorageIcons)) // { // if (storageicon->iconId() == id || storageicon->windowId() == id) // return storageicon; // } return 0; } TrayIcon* UKUITray::findStorageIcon(Window id) { for(TrayIcon* storageicon :qAsConst(mStorageIcons)) { if (storageicon->iconId() == id || storageicon->windowId() == id) return storageicon; } return 0; } /************************************************ ************************************************/ void UKUITray::setIconSize(QSize iconSize) { mIconSize = iconSize; unsigned long size = qMin(mIconSize.width(), mIconSize.height()); XChangeProperty(mDisplay, mTrayId, XfitMan::atom("_NET_SYSTEM_TRAY_ICON_SIZE"), XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&size, 1); } /************************************************ ************************************************/ VisualID UKUITray::getVisual() { VisualID visualId = 0; Display* dsp = mDisplay; XVisualInfo templ; templ.screen=QX11Info::appScreen(); templ.depth=32; templ.c_class=TrueColor; int nvi; XVisualInfo* xvi = XGetVisualInfo(dsp, VisualScreenMask|VisualDepthMask|VisualClassMask, &templ, &nvi); if (xvi) { int i; XRenderPictFormat* format; for (i = 0; i < nvi; i++) { format = XRenderFindVisualFormat(dsp, xvi[i].visual); if (format && format->type == PictTypeDirect && format->direct.alphaMask) { visualId = xvi[i].visualid; break; } } XFree(xvi); } return visualId; } /************************************************ freedesktop systray specification ************************************************/ void UKUITray::startTray() { Display* dsp = mDisplay; Window root = QX11Info::appRootWindow(); QString s = QString("_NET_SYSTEM_TRAY_S%1").arg(DefaultScreen(dsp)); Atom _NET_SYSTEM_TRAY_S = XfitMan::atom(s.toLatin1()); //this limit the tray apps | will not run more Same apps // if (XGetSelectionOwner(dsp, _NET_SYSTEM_TRAY_S) != None) // { // qWarning() << "Another systray is running"; // mValid = false; // return; // } // init systray protocol mTrayId = XCreateSimpleWindow(dsp, root, -1, -1, 1, 1, 0, 0, 0); XSetSelectionOwner(dsp, _NET_SYSTEM_TRAY_S, mTrayId, CurrentTime); if (XGetSelectionOwner(dsp, _NET_SYSTEM_TRAY_S) != mTrayId) { qWarning() << "Can't get systray manager"; stopTray(); mValid = false; return; } int orientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ; XChangeProperty(dsp, mTrayId, XfitMan::atom("_NET_SYSTEM_TRAY_ORIENTATION"), XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &orientation, 1); // ** Visual ******************************** VisualID visualId = getVisual(); if (visualId) { XChangeProperty(mDisplay, mTrayId, XfitMan::atom("_NET_SYSTEM_TRAY_VISUAL"), XA_VISUALID, 32, PropModeReplace, (unsigned char*)&visualId, 1); } XClientMessageEvent ev; ev.type = ClientMessage; ev.window = root; ev.message_type = XfitMan::atom("MANAGER"); ev.format = 32; ev.data.l[0] = CurrentTime; ev.data.l[1] = _NET_SYSTEM_TRAY_S; ev.data.l[2] = mTrayId; ev.data.l[3] = 0; ev.data.l[4] = 0; XSendEvent(dsp, root, False, StructureNotifyMask, (XEvent*)&ev); XDamageQueryExtension(mDisplay, &mDamageEvent, &mDamageError); mValid = true; qApp->installNativeEventFilter(this); } /************************************************ ************************************************/ void UKUITray::stopTray() { for (auto & icon : mIcons) disconnect(icon, &QObject::destroyed, this, &UKUITray::onIconDestroyed); qDeleteAll(mIcons); if (mTrayId) { XDestroyWindow(mDisplay, mTrayId); mTrayId = 0; } mValid = false; } void UKUITray::stopStorageTray() { for (auto & icon : mStorageIcons) disconnect(icon, &QObject::destroyed, this, &UKUITray::onIconDestroyed); qDeleteAll(mStorageIcons); if (mTrayId) { XDestroyWindow(mDisplay, mTrayId); mTrayId = 0; } } /************************************************ ************************************************/ void UKUITray::onIconDestroyed(QObject * icon) { //in the time QOjbect::destroyed is emitted, the child destructor //is already finished, so the qobject_cast to child will return nullptr in all cases qDebug()<<"tray icon destroy"; mIcons.removeAll(static_cast(icon)); mStorageIcons.removeAll(static_cast(icon)); } void UKUITray::freezeTrayApp(Window winId) { QList existsPath = listExistsPath(); int bingdingStr; for (char * path : existsPath) { QString p =KEYBINDINGS_CUSTOM_DIR; std::string str = p.toStdString(); const int len = str.length(); char * prepath = new char[len+1]; strcpy(prepath,str.c_str()); char * allpath = strcat(prepath, path); const QByteArray ba(KEYBINDINGS_CUSTOM_SCHEMA); const QByteArray bba(allpath); QGSettings *settings; const QByteArray id(KEYBINDINGS_CUSTOM_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { settings= new QGSettings(ba, bba,this); bingdingStr=settings->get(BINDING_KEY).toInt(); if(winId==bingdingStr) { settings->set(ACTION_KEY,"freeze"); } } delete settings; } } /************************************************ ************************************************/ void UKUITray::addIcon(Window winId) { // decline to add an icon for a window we already manage TrayIcon *icon = findIcon(winId); if(icon) return; else icon = new TrayIcon(winId, mIconSize, this); mIcons.append(icon); mLayout->addWidget(icon); connect(icon,&QObject::destroyed,icon,&TrayIcon::notifyAppFreeze); connect(icon,&TrayIcon::notifyTray,this,&UKUITray::freezeTrayApp); connect(icon, &QObject::destroyed, this, &UKUITray::onIconDestroyed); } void UKUITray::storageAddIcon(Window winId) { TrayIcon *storageicon = findStorageIcon(winId); if(storageicon) return; else storageicon = new TrayIcon(winId, mIconSize, this); mStorageIcons.append(storageicon); storageLayout->addWidget(storageicon); connect(storageicon,&QObject::destroyed,storageicon,&TrayIcon::notifyAppFreeze); connect(storageicon,&TrayIcon::notifyTray,this,&UKUITray::freezeTrayApp); connect(storageicon, &QObject::destroyed, this, &UKUITray::onIconDestroyed); } void UKUITray::moveIconToTray(Window winId) { TrayIcon *storageicon = findStorageIcon(winId); if(!storageicon) return; else mStorageIcons.removeOne(storageicon); storageLayout->removeWidget(storageicon); mIcons.append(storageicon); mLayout->addWidget(storageicon); connect(storageicon,&QObject::destroyed,storageicon,&TrayIcon::notifyAppFreeze); connect(storageicon,&TrayIcon::notifyTray,this,&UKUITray::freezeTrayApp); connect(storageicon, &QObject::destroyed, this, &UKUITray::onIconDestroyed); } void UKUITray::moveIconToStorage(Window winId) { TrayIcon *icon = findIcon(winId); if(!icon) return; else mLayout->removeWidget(icon); mIcons.removeOne(icon); mStorageIcons.append(icon); storageLayout->addWidget(icon); connect(icon,&QObject::destroyed,icon,&TrayIcon::notifyAppFreeze); connect(icon,&TrayIcon::notifyTray,this,&UKUITray::freezeTrayApp); connect(icon, &QObject::destroyed, this, &UKUITray::onIconDestroyed); } QList UKUITray::listExistsPath(){ char ** childs; int len; DConfClient * client = dconf_client_new(); childs = dconf_client_list (client, KEYBINDINGS_CUSTOM_DIR, &len); g_object_unref (client); QList vals; for (int i = 0; childs[i] != NULL; i++){ if (dconf_is_rel_dir (childs[i], NULL)){ char * val = g_strdup (childs[i]); vals.append(val); } } g_strfreev (childs); return vals; } void UKUITray::regulateIcon(Window *mid) { int wid=(int)*mid; int count=0; QList existsPath = listExistsPath(); QString actionStr; int bingdingStr; QString nameStr; //匹配表中存在的name与该wid的name,若相等则用新的wid覆盖旧的wid,否则在表中添加新的路径,写上新的wid,name,以及状态。 for (char * path : existsPath){ QString p =KEYBINDINGS_CUSTOM_DIR; std::string str = p.toStdString(); const int len = str.length(); char * prepath = new char[len+1]; strcpy(prepath,str.c_str()); char * allpath = strcat(prepath, path); const QByteArray ba(KEYBINDINGS_CUSTOM_SCHEMA); const QByteArray bba(allpath); QGSettings *settings; const QByteArray id(KEYBINDINGS_CUSTOM_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { settings= new QGSettings(ba, bba,this); settings->set(ACTION_KEY,settings->get(RECORD_KEY).toString()); actionStr = settings->get(ACTION_KEY).toString(); nameStr = settings->get(NAME_KEY).toString(); if(nameStr==xfitMan().getApplicationName(wid)) { settings->set(BINDING_KEY, wid); bingdingStr=wid; if(QString::compare(actionStr,"tray")==0){ addIcon(bingdingStr); } if(QString::compare(actionStr,"storage")==0){ storageAddIcon(bingdingStr); } // else // return; connect(settings, &QGSettings::changed, this, [=] (const QString &key) { if(key=="action"){ if(QString::compare(settings->get(ACTION_KEY).toString(),"tray")==0){ moveIconToTray(bingdingStr); } else if(QString::compare(settings->get(ACTION_KEY).toString(),"storage")==0){ moveIconToStorage(bingdingStr); } else if(QString::compare(settings->get(ACTION_KEY).toString(),"freeze")==0){ } } }); break; } } count++; } if(count>=existsPath.count()) { QString availablepath = findFreePath(); const QByteArray id(KEYBINDINGS_CUSTOM_SCHEMA); const QByteArray idd(availablepath.toUtf8().data()); QGSettings *newsetting; const QByteArray keyid(KEYBINDINGS_CUSTOM_SCHEMA); if(QGSettings::isSchemaInstalled(keyid)) { newsetting=new QGSettings(id,idd); newsetting->set(BINDING_KEY,wid); newsetting->set(NAME_KEY,xfitMan().getApplicationName(wid)); QStringList trayIconNameList; trayIconNameList<<"ukui-volume-control-applet-qt"<<"kylin-nm"<<"ukui-sidebar"<<"indicator-china-weather"; if(trayIconNameList.contains(xfitMan().getApplicationName(wid))) { newsetting->set(ACTION_KEY,"tray"); newsetting->set(RECORD_KEY,"tray"); addIcon(wid); } else { newsetting->set(ACTION_KEY,"storage"); newsetting->set(RECORD_KEY,"storage"); storageAddIcon(wid); } } delete newsetting; QGSettings* settings; const QByteArray keyId(KEYBINDINGS_CUSTOM_SCHEMA); if(QGSettings::isSchemaInstalled(keyId)) { settings= new QGSettings(id, idd,this); connect(settings, &QGSettings::changed, this, [=] (const QString &key) { if(key=="action") { if(QString::compare(settings->get(ACTION_KEY).toString(),"tray")==0) { moveIconToTray(wid); } else if(QString::compare(settings->get(ACTION_KEY).toString(),"storage")==0){ moveIconToStorage(wid); } } }); } count++; } } void UKUITray::freezeApp() { QList existsPath = listExistsPath(); for (char * path : existsPath){ QString p =KEYBINDINGS_CUSTOM_DIR; std::string str = p.toStdString(); const int len = str.length(); char * prepath = new char[len+1]; strcpy(prepath,str.c_str()); char * allpath = strcat(prepath, path); const QByteArray ba(KEYBINDINGS_CUSTOM_SCHEMA); const QByteArray bba(allpath); QGSettings *settings; const QByteArray id(KEYBINDINGS_CUSTOM_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { settings= new QGSettings(ba, bba,this); settings->set(ACTION_KEY,"freeze"); } } } QString UKUITray::findFreePath(){ int i = 0; char * dir; bool found; QList existsdirs; existsdirs = listExistsPath(); for (; i < MAX_CUSTOM_SHORTCUTS; i++){ found = true; dir = QString("custom%1/").arg(i).toLatin1().data(); for (int j = 0; j < existsdirs.count(); j++) if (!g_strcmp0(dir, existsdirs.at(j))){ found = false; break; } if (found) break; } if (i == MAX_CUSTOM_SHORTCUTS){ qDebug() << "Keyboard Shortcuts" << "Too many custom shortcuts"; return ""; } return QString("%1%2").arg(KEYBINDINGS_CUSTOM_DIR).arg(QString(dir)); } UKUIStorageFrame::UKUIStorageFrame(QWidget *parent): QWidget(parent, Qt::Popup) { installEventFilter(this); setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 this->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool |Qt::FramelessWindowHint| Qt::X11BypassWindowManagerHint); _NET_SYSTEM_TRAY_OPCODE = XfitMan::atom("_NET_SYSTEM_TRAY_OPCODE"); } UKUIStorageFrame::~UKUIStorageFrame(){ } //bool UKUIStorageFrame::event(QEvent *event) //{ //// if (event->type() == QEvent::ActivationChange) { //// if (event->type() == QEvent::WindowDeactivate) { //// if (QApplication::activeWindow() != this && storagebarstatus==ST_SHOW) { //// this->hide(); //// storagebarstatus==ST_HIDE; //// } //// } //// return QWidget::event(event); //// } //// return QWidget::event(event); //} bool UKUIStorageFrame::nativeEvent(const QByteArray &eventType, void *message, long *result) { Q_UNUSED(result); if(eventType != "xcb_generic_event_t"){ return false; } xcb_generic_event_t *event = (xcb_generic_event_t*)message; switch (event->response_type & ~0x80) { case XCB_FOCUS_OUT: hide(); break; default: break; } return false; } bool UKUIStorageFrame::eventFilter(QObject *obj, QEvent *event) { // Q_UNUSED(obj); // Q_UNUSED(event); if (obj == this) { if (event->type() == QEvent::WindowDeactivate &&flag==true ) { this->hide(); flag=false; return true; } else if (event->type() == QEvent::StyleChange) { } } if (!isActiveWindow()) { activateWindow(); } return false; } void UKUIStorageFrame::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); p.setBrush(QBrush(QColor(0x13,0x14,0x14,0xb2))); p.setPen(Qt::black); p.setRenderHint(QPainter::Antialiasing); // 反锯齿; p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } ukui-panel/plugin-tray/xfitman.cpp0000644000175000017500000002122613632320722016200 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Christopher "VdoP" Regali * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include // #include // #include // #include // #include #include #include #include "xfitman.h" #include #include #include /** * @file xfitman.cpp * @brief implements class Xfitman * @author Christopher "VdoP" Regali */ /* S ome requests from Cli*ents include type of the Client, for example the _NET_ACTIVE_WINDOW message. Currently the types can be 1 for normal applications, and 2 for pagers. See http://standards.freedesktop.org/wm-spec/latest/ar01s09.html#sourceindication */ #define SOURCE_NORMAL 1 #define SOURCE_PAGER 2 const XfitMan& xfitMan() { static XfitMan instance; return instance; } /** * @brief constructor: gets Display vars and registers us */ XfitMan::XfitMan() { root = (Window)QX11Info::appRootWindow(); } Atom XfitMan::atom(const char* atomName) { static QHash hash; if (hash.contains(atomName)) return hash.value(atomName); Atom atom = XInternAtom(QX11Info::display(), atomName, false); hash[atomName] = atom; return atom; } /** * @brief moves a window to a new position */ void XfitMan::moveWindow(Window _win, int _x, int _y) const { XMoveWindow(QX11Info::display(), _win, _x, _y); } /************************************************ ************************************************/ bool XfitMan::getWindowProperty(Window window, Atom atom, // property Atom reqType, // req_type unsigned long* resultLen,// nitems_return unsigned char** result // prop_return ) const { int format; unsigned long type, rest; return XGetWindowProperty(QX11Info::display(), window, atom, 0, 4096, false, reqType, &type, &format, resultLen, &rest, result) == Success; } /************************************************ ************************************************/ bool XfitMan::getRootWindowProperty(Atom atom, // property Atom reqType, // req_type unsigned long* resultLen,// nitems_return unsigned char** result // prop_return ) const { return getWindowProperty(root, atom, reqType, resultLen, result); } /** * @brief resizes a window to the given dimensions */ void XfitMan::resizeWindow(Window _wid, int _width, int _height) const { XResizeWindow(QX11Info::display(), _wid, _width, _height); } /** * @brief gets a windowpixmap from a window */ bool XfitMan::getClientIcon(Window _wid, QPixmap& _pixreturn) const { int format; ulong type, nitems, extra; ulong* data = 0; XGetWindowProperty(QX11Info::display(), _wid, atom("_NET_WM_ICON"), 0, LONG_MAX, False, AnyPropertyType, &type, &format, &nitems, &extra, (uchar**)&data); if (!data) { return false; } QImage img (data[0], data[1], QImage::Format_ARGB32); for (int i=0; iaddPixmap(QPixmap::fromImage(img)); } XFree(data); return true; } /** * @brief destructor */ XfitMan::~XfitMan() { } /** * @brief returns a windowname and sets _nameSource to the finally used Atom */ // i got the idea for this from taskbar-plugin of LXPanel - so credits fly out :) QString XfitMan::getWindowTitle(Window _wid) const { QString name = ""; //first try the modern net-wm ones unsigned long length; unsigned char *data = NULL; Atom utf8Atom = atom("UTF8_STRING"); if (getWindowProperty(_wid, atom("_NET_WM_VISIBLE_NAME"), utf8Atom, &length, &data)) { name = QString::fromUtf8((char*) data); XFree(data); } if (name.isEmpty()) { if (getWindowProperty(_wid, atom("_NET_WM_NAME"), utf8Atom, &length, &data)) { name = QString::fromUtf8((char*) data); XFree(data); } } if (name.isEmpty()) { if (getWindowProperty(_wid, atom("XA_WM_NAME"), XA_STRING, &length, &data)) { name = (char*) data; XFree(data); } } if (name.isEmpty()) { Status ok = XFetchName(QX11Info::display(), _wid, (char**) &data); name = QString((char*) data); if (0 != ok) XFree(data); } if (name.isEmpty()) { XTextProperty prop; if (XGetWMName(QX11Info::display(), _wid, &prop)) { name = QString::fromUtf8((char*) prop.value); XFree(prop.value); } } return name; } QString XfitMan::getApplicationName(Window _wid) const { XClassHint hint; QString ret; if (XGetClassHint(QX11Info::display(), _wid, &hint)) { if (hint.res_name) { ret = hint.res_name; XFree(hint.res_name); } if (hint.res_class) { XFree(hint.res_class); } } return ret; } /** * @brief sends a clientmessage to a window */ int XfitMan::clientMessage(Window _wid, Atom _msg, unsigned long data0, unsigned long data1, unsigned long data2, unsigned long data3, unsigned long data4) const { XClientMessageEvent msg; msg.window = _wid; msg.type = ClientMessage; msg.message_type = _msg; msg.send_event = true; msg.display = QX11Info::display(); msg.format = 32; msg.data.l[0] = data0; msg.data.l[1] = data1; msg.data.l[2] = data2; msg.data.l[3] = data3; msg.data.l[4] = data4; if (XSendEvent(QX11Info::display(), root, false, (SubstructureRedirectMask | SubstructureNotifyMask) , (XEvent *) &msg) == Success) return EXIT_SUCCESS; else return EXIT_FAILURE; } /** * @brief raises windows _wid */ void XfitMan::raiseWindow(Window _wid) const { clientMessage(_wid, atom("_NET_ACTIVE_WINDOW"), SOURCE_PAGER); } /************************************************ ************************************************/ void XfitMan::closeWindow(Window _wid) const { clientMessage(_wid, atom("_NET_CLOSE_WINDOW"), 0, // Timestamp SOURCE_PAGER); } void XfitMan::setIconGeometry(Window _wid, QRect* rect) const { Atom net_wm_icon_geometry = atom("_NET_WM_ICON_GEOMETRY"); if(!rect) XDeleteProperty(QX11Info::display(), _wid, net_wm_icon_geometry); else { long data[4]; data[0] = rect->x(); data[1] = rect->y(); data[2] = rect->width(); data[3] = rect->height(); XChangeProperty(QX11Info::display(), _wid, net_wm_icon_geometry, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)data, 4); } } ukui-panel/plugin-tray/trayicon.cpp0000644000175000017500000003163713642614010016366 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ // Warning: order of those include is important. #include #include #include #include #include #include #include #include "../panel/ukuipanel.h" #include "trayicon.h" #include "xfitman.h" #include #include #include #include #include #define XEMBED_EMBEDDED_NOTIFY 0 static bool xError; /************************************************ ************************************************/ int windowErrorHandler(Display *d, XErrorEvent *e) { xError = true; if (e->error_code != BadWindow) { char str[1024]; XGetErrorText(d, e->error_code, str, 1024); qWarning() << "Error handler" << e->error_code << str; } return 0; } /************************************************ ************************************************/ TrayIcon::TrayIcon(Window iconId, QSize const & iconSize, QWidget* parent): QFrame(parent), mIconId(iconId), mWindowId(0), mIconSize(iconSize), mDamage(0), mDisplay(QX11Info::display()) { traystatus=NORMAL; // NOTE: // it's a good idea to save the return value of QX11Info::display(). // In Qt 5, this API is slower and has some limitations which can trigger crashes. // The XDisplay value is actally stored in QScreen object of the primary screen rather than // in a global variable. So when the parimary QScreen is being deleted and becomes invalid, // QX11Info::display() will fail and cause crash. Storing this value improves the efficiency and // also prevent potential crashes caused by this bug. setObjectName("TrayIcon"); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // NOTE: // see https://github.com/ukui/ukui/issues/945 // workaround: delayed init because of weird behaviour of some icons/windows (claws-mail) // (upon starting the app the window for receiving clicks wasn't correctly sized // no matter what we've done) QTimer::singleShot(200, [this] { init(); update(); }); mRectSize.setWidth(32); mRectSize.setHeight(40); } /************************************************ ************************************************/ void TrayIcon::init() { Display* dsp = mDisplay; XWindowAttributes attr; if (! XGetWindowAttributes(dsp, mIconId, &attr)) { deleteLater(); return; } // qDebug() << "New tray icon ***********************************"; // qDebug() << " * window id: " << hex << mIconId; // qDebug() << " * window name:" << xfitMan().getName(mIconId); // qDebug() << " * size (WxH): " << attr.width << "x" << attr.height; // qDebug() << " * color depth:" << attr.depth; unsigned long mask = 0; XSetWindowAttributes set_attr; Visual* visual = attr.visual; set_attr.colormap = attr.colormap; set_attr.background_pixel = 0; set_attr.border_pixel = 0; mask = CWColormap|CWBackPixel|CWBorderPixel; const QRect icon_geom = iconGeometry(); mWindowId = XCreateWindow(dsp, this->winId(), icon_geom.x(), icon_geom.y(), icon_geom.width() * metric(PdmDevicePixelRatio), icon_geom.height() * metric(PdmDevicePixelRatio), 0, attr.depth, InputOutput, visual, mask, &set_attr); xError = false; XErrorHandler old; old = XSetErrorHandler(windowErrorHandler); XReparentWindow(dsp, mIconId, mWindowId, 0, 0); XSync(dsp, false); XSetErrorHandler(old); if (xError) { qWarning() << "****************************************"; qWarning() << "* Not icon_swallow *"; qWarning() << "****************************************"; XDestroyWindow(dsp, mWindowId); mWindowId = 0; deleteLater(); return; } { Atom acttype; int actfmt; unsigned long nbitem, bytes; unsigned char *data = 0; int ret; ret = XGetWindowProperty(dsp, mIconId, xfitMan().atom("_XEMBED_INFO"), 0, 2, false, xfitMan().atom("_XEMBED_INFO"), &acttype, &actfmt, &nbitem, &bytes, &data); if (ret == Success) { if (data) XFree(data); } else { qWarning() << "TrayIcon: xembed error"; XDestroyWindow(dsp, mWindowId); deleteLater(); return; } } { XEvent e; e.xclient.type = ClientMessage; e.xclient.serial = 0; e.xclient.send_event = True; e.xclient.message_type = xfitMan().atom("_XEMBED"); e.xclient.window = mIconId; e.xclient.format = 32; e.xclient.data.l[0] = CurrentTime; e.xclient.data.l[1] = XEMBED_EMBEDDED_NOTIFY; e.xclient.data.l[2] = 0; e.xclient.data.l[3] = mWindowId; e.xclient.data.l[4] = 0; XSendEvent(dsp, mIconId, false, 0xFFFFFF, &e); } XSelectInput(dsp, mIconId, StructureNotifyMask); mDamage = XDamageCreate(dsp, mIconId, XDamageReportRawRectangles); XCompositeRedirectWindow(dsp, mWindowId, CompositeRedirectManual); XMapWindow(dsp, mIconId); XMapRaised(dsp, mWindowId); const QSize req_size{mIconSize * metric(PdmDevicePixelRatio)}; XResizeWindow(dsp, mIconId, req_size.width(), req_size.height()); } /************************************************ ************************************************/ TrayIcon::~TrayIcon() { Display* dsp = mDisplay; XSelectInput(dsp, mIconId, NoEventMask); if (mDamage) XDamageDestroy(dsp, mDamage); // reparent to root xError = false; XErrorHandler old = XSetErrorHandler(windowErrorHandler); XUnmapWindow(dsp, mIconId); XReparentWindow(dsp, mIconId, QX11Info::appRootWindow(), 0, 0); if (mWindowId) XDestroyWindow(dsp, mWindowId); XSync(dsp, False); XSetErrorHandler(old); } /************************************************ ************************************************/ QSize TrayIcon::sizeHint() const { QMargins margins = contentsMargins(); return QSize(margins.left() + mRectSize.width() + margins.right(), margins.top() + mRectSize.height() + margins.bottom() ); } /************************************************ ************************************************/ void TrayIcon::setIconSize(QSize iconSize) { mIconSize = iconSize; const QSize req_size{mIconSize * metric(PdmDevicePixelRatio)}; if (mWindowId) { xfitMan().resizeWindow(mWindowId, req_size.width(), req_size.height()); } if (mIconId) { xfitMan().resizeWindow(mIconId, req_size.width(), req_size.height()); } QSize mysize(8,8); mIconSize=mysize; } /************************************************ ************************************************/ bool TrayIcon::event(QEvent *event) { if (mWindowId) { switch (event->type()) { case QEvent::Paint: draw(static_cast(event)); break; case QEvent::Move: case QEvent::Resize: { QRect rect = iconGeometry(); xfitMan().moveWindow(mWindowId, rect.left(), rect.top()); } break; case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: event->accept(); break; default: break; } } return QFrame::event(event); } /************************************************ ************************************************/ QRect TrayIcon::iconGeometry() { QRect res = QRect(QPoint(0, 0), mIconSize); res.moveCenter(QRect(0, 0, width(), height()).center()); return res; } /************************************************ ************************************************/ void TrayIcon::draw(QPaintEvent* /*event*/) { Display* dsp = mDisplay; XWindowAttributes attr; if (!XGetWindowAttributes(dsp, mIconId, &attr)) { qWarning() << "Paint error"; return; } QImage image; XImage* ximage = XGetImage(dsp, mIconId, 0, 0, attr.width, attr.height, AllPlanes, ZPixmap); if(ximage) { image = QImage((const uchar*) ximage->data, ximage->width, ximage->height, ximage->bytes_per_line, QImage::Format_ARGB32_Premultiplied); } else { qWarning() << " * Error image is NULL"; XClearArea(mDisplay, (Window)winId(), 0, 0, attr.width, attr.height, False); // for some unknown reason, XGetImage failed. try another less efficient method. // QScreen::grabWindow uses XCopyArea() internally. image = qApp->primaryScreen()->grabWindow(mIconId).toImage(); } // qDebug() << "Paint icon **************************************"; // qDebug() << " * XComposite: " << isXCompositeAvailable(); // qDebug() << " * Icon geometry:" << iconGeometry(); // qDebug() << " Icon"; // qDebug() << " * window id: " << hex << mIconId; // qDebug() << " * window name:" << xfitMan().getName(mIconId); // qDebug() << " * size (WxH): " << attr.width << "x" << attr.height; // qDebug() << " * pos (XxY): " << attr.x << attr.y; // qDebug() << " * color depth:" << attr.depth; // qDebug() << " XImage"; // qDebug() << " * size (WxH): " << ximage->width << "x" << ximage->height; // switch (ximage->format) // { // case XYBitmap: qDebug() << " * format: XYBitmap"; break; // case XYPixmap: qDebug() << " * format: XYPixmap"; break; // case ZPixmap: qDebug() << " * format: ZPixmap"; break; // } // qDebug() << " * color depth: " << ximage->depth; // qDebug() << " * bits per pixel:" << ximage->bits_per_pixel; // Draw QImage ........................... QPainter painter(this); QRect iconRect = iconGeometry(); if (image.size() != iconRect.size()) { image = image.scaled(iconRect.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); QRect r = image.rect(); r.moveCenter(iconRect.center()); iconRect = r; } // qDebug() << " Draw rect:" << iconRect; painter.drawImage(iconRect, image); if(ximage) XDestroyImage(ximage); // debug << "End paint icon **********************************"; } /************************************************ ************************************************/ void TrayIcon::windowDestroyed(Window w) { //damage is destroyed if it's parent window was destroyed if (mIconId == w) mDamage = 0; } /************************************************ ************************************************/ bool TrayIcon::isXCompositeAvailable() { int eventBase, errorBase; return XCompositeQueryExtension(QX11Info::display(), &eventBase, &errorBase ); } void TrayIcon::enterEvent(QEvent *) { traystatus=HOVER; update(); } void TrayIcon::leaveEvent(QEvent *) { traystatus=NORMAL; update(); } void TrayIcon::paintEvent(QPaintEvent *) { QStyleOption opt; opt.initFrom(this); QPainter p(this); switch(traystatus) { case NORMAL: { // p.setBrush(QBrush(QColor(0xFF,0xFF,0xFF,0x19))); p.setPen(Qt::NoPen); break; } case HOVER: { // p.setBrush(QBrush(QColor(0xff,0xff,0xff,0x1f))); p.setPen(Qt::NoPen); break; } case PRESS: { // p.setBrush(QBrush(QColor(0xff,0xff,0xff,0x0f))); p.setPen(Qt::NoPen); break; } } p.setRenderHint(QPainter::Antialiasing); // 反锯齿; p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } void TrayIcon::notifyAppFreeze() { emit notifyTray(mIconId); } ukui-panel/plugin-tray/trayappnitify.h0000644000175000017500000000000013640356061017071 0ustar fengfengukui-panel/plugin-tray/traystorage.h0000644000175000017500000000547313632320722016551 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2019 Kylin team * Authors: * hepuyao * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef TRAYSTORAGE_H #define TRAYSTORAGE_H #include #include #include "../panel/iukuipanel.h" #include #include #include #include #include "fixx11h.h" #include #include class TrayIcon; class QSize; namespace UKUi { class GridLayout; } enum TrayStorageStatus{HIDE,HOVER}; /** * @brief This makes our trayplugin */ class IUKUIPanelPlugin; class TrayStorage: public QFrame, QAbstractNativeEventFilter { Q_OBJECT Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize) public: TrayStorage(QWidget* parent = 0); ~TrayStorage(); friend class UKUITray; QSize iconSize() const { return mIconSize; } void setIconSize(QSize iconSize); bool nativeEventFilter(const QByteArray &eventType, void *message, long *); void mouseReleaseEvent(QMouseEvent* event); void mousePressEvent(QMouseEvent* event); void paintEvent(QPaintEvent *); // QWidget *horizontalLayoutWidget; // QHBoxLayout *horizontalLayout; signals: void iconSizeChanged(int iconSize); public slots: void onIconDestroyed(QObject * icon); private slots: void stopTrayStorage(); protected: bool event(QEvent *event);//重写窗口事件 void leaveEvent(QEvent *); private: VisualID getVisual(); int clientMessage(WId _wid, Atom _msg, long unsigned int data0, long unsigned int data1 = 0, long unsigned int data2 = 0, long unsigned int data3 = 0, long unsigned int data4 = 0) const; bool mValid; Window mTrayId; QList mIcons; int mDamageEvent; int mDamageError; QSize mIconSize; Atom _NET_SYSTEM_TRAY_OPCODE; Display* mDisplay; UKUi::GridLayout *mLayout; }; #endif ukui-panel/plugin-tray/CMakeLists.txt0000644000175000017500000000257413640356061016577 0ustar fengfengset(PLUGIN "tray") include(CheckLibraryExists) #find_package(XCB REQUIRED COMPONENTS xcb xcb-util xcb-damage) find_package(PkgConfig) find_package(X11 REQUIRED) find_package(Qt5X11Extras ${REQUIRED_QT_VERSION} REQUIRED) pkg_check_modules(XCOMPOSITE REQUIRED xcomposite) pkg_check_modules(XDAMAGE REQUIRED xdamage) pkg_check_modules(XRENDER REQUIRED xrender) pkg_check_modules(Gsetting REQUIRED gsettings-qt) pkg_check_modules(GIO2 REQUIRED gio-2.0) pkg_check_modules(GIOUNIX2 REQUIRED gio-unix-2.0) pkg_check_modules(DCONF REQUIRED dconf) include_directories(${Gsetting_INCLUDE_DIRS}) include_directories(${GIO2_INCLUDE_DIRS}) include_directories(${GIOUNIX2_INCLUDE_DIRS}) include_directories(${DCONF_INCLUDE_DIRS}) set(HEADERS ukuitrayplugin.h ukuitray.h trayicon.h xfitman.h traystorage.h # ../panel/customstyle.h ) set(SOURCES ukuitrayplugin.cpp ukuitray.cpp trayicon.cpp xfitman.cpp traystorage.cpp # ../panel/customstyle.cpp ) set(LIBRARIES ${X11_LIBRARIES} ${XCOMPOSITE_LDFLAGS} ${XDAMAGE_LIBRARIES} ${XRENDER_LIBRARIES} ${XCB_LIBRARIES} Qt5X11Extras ${Gsetting_LIBRARIES} ${GIO2_LIBRARIES} ${GIOUNIX2_LIBRARIES} ${DCONF_LIBRARIES} ) install(FILES ../panel/resources/org.ukui.panel.tray.gschema.xml DESTINATION "/usr/share/glib-2.0/schemas/" COMPONENT Runtime ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel/plugin-tray/ukuitrayplugin.cpp0000644000175000017500000000257013632320722017627 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2013 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuitrayplugin.h" #include "ukuitray.h" UKUITrayPlugin::UKUITrayPlugin(const IUKUIPanelPluginStartupInfo &startupInfo) : QObject(), IUKUIPanelPlugin(startupInfo), mWidget(new UKUITray(this)) { } UKUITrayPlugin::~UKUITrayPlugin() { delete mWidget; } QWidget *UKUITrayPlugin::widget() { return mWidget; } void UKUITrayPlugin::realign() { mWidget->realign(); } ukui-panel/plugin-tray/trayicon.h0000644000175000017500000000444413640356061016036 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef TRAYICON_H #define TRAYICON_H #include #include #include #include #include #include #define TRAY_ICON_SIZE_DEFAULT 16 class QWidget; class UKUIPanel; class IUKUIPanelPlugin; class TrayIcon: public QFrame { Q_OBJECT // Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize) public: TrayIcon(Window iconId, QSize const & iconSize, QWidget* parent); virtual ~TrayIcon(); Window iconId() { return mIconId; } Window windowId() { return mWindowId; } void windowDestroyed(Window w); // QSize iconSize() const { return mIconSize; } void setIconSize(QSize iconSize); QSize sizeHint() const; IUKUIPanelPlugin *mPlugin; public slots: void notifyAppFreeze(); signals: void notifyTray(Window); protected: bool event(QEvent *event); void draw(QPaintEvent* event); void enterEvent(QEvent *); void leaveEvent(QEvent *); void paintEvent(QPaintEvent *); private: void init(); QRect iconGeometry(); Window mIconId; Window mWindowId; QSize mIconSize; Damage mDamage; Display* mDisplay; static bool isXCompositeAvailable(); QSize mRectSize; enum TrayAppStatus{NORMAL, HOVER, PRESS}; TrayAppStatus traystatus; }; #endif // TRAYICON_H ukui-panel/plugin-tray/ukuitrayplugin.h0000644000175000017500000000427113632320722017274 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2013 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITRAYPLUGIN_H #define UKUITRAYPLUGIN_H #include "../panel/iukuipanelplugin.h" #include #include #include class UKUITray; class UKUITrayPlugin : public QObject, public IUKUIPanelPlugin { Q_OBJECT public: explicit UKUITrayPlugin(const IUKUIPanelPluginStartupInfo &startupInfo); ~UKUITrayPlugin(); virtual QWidget *widget(); virtual QString themeId() const { return "Tray"; } virtual Flags flags() const { return PreferRightAlignment | SingleInstance | NeedsHandle; } void realign(); bool isSeparate() const { return true; } private: UKUITray *mWidget; }; class UKUITrayPluginLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT // Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { // Currently only X11 supported if (!QX11Info::connection()) { qWarning() << "Currently tray plugin supports X11 only. Skipping."; return nullptr; } return new UKUITrayPlugin(startupInfo); } }; #endif // UKUITRAYPLUGIN_H ukui-panel/plugin-tray/ukuitray.h0000644000175000017500000000753213643566146016076 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2019 Kylin team * Authors: * hepuyao * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITRAY_H #define UKUITRAY_H #include #include #include "../panel/iukuipanel.h" #include #include #include #include "fixx11h.h" #include #include "traystorage.h" #include "../panel/customstyle.h" #include "../panel/ukuicontrolstyle.h" #include #include #include class TrayIcon; class QSize; namespace UKUi { class GridLayout; } enum storageBarStatus{ST_HIDE,ST_SHOW}; /** * @brief This makes our trayplugin */ class IUKUIPanelPlugin; class UKUIStorageFrame:public QWidget { Q_OBJECT public: UKUIStorageFrame(QWidget* parent =0); ~UKUIStorageFrame(); protected: // bool event(QEvent *e); bool eventFilter(QObject *watched, QEvent *event); bool nativeEvent(const QByteArray &eventType, void *message, long *result); void paintEvent(QPaintEvent *event); private: Atom _NET_SYSTEM_TRAY_OPCODE; UKUi::GridLayout *storageLayout; }; class UKUITray: public QFrame, QAbstractNativeEventFilter { Q_OBJECT Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize) public: UKUITray(IUKUIPanelPlugin *plugin, QWidget* parent = 0); ~UKUITray(); QSize iconSize() const { return mIconSize; } void setIconSize(QSize iconSize); bool nativeEventFilter(const QByteArray &eventType, void *message, long *); void realign(); IUKUIPanelPlugin *mPlugin; // TrayStorage *tys; //control app show in tray/traystorege by ukui-control-center QList listExistsPath(); QString findFreePath(); void regulateIcon(Window *mid); void freezeApp(); public slots: void storageBar(); void storageAddIcon(Window winId); signals: void iconSizeChanged(int iconSize); void freezeIcon(TrayIcon *icon,Window winid); private slots: void startTray(); void stopTray(); void stopStorageTray(); void onIconDestroyed(QObject * icon); void freezeTrayApp(Window winId); private: VisualID getVisual(); void clientMessageEvent(xcb_generic_event_t *e); int clientMessage(WId _wid, Atom _msg, long unsigned int data0, long unsigned int data1 = 0, long unsigned int data2 = 0, long unsigned int data3 = 0, long unsigned int data4 = 0) const; void addIcon(Window id); void moveIconToStorage(Window id); void moveIconToTray(Window winId); TrayIcon* findIcon(Window trayId); TrayIcon* findStorageIcon(Window trayId); bool mValid; Window mTrayId; QList mIcons; QList mStorageIcons; int mDamageEvent; int mDamageError; QSize mIconSize; UKUi::GridLayout *mLayout; UKUi::GridLayout *storageLayout; QToolButton *bt; Atom _NET_SYSTEM_TRAY_OPCODE; Display* mDisplay; UKUIStorageFrame *storageFrame; }; #endif