From 176721b32d94cb994c7be1c5723d1f0690667b9b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aur=C3=A9lien=20COUDERC?= Date: Tue, 3 Dec 2024 16:21:25 +0100 Subject: [PATCH] Import kdecoration_6.2.4.orig.tar.xz [dgit import orig kdecoration_6.2.4.orig.tar.xz] --- .git-blame-ignore-revs | 2 + .gitignore | 7 + .gitlab-ci.yml | 8 + .kde-ci.yml | 10 + CMakeLists.txt | 93 ++ KDecoration2Config.cmake.in | 10 + LICENSES/CC0-1.0.txt | 121 ++ LICENSES/LGPL-2.1-only.txt | 467 +++++++ LICENSES/LGPL-3.0-only.txt | 163 +++ LICENSES/LicenseRef-KDE-Accepted-LGPL.txt | 12 + README.md | 54 + autotests/CMakeLists.txt | 35 + autotests/decorationbuttontest.cpp | 1372 +++++++++++++++++++++ autotests/decorationtest.cpp | 151 +++ autotests/mockbridge.cpp | 25 + autotests/mockbridge.h | 33 + autotests/mockbutton.cpp | 19 + autotests/mockbutton.h | 16 + autotests/mockclient.cpp | 292 +++++ autotests/mockclient.h | 91 ++ autotests/mockdecoration.cpp | 60 + autotests/mockdecoration.h | 25 + autotests/mocksettings.cpp | 60 + autotests/mocksettings.h | 28 + autotests/shadowtest.cpp | 129 ++ metainfo.yaml | 18 + po/ar/kdecoration.po | 93 ++ po/ast/kdecoration.po | 93 ++ po/az/kdecoration.po | 102 ++ po/bg/kdecoration.po | 93 ++ po/ca/kdecoration.po | 98 ++ po/ca@valencia/kdecoration.po | 98 ++ po/cs/kdecoration.po | 93 ++ po/da/kdecoration.po | 104 ++ po/de/kdecoration.po | 102 ++ po/el/kdecoration.po | 102 ++ po/en_GB/kdecoration.po | 102 ++ po/eo/kdecoration.po | 92 ++ po/es/kdecoration.po | 104 ++ po/et/kdecoration.po | 104 ++ po/eu/kdecoration.po | 106 ++ po/fi/kdecoration.po | 102 ++ po/fr/kdecoration.po | 103 ++ po/gl/kdecoration.po | 102 ++ po/he/kdecoration.po | 94 ++ po/hi/kdecoration.po | 97 ++ po/hu/kdecoration.po | 103 ++ po/ia/kdecoration.po | 102 ++ po/id/kdecoration.po | 103 ++ po/is/kdecoration.po | 94 ++ po/it/kdecoration.po | 102 ++ po/ja/kdecoration.po | 93 ++ po/ka/kdecoration.po | 94 ++ po/ko/kdecoration.po | 102 ++ po/lt/kdecoration.po | 104 ++ po/lv/kdecoration.po | 94 ++ po/ml/kdecoration.po | 94 ++ po/nl/kdecoration.po | 102 ++ po/nn/kdecoration.po | 96 ++ po/pa/kdecoration.po | 93 ++ po/pl/kdecoration.po | 102 ++ po/pt/kdecoration.po | 88 ++ po/pt_BR/kdecoration.po | 102 ++ po/ro/kdecoration.po | 103 ++ po/ru/kdecoration.po | 104 ++ po/sa/kdecoration.po | 94 ++ po/sk/kdecoration.po | 101 ++ po/sl/kdecoration.po | 103 ++ po/sv/kdecoration.po | 102 ++ po/ta/kdecoration.po | 93 ++ po/tr/kdecoration.po | 93 ++ po/uk/kdecoration.po | 105 ++ po/zh_CN/kdecoration.po | 93 ++ po/zh_TW/kdecoration.po | 103 ++ src/CMakeLists.txt | 82 ++ src/Messages.sh | 2 + src/decoratedclient.cpp | 192 +++ src/decoratedclient.h | 273 ++++ src/decoration.cpp | 497 ++++++++ src/decoration.h | 248 ++++ src/decoration_p.h | 57 + src/decorationbutton.cpp | 601 +++++++++ src/decorationbutton.h | 179 +++ src/decorationbutton_p.h | 79 ++ src/decorationbuttongroup.cpp | 244 ++++ src/decorationbuttongroup.h | 115 ++ src/decorationbuttongroup_p.h | 45 + src/decorationdefines.h | 163 +++ src/decorationsettings.cpp | 96 ++ src/decorationsettings.h | 132 ++ src/decorationshadow.cpp | 173 +++ src/decorationshadow.h | 128 ++ src/decorationshadow_p.h | 38 + src/decorationthemeprovider.cpp | 87 ++ src/decorationthemeprovider.h | 76 ++ src/private/CMakeLists.txt | 58 + src/private/decoratedclientprivate.cpp | 63 + src/private/decoratedclientprivate.h | 105 ++ src/private/decorationbridge.cpp | 22 + src/private/decorationbridge.h | 50 + src/private/decorationsettingsprivate.cpp | 85 ++ src/private/decorationsettingsprivate.h | 60 + 102 files changed, 11997 insertions(+) create mode 100644 .git-blame-ignore-revs create mode 100644 .gitignore create mode 100644 .gitlab-ci.yml create mode 100644 .kde-ci.yml create mode 100644 CMakeLists.txt create mode 100644 KDecoration2Config.cmake.in create mode 100644 LICENSES/CC0-1.0.txt create mode 100644 LICENSES/LGPL-2.1-only.txt create mode 100644 LICENSES/LGPL-3.0-only.txt create mode 100644 LICENSES/LicenseRef-KDE-Accepted-LGPL.txt create mode 100644 README.md create mode 100644 autotests/CMakeLists.txt create mode 100644 autotests/decorationbuttontest.cpp create mode 100644 autotests/decorationtest.cpp create mode 100644 autotests/mockbridge.cpp create mode 100644 autotests/mockbridge.h create mode 100644 autotests/mockbutton.cpp create mode 100644 autotests/mockbutton.h create mode 100644 autotests/mockclient.cpp create mode 100644 autotests/mockclient.h create mode 100644 autotests/mockdecoration.cpp create mode 100644 autotests/mockdecoration.h create mode 100644 autotests/mocksettings.cpp create mode 100644 autotests/mocksettings.h create mode 100644 autotests/shadowtest.cpp create mode 100644 metainfo.yaml create mode 100644 po/ar/kdecoration.po create mode 100644 po/ast/kdecoration.po create mode 100644 po/az/kdecoration.po create mode 100644 po/bg/kdecoration.po create mode 100644 po/ca/kdecoration.po create mode 100644 po/ca@valencia/kdecoration.po create mode 100644 po/cs/kdecoration.po create mode 100644 po/da/kdecoration.po create mode 100644 po/de/kdecoration.po create mode 100644 po/el/kdecoration.po create mode 100644 po/en_GB/kdecoration.po create mode 100644 po/eo/kdecoration.po create mode 100644 po/es/kdecoration.po create mode 100644 po/et/kdecoration.po create mode 100644 po/eu/kdecoration.po create mode 100644 po/fi/kdecoration.po create mode 100644 po/fr/kdecoration.po create mode 100644 po/gl/kdecoration.po create mode 100644 po/he/kdecoration.po create mode 100644 po/hi/kdecoration.po create mode 100644 po/hu/kdecoration.po create mode 100644 po/ia/kdecoration.po create mode 100644 po/id/kdecoration.po create mode 100644 po/is/kdecoration.po create mode 100644 po/it/kdecoration.po create mode 100644 po/ja/kdecoration.po create mode 100644 po/ka/kdecoration.po create mode 100644 po/ko/kdecoration.po create mode 100644 po/lt/kdecoration.po create mode 100644 po/lv/kdecoration.po create mode 100644 po/ml/kdecoration.po create mode 100644 po/nl/kdecoration.po create mode 100644 po/nn/kdecoration.po create mode 100644 po/pa/kdecoration.po create mode 100644 po/pl/kdecoration.po create mode 100644 po/pt/kdecoration.po create mode 100644 po/pt_BR/kdecoration.po create mode 100644 po/ro/kdecoration.po create mode 100644 po/ru/kdecoration.po create mode 100644 po/sa/kdecoration.po create mode 100644 po/sk/kdecoration.po create mode 100644 po/sl/kdecoration.po create mode 100644 po/sv/kdecoration.po create mode 100644 po/ta/kdecoration.po create mode 100644 po/tr/kdecoration.po create mode 100644 po/uk/kdecoration.po create mode 100644 po/zh_CN/kdecoration.po create mode 100644 po/zh_TW/kdecoration.po create mode 100644 src/CMakeLists.txt create mode 100644 src/Messages.sh create mode 100644 src/decoratedclient.cpp create mode 100644 src/decoratedclient.h create mode 100644 src/decoration.cpp create mode 100644 src/decoration.h create mode 100644 src/decoration_p.h create mode 100644 src/decorationbutton.cpp create mode 100644 src/decorationbutton.h create mode 100644 src/decorationbutton_p.h create mode 100644 src/decorationbuttongroup.cpp create mode 100644 src/decorationbuttongroup.h create mode 100644 src/decorationbuttongroup_p.h create mode 100644 src/decorationdefines.h create mode 100644 src/decorationsettings.cpp create mode 100644 src/decorationsettings.h create mode 100644 src/decorationshadow.cpp create mode 100644 src/decorationshadow.h create mode 100644 src/decorationshadow_p.h create mode 100644 src/decorationthemeprovider.cpp create mode 100644 src/decorationthemeprovider.h create mode 100644 src/private/CMakeLists.txt create mode 100644 src/private/decoratedclientprivate.cpp create mode 100644 src/private/decoratedclientprivate.h create mode 100644 src/private/decorationbridge.cpp create mode 100644 src/private/decorationbridge.h create mode 100644 src/private/decorationsettingsprivate.cpp create mode 100644 src/private/decorationsettingsprivate.h diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..566bc68 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# clang-format +2a523449997260eb1d4585a673f81477c47b9979 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5a6a58e --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.clang-format +/compile_commands.json +.clangd +.idea +/cmake-build* +.cache +/build* diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..f6e2f69 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: None +# SPDX-License-Identifier: CC0-1.0 + +include: + - project: sysadmin/ci-utilities + file: + - /gitlab-templates/linux-qt6.yml + - /gitlab-templates/freebsd-qt6.yml diff --git a/.kde-ci.yml b/.kde-ci.yml new file mode 100644 index 0000000..915f993 --- /dev/null +++ b/.kde-ci.yml @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: None +# SPDX-License-Identifier: CC0-1.0 + +Dependencies: +- 'on': ['@all'] + 'require': + 'frameworks/extra-cmake-modules': '@latest-kf6' + 'frameworks/ki18n': '@latest-kf6' +Options: + require-passing-tests-on: [ 'Linux', 'FreeBSD'] diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7ba4e0c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,93 @@ +cmake_minimum_required(VERSION 3.16) + +project(decoration-api) +set(PROJECT_VERSION "6.2.4") +set(PROJECT_VERSION_MAJOR 6) + +set(QT_MIN_VERSION "6.7.0") +set(KF6_MIN_VERSION "6.5.0") +set(KDE_COMPILERSETTINGS_LEVEL "5.82") + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(ECM ${KF6_MIN_VERSION} REQUIRED NO_MODULE) +# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ) + +include(KDEInstallDirs) +include(KDECompilerSettings NO_POLICY_SCOPE) +include(KDECMakeSettings) +include(ECMSetupVersion) +include(ECMGenerateHeaders) +include(ECMGenerateExportHeader) +include(FeatureSummary) +include(GenerateExportHeader) +include(CMakePackageConfigHelpers) +include(KDEClangFormat) +include(KDEGitCommitHooks) +include(ECMDeprecationSettings) + +ecm_setup_version(${PROJECT_VERSION} VARIABLE_PREFIX KDECORATION2 + VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kdecoration2_version.h" + PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KDecoration2ConfigVersion.cmake" + SOVERSION ${PROJECT_VERSION_MAJOR}) + +#dependencies +find_package(Qt6 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS + Core + Gui + Test +) + +# require at least gcc 4.8 +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + if ("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.8") + message(SEND_ERROR "Version ${CMAKE_CXX_COMPILER_VERSION} of the ${CMAKE_CXX_COMPILER_ID} C++ compiler is not supported. Please use version 4.8 or later.") + endif() +endif() + +set(EXCLUDE_DEPRECATED_BEFORE_AND_AT 0 CACHE STRING "Control the range of deprecated API excluded from the build [default=0].") + +set(KDECORATION2_INCLUDEDIR "${KDE_INSTALL_INCLUDEDIR}/KDecoration2") +find_package(KF6I18n ${KF6_MIN_VERSION} CONFIG REQUIRED) + +ecm_set_disabled_deprecation_versions(QT 5.15.2 + KF 5.240.0 + ) + +add_definitions(-DQT_NO_KEYWORDS) + +# Subdirectories +add_subdirectory(src) +if(BUILD_TESTING) + add_subdirectory(autotests) +endif() + +# add clang-format target for all our real source files +file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES *.cpp *.h) +kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES}) +kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT) + +# create a Config.cmake and a ConfigVersion.cmake file and install them +set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KDecoration2") + +configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/KDecoration2Config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/KDecoration2Config.cmake" + INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} + ) + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KDecoration2Config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/KDecoration2ConfigVersion.cmake" + DESTINATION "${CMAKECONFIG_INSTALL_DIR}" + COMPONENT Devel ) + +install(EXPORT KDecoration2Targets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KDecoration2Targets.cmake NAMESPACE KDecoration2:: ) + + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kdecoration2_version.h + DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF} COMPONENT Devel ) + +feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) + +ki18n_install(po) diff --git a/KDecoration2Config.cmake.in b/KDecoration2Config.cmake.in new file mode 100644 index 0000000..5f624d5 --- /dev/null +++ b/KDecoration2Config.cmake.in @@ -0,0 +1,10 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) +find_dependency(Qt6Gui @QT_MIN_VERSION@) + +set(KDECORATION_PLUGIN_DIR "org.kde.kdecoration2") +set(KDECORATION_KCM_PLUGIN_DIR "org.kde.kdecoration2.kcm") + +include("${CMAKE_CURRENT_LIST_DIR}/KDecoration2Targets.cmake") + diff --git a/LICENSES/CC0-1.0.txt b/LICENSES/CC0-1.0.txt new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/LICENSES/CC0-1.0.txt @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/LICENSES/LGPL-2.1-only.txt b/LICENSES/LGPL-2.1-only.txt new file mode 100644 index 0000000..130dffb --- /dev/null +++ b/LICENSES/LGPL-2.1-only.txt @@ -0,0 +1,467 @@ +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. + +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 + +How to Apply These Terms to Your New Libraries + +If you develop a new library, and you want it to be of the greatest possible +use to the public, we recommend making it free software that everyone can +redistribute and change. You can do so by permitting redistribution under +these terms (or, alternatively, under the terms of the ordinary General Public +License). + +To apply these terms, attach the following notices to the library. It is safest +to attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the "copyright" +line and a pointer to where the full notice is found. + +< one line to give the library's name and an idea of what it does. > + +Copyright (C) < year > < name of author > + +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 Also add information +on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your school, +if any, to sign a "copyright disclaimer" for the library, if necessary. Here +is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in + +the library `Frob' (a library for tweaking knobs) written + +by James Random Hacker. + +< signature of Ty Coon > , 1 April 1990 + +Ty Coon, President of Vice + +That's all there is to it! diff --git a/LICENSES/LGPL-3.0-only.txt b/LICENSES/LGPL-3.0-only.txt new file mode 100644 index 0000000..bd405af --- /dev/null +++ b/LICENSES/LGPL-3.0-only.txt @@ -0,0 +1,163 @@ +GNU LESSER GENERAL PUBLIC LICENSE + +Version 3, 29 June 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +This version of the GNU Lesser General Public License incorporates the terms +and conditions of version 3 of the GNU General Public License, supplemented +by the additional permissions listed below. + + 0. Additional Definitions. + + + +As used herein, "this License" refers to version 3 of the GNU Lesser General +Public License, and the "GNU GPL" refers to version 3 of the GNU General Public +License. + + + +"The Library" refers to a covered work governed by this License, other than +an Application or a Combined Work as defined below. + + + +An "Application" is any work that makes use of an interface provided by the +Library, but which is not otherwise based on the Library. Defining a subclass +of a class defined by the Library is deemed a mode of using an interface provided +by the Library. + + + +A "Combined Work" is a work produced by combining or linking an Application +with the Library. The particular version of the Library with which the Combined +Work was made is also called the "Linked Version". + + + +The "Minimal Corresponding Source" for a Combined Work means the Corresponding +Source for the Combined Work, excluding any source code for portions of the +Combined Work that, considered in isolation, are based on the Application, +and not on the Linked Version. + + + +The "Corresponding Application Code" for a Combined Work means the object +code and/or source code for the Application, including any data and utility +programs needed for reproducing the Combined Work from the Application, but +excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + +You may convey a covered work under sections 3 and 4 of this License without +being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + +If you modify a copy of the Library, and, in your modifications, a facility +refers to a function or data to be supplied by an Application that uses the +facility (other than as an argument passed when the facility is invoked), +then you may convey a copy of the modified version: + +a) under this License, provided that you make a good faith effort to ensure +that, in the event an Application does not supply the function or data, the +facility still operates, and performs whatever part of its purpose remains +meaningful, or + +b) under the GNU GPL, with none of the additional permissions of this License +applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + +The object code form of an Application may incorporate material from a header +file that is part of the Library. You may convey such object code under terms +of your choice, provided that, if the incorporated material is not limited +to numerical parameters, data structure layouts and accessors, or small macros, +inline functions and templates (ten or fewer lines in length), you do both +of the following: + +a) Give prominent notice with each copy of the object code that the Library +is used in it and that the Library and its use are covered by this License. + +b) Accompany the object code with a copy of the GNU GPL and this license document. + + 4. Combined Works. + +You may convey a Combined Work under terms of your choice that, taken together, +effectively do not restrict modification of the portions of the Library contained +in the Combined Work and reverse engineering for debugging such modifications, +if you also do each of the following: + +a) Give prominent notice with each copy of the Combined Work that the Library +is used in it and that the Library and its use are covered by this License. + +b) Accompany the Combined Work with a copy of the GNU GPL and this license +document. + +c) For a Combined Work that displays copyright notices during execution, include +the copyright notice for the Library among these notices, as well as a reference +directing the user to the copies of the GNU GPL and this license document. + + d) Do one of the following: + +0) Convey the Minimal Corresponding Source under the terms of this License, +and the Corresponding Application Code in a form suitable for, and under terms +that permit, the user to recombine or relink the Application with a modified +version of the Linked Version to produce a modified Combined Work, in the +manner specified by section 6 of the GNU GPL for conveying Corresponding Source. + +1) Use a suitable shared library mechanism for linking with the Library. A +suitable mechanism is one that (a) uses at run time a copy of the Library +already present on the user's computer system, and (b) will operate properly +with a modified version of the Library that is interface-compatible with the +Linked Version. + +e) Provide Installation Information, but only if you would otherwise be required +to provide such information under section 6 of the GNU GPL, and only to the +extent that such information is necessary to install and execute a modified +version of the Combined Work produced by recombining or relinking the Application +with a modified version of the Linked Version. (If you use option 4d0, the +Installation Information must accompany the Minimal Corresponding Source and +Corresponding Application Code. If you use option 4d1, you must provide the +Installation Information in the manner specified by section 6 of the GNU GPL +for conveying Corresponding Source.) + + 5. Combined Libraries. + +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 that are +not Applications and are not covered by this License, and convey such a combined +library under terms of your choice, if you do both of the following: + +a) Accompany the combined library with a copy of the same work based on the +Library, uncombined with any other library facilities, conveyed under the +terms of this License. + +b) Give prominent notice with the combined library that part of it is a work +based on the Library, and explaining where to find the accompanying uncombined +form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + +The Free Software Foundation may publish revised and/or new versions of the +GNU 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 as you +received it specifies that a certain numbered version of the GNU Lesser General +Public License "or any later version" applies to it, you have the option of +following the terms and conditions either of that published version or of +any later version published by the Free Software Foundation. If the Library +as you received it does not specify a version number of the GNU Lesser General +Public License, you may choose any version of the GNU Lesser General Public +License ever published by the Free Software Foundation. + +If the Library as you received it specifies that a proxy can decide whether +future versions of the GNU Lesser General Public License shall apply, that +proxy's public statement of acceptance of any version is permanent authorization +for you to choose that version for the Library. diff --git a/LICENSES/LicenseRef-KDE-Accepted-LGPL.txt b/LICENSES/LicenseRef-KDE-Accepted-LGPL.txt new file mode 100644 index 0000000..232b3c5 --- /dev/null +++ b/LICENSES/LicenseRef-KDE-Accepted-LGPL.txt @@ -0,0 +1,12 @@ +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 3 of the license or (at your option) any later version +that is accepted by the membership of KDE e.V. (or its successor +approved by the membership of KDE e.V.), which shall act as a +proxy as defined in Section 6 of version 3 of the license. + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e30f344 --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# KDecoration2 + +Plugin based library to create window decorations. + +## Introduction + +KDecoration2 is a library to create window decorations. These window decorations can be used by +for example an X11 based window manager which re-parents a Client window to a window decoration +frame. + +The library consists of two parts: +* Decoration API for implementing a Decoration theme +* Private API to implement the backend part (e.g. from Window Manager side) + +## Providing a Decoration + +To provide a custom decoration one needs to create a plugin and provide an own implementation +of KDecoration2::Decoration. For a framework to load and find the plugin it needs to be compiled +with the proper json metadata. An example for such metadata (deco.json): + +```json +{ + "KPlugin": { + "Id": "org.kde.myAweseomeDecoration", + "ServiceTypes": [ + "org.kde.kdecoration2" + ] + }, + "X-KDE-ConfigModule": "kcm_name", /* comes with a configuration module */ + "org.kde.kdecoration2": { + "blur": false, /* blur behind not needed */ + } +} +``` + +To simplify one can use the KPluginFactory macro from the KCoreAddons framework: + +```cpp +K_PLUGIN_FACTORY_WITH_JSON( + MyAwesomeDecorationFactory, + "deco.json", + registerPlugin(); +) +``` + +The plugin needs to get installed to `${KDE_INSTALL_PLUGINDIR}/org.kde.kdecoration2`. + +## Configuring the Decoration + +It is possible to provide a configuration module to tweak some aspects of the decoration. This is done +by creating a plugin that provides such a configuration module. + +The `kcmoduleName` specifies the name of the configuration module. It needs to be installed under +`${KDE_INSTALL_PLUGINDIR}/org.kde.kdecoration2.kcm` so that it can be looked up. diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt new file mode 100644 index 0000000..f8e5e81 --- /dev/null +++ b/autotests/CMakeLists.txt @@ -0,0 +1,35 @@ +include(ECMMarkAsTest) + +set(decorationButtonTest_SRCS + mockbridge.cpp mockbridge.h + mockbutton.cpp mockbutton.h + mockclient.cpp mockclient.h + mockdecoration.cpp mockdecoration.h + mocksettings.cpp mocksettings.h + decorationbuttontest.cpp + ) +add_executable(decorationButtonTest ${decorationButtonTest_SRCS}) +target_link_libraries(decorationButtonTest kdecorations2 kdecorations2private Qt::Test) +add_test(NAME kdecoration2-decorationButtonTest COMMAND decorationButtonTest) +ecm_mark_as_test(decorationButtonTest) + +set(decorationTest_SRCS + mockbridge.cpp mockbridge.h + mockbutton.cpp mockbutton.h + mockclient.cpp mockclient.h + mockdecoration.cpp mockdecoration.h + mocksettings.cpp mocksettings.h + decorationtest.cpp + ) +add_executable(decorationTest ${decorationTest_SRCS}) +target_link_libraries(decorationTest kdecorations2 kdecorations2private Qt::Test) +add_test(NAME kdecoration2-decorationTest COMMAND decorationTest) +ecm_mark_as_test(decorationTest) + +set(decorationShadowTest_SRCS + shadowtest.cpp + ) +add_executable(decorationShadowTest ${decorationShadowTest_SRCS}) +target_link_libraries(decorationShadowTest kdecorations2 Qt::Test) +add_test(NAME kdecoration2-decorationShadowTest COMMAND decorationShadowTest) +ecm_mark_as_test(decorationShadowTest) diff --git a/autotests/decorationbuttontest.cpp b/autotests/decorationbuttontest.cpp new file mode 100644 index 0000000..f5aa8e1 --- /dev/null +++ b/autotests/decorationbuttontest.cpp @@ -0,0 +1,1372 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "../src/decoratedclient.h" +#include "../src/decorationsettings.h" +#include "mockbridge.h" +#include "mockbutton.h" +#include "mockclient.h" +#include "mockdecoration.h" +#include "mocksettings.h" +#include +#include +#include + +Q_DECLARE_METATYPE(Qt::MouseButton) + +class DecorationButtonTest : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void testButton(); + void testChecked(); + void testEnabled(); + void testPressIgnore_data(); + void testPressIgnore(); + void testReleaseIgnore_data(); + void testReleaseIgnore(); + void testHoverEnterIgnore_data(); + void testHoverEnterIgnore(); + void testHoverLeaveIgnore_data(); + void testHoverLeaveIgnore(); + void testHover(); + void testMouseMove_data(); + void testMouseMove(); + void testClose(); + void testMinimize(); + void testQuickHelp(); + void testKeepAbove(); + void testKeepBelow(); + void testShade(); + void testMaximize(); + void testOnAllDesktops(); + void testMenu(); + void testMenuDoubleClick(); + void testMenuPressAndHold(); + void testApplicationMenu(); + void testContains_data(); + void testContains(); +}; + +void DecorationButtonTest::testButton() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + // create a custom button and verify the base settings + MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration); + QCOMPARE(button.decoration(), &mockDecoration); + const MockButton &constRef(button); + QCOMPARE(constRef.decoration(), &mockDecoration); + QCOMPARE(button.type(), KDecoration2::DecorationButtonType::Custom); + QCOMPARE(button.acceptedButtons(), Qt::MouseButtons(Qt::LeftButton)); + QCOMPARE(button.isCheckable(), false); + QCOMPARE(button.isChecked(), false); + QCOMPARE(button.isEnabled(), true); + QCOMPARE(button.isHovered(), false); + QCOMPARE(button.isPressed(), false); + QCOMPARE(button.isVisible(), true); + QCOMPARE(button.size(), QSizeF(0, 0)); + QCOMPARE(button.geometry(), QRectF()); + + // test setting the geometry + QSignalSpy geometryChangedSpy(&button, &KDecoration2::DecorationButton::geometryChanged); + QVERIFY(geometryChangedSpy.isValid()); + // setting to default geometry shouldn't change + button.setGeometry(QRectF()); + QCOMPARE(button.geometry(), QRectF()); + QCOMPARE(geometryChangedSpy.count(), 0); + // setting to a proper geometry should change + const QRectF testGeometry = QRectF(0, 0, 10, 20); + button.setGeometry(testGeometry); + QCOMPARE(button.geometry(), testGeometry); + QCOMPARE(button.size(), testGeometry.size()); + QCOMPARE(geometryChangedSpy.count(), 1); + QCOMPARE(geometryChangedSpy.first().first().toRectF(), testGeometry); + + // test changing visibility + QSignalSpy visibilityChangedSpy(&button, &KDecoration2::DecorationButton::visibilityChanged); + QVERIFY(visibilityChangedSpy.isValid()); + button.setVisible(true); + QCOMPARE(visibilityChangedSpy.count(), 0); + button.setVisible(false); + QCOMPARE(button.isVisible(), false); + QCOMPARE(visibilityChangedSpy.count(), 1); + QCOMPARE(visibilityChangedSpy.first().first().toBool(), false); +} + +void DecorationButtonTest::testChecked() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + // create a custom button and verify the base settings + MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + + // without being checkable it should not get checked + QSignalSpy checkedChangedSpy(&button, &KDecoration2::DecorationButton::checkedChanged); + QVERIFY(checkedChangedSpy.isValid()); + button.setChecked(true); + QCOMPARE(button.isChecked(), false); + QCOMPARE(checkedChangedSpy.count(), 0); + + // now let's set the checkable state + QSignalSpy checkableChangedSpy(&button, &KDecoration2::DecorationButton::checkableChanged); + QVERIFY(checkableChangedSpy.isValid()); + // setting to same should not emit + button.setCheckable(false); + QCOMPARE(checkableChangedSpy.count(), 0); + button.setCheckable(true); + QCOMPARE(button.isCheckable(), true); + QCOMPARE(checkableChangedSpy.count(), 1); + QCOMPARE(checkableChangedSpy.first().first().toBool(), true); + + // now it should be possible to check the button + button.setChecked(true); + QCOMPARE(button.isChecked(), true); + QCOMPARE(checkedChangedSpy.count(), 1); + // setting again should not change + button.setChecked(true); + QCOMPARE(button.isChecked(), true); + QCOMPARE(checkedChangedSpy.count(), 1); + // and disable + button.setChecked(false); + QCOMPARE(button.isChecked(), false); + QCOMPARE(checkedChangedSpy.count(), 2); + QCOMPARE(checkedChangedSpy.first().first().toBool(), true); + QCOMPARE(checkedChangedSpy.last().first().toBool(), false); + + // last but not least let's disable the checkable again, this should disable a checked button + button.setChecked(true); + QCOMPARE(button.isChecked(), true); + checkedChangedSpy.clear(); + QCOMPARE(checkedChangedSpy.count(), 0); + button.setCheckable(false); + QCOMPARE(button.isCheckable(), false); + QCOMPARE(checkableChangedSpy.count(), 2); + QCOMPARE(checkableChangedSpy.last().first().toBool(), false); + QCOMPARE(button.isChecked(), false); + QCOMPARE(checkedChangedSpy.count(), 1); +} + +void DecorationButtonTest::testEnabled() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + // create a custom button and verify the base settings + MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + + // enabling has influence on whether the button accepts events, so we need to fake events + QSignalSpy enabledChangedSpy(&button, &KDecoration2::DecorationButton::enabledChanged); + QVERIFY(enabledChangedSpy.isValid()); + // setting to same shouldn't change + button.setEnabled(true); + QCOMPARE(enabledChangedSpy.count(), 0); + button.setEnabled(false); + QCOMPARE(button.isEnabled(), false); + QCOMPARE(enabledChangedSpy.count(), 1); + QCOMPARE(enabledChangedSpy.first().first().toBool(), false); + + // now let's send it a hover entered event + QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged); + QVERIFY(hoveredChangedSpy.isValid()); + QHoverEvent event(QEvent::HoverEnter, QPointF(1, 1), QPointF(-1, -1)); + event.setAccepted(false); + button.event(&event); + QCOMPARE(event.isAccepted(), false); + QCOMPARE(hoveredChangedSpy.count(), 0); + + // if we enable the button again we should get a hovered changed signal + button.setEnabled(true); + QCOMPARE(enabledChangedSpy.count(), 2); + QCOMPARE(enabledChangedSpy.last().first().toBool(), true); + button.event(&event); + QCOMPARE(event.isAccepted(), true); + QCOMPARE(hoveredChangedSpy.count(), 1); + QCOMPARE(hoveredChangedSpy.first().first().toBool(), true); + + // if we disable the button now we get a hovered disabled signal + button.setEnabled(false); + QCOMPARE(hoveredChangedSpy.count(), 2); + QCOMPARE(hoveredChangedSpy.last().first().toBool(), false); +} + +void DecorationButtonTest::testPressIgnore_data() +{ + QTest::addColumn("enabled"); + QTest::addColumn("visible"); + QTest::addColumn("clickPos"); + QTest::addColumn("mouseButton"); + QTest::addColumn("expectedAccepted"); + + QTest::newRow("all-disabled") << false << false << QPoint(0, 0) << Qt::LeftButton << false; + QTest::newRow("enabled") << true << false << QPoint(0, 0) << Qt::LeftButton << false; + QTest::newRow("visible") << false << true << QPoint(0, 0) << Qt::LeftButton << false; + QTest::newRow("outside") << true << true << QPoint(20, 20) << Qt::LeftButton << false; + QTest::newRow("wrong-button") << true << true << QPoint(0, 0) << Qt::RightButton << false; +} + +void DecorationButtonTest::testPressIgnore() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + // create a custom button and verify the base settings + MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + button.setAcceptedButtons(Qt::LeftButton); + QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed); + QVERIFY(pressedSpy.isValid()); + QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged); + QVERIFY(pressedChangedSpy.isValid()); + + QFETCH(bool, enabled); + QFETCH(bool, visible); + button.setEnabled(enabled); + button.setVisible(visible); + + QFETCH(QPoint, clickPos); + QFETCH(Qt::MouseButton, mouseButton); + QMouseEvent pressEvent(QEvent::MouseButtonPress, clickPos, mouseButton, mouseButton, Qt::NoModifier); + pressEvent.setAccepted(false); + button.event(&pressEvent); + QTEST(pressEvent.isAccepted(), "expectedAccepted"); + QCOMPARE(button.isPressed(), false); + QVERIFY(pressedSpy.isEmpty()); + QVERIFY(pressedChangedSpy.isEmpty()); +} + +void DecorationButtonTest::testReleaseIgnore_data() +{ + QTest::addColumn("enabled"); + QTest::addColumn("visible"); + QTest::addColumn("clickPos"); + QTest::addColumn("mouseButton"); + QTest::addColumn("expectedAccepted"); + QTest::addColumn("expectedPressed"); + QTest::addColumn("expectedPressedChanged"); + + QTest::newRow("all-disabled") << false << false << QPoint(0, 0) << Qt::LeftButton << false << false << 2; + QTest::newRow("enabled") << true << false << QPoint(0, 0) << Qt::LeftButton << false << false << 2; + QTest::newRow("visible") << false << true << QPoint(0, 0) << Qt::LeftButton << false << false << 2; + QTest::newRow("outside") << true << true << QPoint(20, 20) << Qt::LeftButton << true << false << 2; + QTest::newRow("wrong-button") << true << true << QPoint(0, 0) << Qt::RightButton << false << true << 1; +} + +void DecorationButtonTest::testReleaseIgnore() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + // create a custom button and verify the base settings + MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + button.setAcceptedButtons(Qt::LeftButton); + button.setEnabled(true); + button.setVisible(true); + QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed); + QVERIFY(pressedSpy.isValid()); + QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged); + QVERIFY(pressedChangedSpy.isValid()); + QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked); + QVERIFY(clickedSpy.isValid()); + + QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(0, 0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + pressEvent.setAccepted(false); + button.event(&pressEvent); + QCOMPARE(pressEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), true); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.last().first().toBool(), true); + + QFETCH(bool, enabled); + QFETCH(bool, visible); + button.setEnabled(enabled); + button.setVisible(visible); + + QFETCH(QPoint, clickPos); + QFETCH(Qt::MouseButton, mouseButton); + QMouseEvent releaseEvent(QEvent::MouseButtonRelease, clickPos, mouseButton, Qt::NoButton, Qt::NoModifier); + releaseEvent.setAccepted(false); + button.event(&releaseEvent); + QTEST(releaseEvent.isAccepted(), "expectedAccepted"); + QTEST(button.isPressed(), "expectedPressed"); + QCOMPARE(pressedSpy.count(), 1); + QFETCH(int, expectedPressedChanged); + QCOMPARE(pressedChangedSpy.count(), expectedPressedChanged); + QCOMPARE(pressedChangedSpy.last().first().toBool(), button.isPressed()); + QCOMPARE(clickedSpy.count(), 0); +} + +void DecorationButtonTest::testHoverEnterIgnore_data() +{ + QTest::addColumn("enabled"); + QTest::addColumn("visible"); + QTest::addColumn("enterPos"); + + QTest::newRow("all-disabled") << false << false << QPoint(0, 0); + QTest::newRow("enabled") << true << false << QPoint(0, 0); + QTest::newRow("visible") << false << true << QPoint(0, 0); + QTest::newRow("outside") << true << true << QPoint(20, 20); +} + +void DecorationButtonTest::testHoverEnterIgnore() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + // create a custom button and verify the base settings + MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + QSignalSpy pointerEnteredSpy(&button, &KDecoration2::DecorationButton::pointerEntered); + QVERIFY(pointerEnteredSpy.isValid()); + QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged); + QVERIFY(hoveredChangedSpy.isValid()); + + QFETCH(bool, enabled); + QFETCH(bool, visible); + button.setEnabled(enabled); + button.setVisible(visible); + + QFETCH(QPoint, enterPos); + QHoverEvent enterEvent(QEvent::HoverEnter, enterPos, QPoint()); + enterEvent.setAccepted(false); + button.event(&enterEvent); + QCOMPARE(enterEvent.isAccepted(), false); + QCOMPARE(button.isHovered(), false); + QCOMPARE(pointerEnteredSpy.count(), 0); + QCOMPARE(hoveredChangedSpy.count(), 0); + + // send a HoverLeft event should not be processed + button.setEnabled(true); + button.setVisible(true); + QHoverEvent leftEvent(QEvent::HoverLeave, QPoint(20, 20), enterPos); + leftEvent.setAccepted(false); + button.event(&leftEvent); + QCOMPARE(leftEvent.isAccepted(), false); +} + +void DecorationButtonTest::testHoverLeaveIgnore_data() +{ + QTest::addColumn("enabled"); + QTest::addColumn("visible"); + QTest::addColumn("leavePos"); + QTest::addColumn("expectedLeaveCount"); + QTest::addColumn("expectedHoverChangedCount"); + + QTest::newRow("all-disabled") << false << false << QPoint(20, 20) << 1 << 2; + QTest::newRow("enabled") << true << false << QPoint(20, 20) << 1 << 2; + QTest::newRow("visible") << false << true << QPoint(20, 20) << 1 << 2; + QTest::newRow("inside") << true << true << QPoint(5, 5) << 0 << 1; +} + +void DecorationButtonTest::testHoverLeaveIgnore() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + // create a custom button and verify the base settings + MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + button.setEnabled(true); + button.setVisible(true); + QSignalSpy pointerEnteredSpy(&button, &KDecoration2::DecorationButton::pointerEntered); + QVERIFY(pointerEnteredSpy.isValid()); + QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged); + QVERIFY(hoveredChangedSpy.isValid()); + QSignalSpy pointerLeavedSpy(&button, &KDecoration2::DecorationButton::pointerLeft); + QVERIFY(pointerLeavedSpy.isValid()); + + QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(0, 0), QPoint()); + enterEvent.setAccepted(false); + button.event(&enterEvent); + QCOMPARE(enterEvent.isAccepted(), true); + QCOMPARE(button.isHovered(), true); + QCOMPARE(pointerEnteredSpy.count(), 1); + QCOMPARE(hoveredChangedSpy.count(), 1); + QCOMPARE(hoveredChangedSpy.last().first().toBool(), true); + + QFETCH(bool, enabled); + QFETCH(bool, visible); + button.setEnabled(enabled); + button.setVisible(visible); + + QFETCH(QPoint, leavePos); + QHoverEvent leftEvent(QEvent::HoverLeave, leavePos, QPoint(0, 0)); + leftEvent.setAccepted(false); + button.event(&leftEvent); + QCOMPARE(leftEvent.isAccepted(), false); + QCOMPARE(pointerEnteredSpy.count(), 1); + QFETCH(int, expectedLeaveCount); + QFETCH(int, expectedHoverChangedCount); + QCOMPARE(pointerLeavedSpy.count(), expectedLeaveCount); + QCOMPARE(hoveredChangedSpy.count(), expectedHoverChangedCount); + QCOMPARE(hoveredChangedSpy.last().first().toBool(), button.isHovered()); +} + +void DecorationButtonTest::testHover() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + // create a custom button and verify the base settings + MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration); + button.setGeometry(QRectF(0, 0, 10, 10)); + button.setEnabled(true); + button.setVisible(true); + QSignalSpy pointerEnteredSpy(&button, &KDecoration2::DecorationButton::pointerEntered); + QVERIFY(pointerEnteredSpy.isValid()); + QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged); + QVERIFY(hoveredChangedSpy.isValid()); + QSignalSpy pointerLeavedSpy(&button, &KDecoration2::DecorationButton::pointerLeft); + QVERIFY(pointerLeavedSpy.isValid()); + + QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(0, 0), QPoint()); + enterEvent.setAccepted(false); + button.event(&enterEvent); + QCOMPARE(enterEvent.isAccepted(), true); + QCOMPARE(button.isHovered(), true); + QCOMPARE(pointerEnteredSpy.count(), 1); + QCOMPARE(hoveredChangedSpy.count(), 1); + QCOMPARE(hoveredChangedSpy.last().first().toBool(), true); + + // send in a hovermove event - it's passed through, but not used + QHoverEvent moveEvent(QEvent::HoverMove, QPoint(5, 0), QPoint(0, 0)); + moveEvent.setAccepted(false); + button.event(&moveEvent); + QCOMPARE(moveEvent.isAccepted(), false); + + QHoverEvent leftEvent(QEvent::HoverLeave, QPointF(10.1, 0.0), QPointF(0, 0)); + leftEvent.setAccepted(false); + button.event(&leftEvent); + QCOMPARE(leftEvent.isAccepted(), true); + QCOMPARE(pointerEnteredSpy.count(), 1); + QCOMPARE(pointerLeavedSpy.count(), 1); + QCOMPARE(hoveredChangedSpy.count(), 2); + QCOMPARE(hoveredChangedSpy.last().first().toBool(), false); +} + +void DecorationButtonTest::testMouseMove_data() +{ + QTest::addColumn("enabled"); + QTest::addColumn("visible"); + QTest::addColumn("movePos"); + QTest::addColumn("expectedAccepted"); + QTest::addColumn("expectedHovered"); + QTest::addColumn("expectedChangedCount"); + + QTest::newRow("outside") << true << true << QPointF(10.1, 10) << true << false << 2; + QTest::newRow("inside") << true << true << QPointF(5, 5) << false << true << 1; + QTest::newRow("disabled") << false << true << QPointF(10, 10) << false << false << 2; + QTest::newRow("invisible") << true << false << QPointF(10, 10) << false << false << 2; +} + +void DecorationButtonTest::testMouseMove() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + // create a custom button and verify the base settings + MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration); + button.setGeometry(QRectF(0, 0, 10, 10)); + button.setEnabled(true); + button.setVisible(true); + QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged); + QVERIFY(hoveredChangedSpy.isValid()); + QSignalSpy pointerLeavedSpy(&button, &KDecoration2::DecorationButton::pointerLeft); + QVERIFY(pointerLeavedSpy.isValid()); + + QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(0, 0), QPoint()); + enterEvent.setAccepted(false); + button.event(&enterEvent); + QCOMPARE(enterEvent.isAccepted(), true); + QCOMPARE(button.isHovered(), true); + QCOMPARE(hoveredChangedSpy.count(), 1); + QCOMPARE(hoveredChangedSpy.last().first().toBool(), true); + + QFETCH(bool, enabled); + button.setEnabled(enabled); + QFETCH(bool, visible); + button.setVisible(visible); + + QFETCH(QPointF, movePos); + QMouseEvent mouseMoveEvent(QEvent::MouseMove, movePos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + mouseMoveEvent.setAccepted(false); + button.event(&mouseMoveEvent); + QTEST(mouseMoveEvent.isAccepted(), "expectedAccepted"); + QTEST(button.isHovered(), "expectedHovered"); + QFETCH(int, expectedChangedCount); + QCOMPARE(hoveredChangedSpy.count(), expectedChangedCount); + QCOMPARE(hoveredChangedSpy.last().first().toBool(), button.isHovered()); + + // explicit further move event outside of button + QMouseEvent mouseMoveEvent2(QEvent::MouseMove, QPoint(50, 50), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + mouseMoveEvent2.setAccepted(false); + button.event(&mouseMoveEvent2); + QTEST(mouseMoveEvent2.isAccepted(), "expectedHovered"); + QCOMPARE(button.isHovered(), false); +} + +void DecorationButtonTest::testClose() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + MockClient *client = bridge.lastCreatedClient(); + MockButton button(KDecoration2::DecorationButtonType::Close, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + + QCOMPARE(button.isEnabled(), false); + QCOMPARE(button.isCheckable(), false); + QCOMPARE(button.isChecked(), false); + QCOMPARE(button.isVisible(), true); + QCOMPARE(button.acceptedButtons(), Qt::LeftButton); + + // if the client is closeable the button should get enabled + QSignalSpy closeableChangedSpy(mockDecoration.client(), &KDecoration2::DecoratedClient::closeableChanged); + QVERIFY(closeableChangedSpy.isValid()); + client->setCloseable(true); + QCOMPARE(button.isEnabled(), true); + QCOMPARE(closeableChangedSpy.count(), 1); + QCOMPARE(closeableChangedSpy.first().first().toBool(), true); + + // clicking the button should trigger a request for close + QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked); + QVERIFY(clickedSpy.isValid()); + QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed); + QVERIFY(pressedSpy.isValid()); + QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released); + QVERIFY(releasedSpy.isValid()); + QSignalSpy closeRequestedSpy(client, &MockClient::closeRequested); + QVERIFY(closeRequestedSpy.isValid()); + QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged); + QVERIFY(pressedChangedSpy.isValid()); + + QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + pressEvent.setAccepted(false); + button.event(&pressEvent); + QCOMPARE(pressEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), true); + QCOMPARE(clickedSpy.count(), 0); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 0); + QCOMPARE(closeRequestedSpy.count(), 0); + QCOMPARE(pressedChangedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.first().first().toBool(), true); + + QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + releaseEvent.setAccepted(false); + button.event(&releaseEvent); + QCOMPARE(releaseEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), false); + QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.first().first().value(), Qt::LeftButton); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 1); + QVERIFY(closeRequestedSpy.wait()); + QCOMPARE(closeRequestedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.count(), 2); + QCOMPARE(pressedChangedSpy.last().first().toBool(), false); +} + +void DecorationButtonTest::testMinimize() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + MockClient *client = bridge.lastCreatedClient(); + MockButton button(KDecoration2::DecorationButtonType::Minimize, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + + QCOMPARE(button.isEnabled(), false); + QCOMPARE(button.isCheckable(), false); + QCOMPARE(button.isChecked(), false); + QCOMPARE(button.isVisible(), true); + QCOMPARE(button.acceptedButtons(), Qt::LeftButton); + + // if the client is minimizeable the button should get enabled + QSignalSpy minimizableChangedSpy(mockDecoration.client(), &KDecoration2::DecoratedClient::minimizeableChanged); + QVERIFY(minimizableChangedSpy.isValid()); + client->setMinimizable(true); + QCOMPARE(button.isEnabled(), true); + QCOMPARE(minimizableChangedSpy.count(), 1); + QCOMPARE(minimizableChangedSpy.first().first().toBool(), true); + + // clicking the button should trigger a request for minimize + QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked); + QVERIFY(clickedSpy.isValid()); + QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed); + QVERIFY(pressedSpy.isValid()); + QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released); + QVERIFY(releasedSpy.isValid()); + QSignalSpy minimizeRequestedSpy(client, &MockClient::minimizeRequested); + QVERIFY(minimizeRequestedSpy.isValid()); + QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged); + QVERIFY(pressedChangedSpy.isValid()); + + QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + pressEvent.setAccepted(false); + button.event(&pressEvent); + QCOMPARE(pressEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), true); + QCOMPARE(clickedSpy.count(), 0); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 0); + QCOMPARE(minimizeRequestedSpy.count(), 0); + QCOMPARE(pressedChangedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.first().first().toBool(), true); + + QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + releaseEvent.setAccepted(false); + button.event(&releaseEvent); + QCOMPARE(releaseEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), false); + QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.first().first().value(), Qt::LeftButton); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 1); + QVERIFY(minimizeRequestedSpy.wait()); + QCOMPARE(minimizeRequestedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.count(), 2); + QCOMPARE(pressedChangedSpy.last().first().toBool(), false); +} + +void DecorationButtonTest::testQuickHelp() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + MockClient *client = bridge.lastCreatedClient(); + MockButton button(KDecoration2::DecorationButtonType::ContextHelp, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + + QCOMPARE(button.isEnabled(), true); + QCOMPARE(button.isCheckable(), false); + QCOMPARE(button.isChecked(), false); + QCOMPARE(button.isVisible(), false); + QCOMPARE(button.acceptedButtons(), Qt::LeftButton); + + // if the client provides quickhelp the button should get enabled + QSignalSpy providesContextHelpChangedSpy(mockDecoration.client(), &KDecoration2::DecoratedClient::providesContextHelpChanged); + QVERIFY(providesContextHelpChangedSpy.isValid()); + client->setProvidesContextHelp(true); + QCOMPARE(button.isVisible(), true); + QCOMPARE(providesContextHelpChangedSpy.count(), 1); + QCOMPARE(providesContextHelpChangedSpy.first().first().toBool(), true); + + // clicking the button should trigger a request for minimize + QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked); + QVERIFY(clickedSpy.isValid()); + QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed); + QVERIFY(pressedSpy.isValid()); + QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released); + QVERIFY(releasedSpy.isValid()); + QSignalSpy quickhelpRequestedSpy(client, &MockClient::quickHelpRequested); + QVERIFY(quickhelpRequestedSpy.isValid()); + QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged); + QVERIFY(pressedChangedSpy.isValid()); + + QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + pressEvent.setAccepted(false); + button.event(&pressEvent); + QCOMPARE(pressEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), true); + QCOMPARE(clickedSpy.count(), 0); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 0); + QCOMPARE(quickhelpRequestedSpy.count(), 0); + QCOMPARE(pressedChangedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.first().first().toBool(), true); + + QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + releaseEvent.setAccepted(false); + button.event(&releaseEvent); + QCOMPARE(releaseEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), false); + QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.first().first().value(), Qt::LeftButton); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 1); + QVERIFY(quickhelpRequestedSpy.wait()); + QCOMPARE(quickhelpRequestedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.count(), 2); + QCOMPARE(pressedChangedSpy.last().first().toBool(), false); +} + +void DecorationButtonTest::testKeepAbove() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + MockButton button(KDecoration2::DecorationButtonType::KeepAbove, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + + QCOMPARE(button.isEnabled(), true); + QCOMPARE(button.isCheckable(), true); + QCOMPARE(button.isChecked(), false); + QCOMPARE(button.isVisible(), true); + QCOMPARE(button.acceptedButtons(), Qt::LeftButton); + + // clicking the button should trigger a request for keep above changed + QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked); + QVERIFY(clickedSpy.isValid()); + QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed); + QVERIFY(pressedSpy.isValid()); + QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released); + QVERIFY(releasedSpy.isValid()); + QSignalSpy keepAboveChangedSpy(mockDecoration.client(), &KDecoration2::DecoratedClient::keepAboveChanged); + QVERIFY(keepAboveChangedSpy.isValid()); + QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged); + QVERIFY(pressedChangedSpy.isValid()); + + QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + pressEvent.setAccepted(false); + button.event(&pressEvent); + QCOMPARE(pressEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), true); + QCOMPARE(clickedSpy.count(), 0); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 0); + QCOMPARE(keepAboveChangedSpy.count(), 0); + QCOMPARE(pressedChangedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.first().first().toBool(), true); + + QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + releaseEvent.setAccepted(false); + button.event(&releaseEvent); + QCOMPARE(releaseEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), false); + QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.first().first().value(), Qt::LeftButton); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 1); + QVERIFY(keepAboveChangedSpy.wait()); + QCOMPARE(keepAboveChangedSpy.count(), 1); + QCOMPARE(keepAboveChangedSpy.first().first().toBool(), true); + QCOMPARE(pressedChangedSpy.count(), 2); + QCOMPARE(pressedChangedSpy.last().first().toBool(), false); + QCOMPARE(button.isChecked(), true); + + // click once more should change again + button.event(&pressEvent); + button.event(&releaseEvent); + QVERIFY(keepAboveChangedSpy.wait()); + QCOMPARE(keepAboveChangedSpy.count(), 2); + QCOMPARE(keepAboveChangedSpy.first().first().toBool(), true); + QCOMPARE(keepAboveChangedSpy.last().first().toBool(), false); + QCOMPARE(button.isChecked(), false); +} + +void DecorationButtonTest::testKeepBelow() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + MockButton button(KDecoration2::DecorationButtonType::KeepBelow, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + + QCOMPARE(button.isEnabled(), true); + QCOMPARE(button.isCheckable(), true); + QCOMPARE(button.isChecked(), false); + QCOMPARE(button.isVisible(), true); + QCOMPARE(button.acceptedButtons(), Qt::LeftButton); + + // clicking the button should trigger a request for keep above changed + QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked); + QVERIFY(clickedSpy.isValid()); + QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed); + QVERIFY(pressedSpy.isValid()); + QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released); + QVERIFY(releasedSpy.isValid()); + QSignalSpy keepBelowChangedSpy(mockDecoration.client(), &KDecoration2::DecoratedClient::keepBelowChanged); + QVERIFY(keepBelowChangedSpy.isValid()); + QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged); + QVERIFY(pressedChangedSpy.isValid()); + + QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + pressEvent.setAccepted(false); + button.event(&pressEvent); + QCOMPARE(pressEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), true); + QCOMPARE(clickedSpy.count(), 0); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 0); + QCOMPARE(keepBelowChangedSpy.count(), 0); + QCOMPARE(pressedChangedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.first().first().toBool(), true); + + QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + releaseEvent.setAccepted(false); + button.event(&releaseEvent); + QCOMPARE(releaseEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), false); + QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.first().first().value(), Qt::LeftButton); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 1); + QVERIFY(keepBelowChangedSpy.wait()); + QCOMPARE(keepBelowChangedSpy.count(), 1); + QCOMPARE(keepBelowChangedSpy.first().first().toBool(), true); + QCOMPARE(pressedChangedSpy.count(), 2); + QCOMPARE(pressedChangedSpy.last().first().toBool(), false); + QCOMPARE(button.isChecked(), true); + + // click once more should change again + button.event(&pressEvent); + button.event(&releaseEvent); + QVERIFY(keepBelowChangedSpy.wait()); + QCOMPARE(keepBelowChangedSpy.count(), 2); + QCOMPARE(keepBelowChangedSpy.first().first().toBool(), true); + QCOMPARE(keepBelowChangedSpy.last().first().toBool(), false); + QCOMPARE(button.isChecked(), false); +} + +void DecorationButtonTest::testShade() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + MockClient *client = bridge.lastCreatedClient(); + MockButton button(KDecoration2::DecorationButtonType::Shade, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + + QCOMPARE(button.isEnabled(), false); + QCOMPARE(button.isCheckable(), true); + QCOMPARE(button.isChecked(), false); + QCOMPARE(button.isVisible(), true); + QCOMPARE(button.acceptedButtons(), Qt::LeftButton); + + // if the client is shadeable the button should get enabled + const auto decoClient = mockDecoration.client(); + QSignalSpy shadeableChangedSpy(decoClient, &KDecoration2::DecoratedClient::shadeableChanged); + QVERIFY(shadeableChangedSpy.isValid()); + client->setShadeable(true); + QCOMPARE(button.isEnabled(), true); + QCOMPARE(shadeableChangedSpy.count(), 1); + QCOMPARE(shadeableChangedSpy.first().first().toBool(), true); + + // clicking the button should trigger a request for keep above changed + QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked); + QVERIFY(clickedSpy.isValid()); + QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed); + QVERIFY(pressedSpy.isValid()); + QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released); + QVERIFY(releasedSpy.isValid()); + QSignalSpy shadedChangedSpy(decoClient, &KDecoration2::DecoratedClient::shadedChanged); + QVERIFY(shadedChangedSpy.isValid()); + QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged); + QVERIFY(pressedChangedSpy.isValid()); + + QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + pressEvent.setAccepted(false); + button.event(&pressEvent); + QCOMPARE(pressEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), true); + QCOMPARE(clickedSpy.count(), 0); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 0); + QCOMPARE(shadedChangedSpy.count(), 0); + QCOMPARE(pressedChangedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.first().first().toBool(), true); + + QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + releaseEvent.setAccepted(false); + button.event(&releaseEvent); + QCOMPARE(releaseEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), false); + QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.first().first().value(), Qt::LeftButton); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 1); + QVERIFY(shadedChangedSpy.wait()); + QCOMPARE(shadedChangedSpy.count(), 1); + QCOMPARE(shadedChangedSpy.first().first().toBool(), true); + QCOMPARE(pressedChangedSpy.count(), 2); + QCOMPARE(pressedChangedSpy.last().first().toBool(), false); + QCOMPARE(button.isChecked(), true); + + // click once more should change again + button.event(&pressEvent); + button.event(&releaseEvent); + QVERIFY(shadedChangedSpy.wait()); + QCOMPARE(shadedChangedSpy.count(), 2); + QCOMPARE(shadedChangedSpy.first().first().toBool(), true); + QCOMPARE(shadedChangedSpy.last().first().toBool(), false); + QCOMPARE(button.isChecked(), false); +} + +void DecorationButtonTest::testMaximize() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + MockClient *client = bridge.lastCreatedClient(); + MockButton button(KDecoration2::DecorationButtonType::Maximize, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + + QCOMPARE(button.isEnabled(), false); + QCOMPARE(button.isCheckable(), true); + QCOMPARE(button.isChecked(), false); + QCOMPARE(button.isVisible(), true); + QCOMPARE(button.acceptedButtons(), Qt::LeftButton | Qt::MiddleButton | Qt::RightButton); + + // if the client is maximizable the button should get enabled + const auto decoClient = mockDecoration.client(); + QSignalSpy maximizableChangedSpy(decoClient, &KDecoration2::DecoratedClient::maximizeableChanged); + QVERIFY(maximizableChangedSpy.isValid()); + client->setMaximizable(true); + QCOMPARE(button.isEnabled(), true); + QCOMPARE(maximizableChangedSpy.count(), 1); + QCOMPARE(maximizableChangedSpy.first().first().toBool(), true); + + // clicking the button should trigger a request for keep above changed + QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked); + QVERIFY(clickedSpy.isValid()); + QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed); + QVERIFY(pressedSpy.isValid()); + QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released); + QVERIFY(releasedSpy.isValid()); + QSignalSpy maximizedChangedSpy(decoClient, &KDecoration2::DecoratedClient::maximizedChanged); + QVERIFY(maximizedChangedSpy.isValid()); + QSignalSpy maximizedVerticallyChangedSpy(decoClient, &KDecoration2::DecoratedClient::maximizedVerticallyChanged); + QVERIFY(maximizedVerticallyChangedSpy.isValid()); + QSignalSpy maximizedHorizontallyChangedSpy(decoClient, &KDecoration2::DecoratedClient::maximizedHorizontallyChanged); + QVERIFY(maximizedHorizontallyChangedSpy.isValid()); + QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged); + QVERIFY(pressedChangedSpy.isValid()); + + QMouseEvent leftPressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + leftPressEvent.setAccepted(false); + button.event(&leftPressEvent); + QCOMPARE(leftPressEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), true); + QCOMPARE(clickedSpy.count(), 0); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 0); + QCOMPARE(maximizedChangedSpy.count(), 0); + QCOMPARE(pressedChangedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.first().first().toBool(), true); + + QMouseEvent leftReleaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + leftReleaseEvent.setAccepted(false); + button.event(&leftReleaseEvent); + QCOMPARE(leftReleaseEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), false); + QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.first().first().value(), Qt::LeftButton); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 1); + QVERIFY(maximizedChangedSpy.wait()); + QCOMPARE(maximizedChangedSpy.count(), 1); + QCOMPARE(maximizedChangedSpy.first().first().toBool(), true); + QCOMPARE(pressedChangedSpy.count(), 2); + QCOMPARE(pressedChangedSpy.last().first().toBool(), false); + QCOMPARE(button.isChecked(), true); + + // clicking again should set to restored + button.event(&leftPressEvent); + button.event(&leftReleaseEvent); + QVERIFY(maximizedChangedSpy.wait()); + QCOMPARE(maximizedChangedSpy.count(), 2); + QCOMPARE(maximizedChangedSpy.first().first().toBool(), true); + QCOMPARE(maximizedChangedSpy.last().first().toBool(), false); + QCOMPARE(button.isChecked(), false); + + // test the other buttons + QMouseEvent rightPressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::RightButton, Qt::RightButton, Qt::NoModifier); + rightPressEvent.setAccepted(false); + button.event(&rightPressEvent); + QCOMPARE(rightPressEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), true); + + QMouseEvent middlePressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::MiddleButton, Qt::MiddleButton, Qt::NoModifier); + middlePressEvent.setAccepted(false); + button.event(&middlePressEvent); + QCOMPARE(middlePressEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), true); + + QMouseEvent middleReleaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::MiddleButton, Qt::NoButton, Qt::NoModifier); + middleReleaseEvent.setAccepted(false); + button.event(&middleReleaseEvent); + QCOMPARE(middleReleaseEvent.isAccepted(), true); + QVERIFY(maximizedHorizontallyChangedSpy.wait()); + QCOMPARE(button.isPressed(), true); + QCOMPARE(clickedSpy.count(), 3); + QCOMPARE(button.isChecked(), false); + QCOMPARE(client->isMaximizedHorizontally(), true); + QCOMPARE(client->isMaximizedVertically(), false); + + QMouseEvent rightReleaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::RightButton, Qt::NoButton, Qt::NoModifier); + rightReleaseEvent.setAccepted(false); + button.event(&rightReleaseEvent); + QCOMPARE(rightReleaseEvent.isAccepted(), true); + QVERIFY(maximizedVerticallyChangedSpy.wait()); + QCOMPARE(button.isPressed(), false); + QCOMPARE(clickedSpy.count(), 4); + QCOMPARE(client->isMaximizedHorizontally(), true); + QCOMPARE(client->isMaximizedVertically(), true); + QCOMPARE(button.isChecked(), true); +} + +void DecorationButtonTest::testOnAllDesktops() +{ + MockBridge bridge; + auto decoSettings = std::make_shared(&bridge); + MockDecoration mockDecoration(&bridge); + mockDecoration.setSettings(decoSettings); + MockButton button(KDecoration2::DecorationButtonType::OnAllDesktops, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + + QCOMPARE(button.isEnabled(), true); + QCOMPARE(button.isCheckable(), true); + QCOMPARE(button.isChecked(), false); + QCOMPARE(button.isVisible(), false); + QCOMPARE(button.acceptedButtons(), Qt::LeftButton); + const auto decoClient = mockDecoration.client(); + QCOMPARE(decoClient->isOnAllDesktops(), false); + + MockSettings *settings = bridge.lastCreatedSettings(); + QVERIFY(settings); + + QSignalSpy onAllDesktopsAvailableChangedSpy(decoSettings.get(), &KDecoration2::DecorationSettings::onAllDesktopsAvailableChanged); + QVERIFY(onAllDesktopsAvailableChangedSpy.isValid()); + QSignalSpy visibleChangedSpy(&button, &KDecoration2::DecorationButton::visibilityChanged); + QVERIFY(visibleChangedSpy.isValid()); + + settings->setOnAllDesktopsAvailabe(true); + QCOMPARE(onAllDesktopsAvailableChangedSpy.count(), 1); + QCOMPARE(onAllDesktopsAvailableChangedSpy.last().first().toBool(), true); + QCOMPARE(visibleChangedSpy.count(), 1); + QCOMPARE(visibleChangedSpy.last().first().toBool(), true); + + // clicking the button should trigger a request for on all desktops + QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked); + QVERIFY(clickedSpy.isValid()); + QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed); + QVERIFY(pressedSpy.isValid()); + QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released); + QVERIFY(releasedSpy.isValid()); + QSignalSpy onAllDesktopsChangedSpy(decoClient, &KDecoration2::DecoratedClient::onAllDesktopsChanged); + QVERIFY(onAllDesktopsChangedSpy.isValid()); + QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged); + QVERIFY(pressedChangedSpy.isValid()); + + QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + pressEvent.setAccepted(false); + button.event(&pressEvent); + QCOMPARE(pressEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), true); + QCOMPARE(clickedSpy.count(), 0); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 0); + QCOMPARE(onAllDesktopsChangedSpy.count(), 0); + QCOMPARE(pressedChangedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.first().first().toBool(), true); + + QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + releaseEvent.setAccepted(false); + button.event(&releaseEvent); + QCOMPARE(releaseEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), false); + QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.first().first().value(), Qt::LeftButton); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 1); + QVERIFY(onAllDesktopsChangedSpy.wait()); + QCOMPARE(onAllDesktopsChangedSpy.count(), 1); + QCOMPARE(onAllDesktopsChangedSpy.first().first().toBool(), true); + QCOMPARE(pressedChangedSpy.count(), 2); + QCOMPARE(pressedChangedSpy.last().first().toBool(), false); + QCOMPARE(button.isChecked(), true); +} + +void DecorationButtonTest::testMenu() +{ + MockBridge bridge; + auto decoSettings = std::make_shared(&bridge); + MockDecoration mockDecoration(&bridge); + mockDecoration.setSettings(decoSettings); + MockClient *client = bridge.lastCreatedClient(); + MockButton button(KDecoration2::DecorationButtonType::Menu, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + + QCOMPARE(button.isEnabled(), true); + QCOMPARE(button.isCheckable(), false); + QCOMPARE(button.isChecked(), false); + QCOMPARE(button.isVisible(), true); + QCOMPARE(button.acceptedButtons(), Qt::LeftButton | Qt::RightButton); + + // clicking the button should trigger a request for menu button + QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked); + QVERIFY(clickedSpy.isValid()); + QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed); + QVERIFY(pressedSpy.isValid()); + QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released); + QVERIFY(releasedSpy.isValid()); + QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged); + QVERIFY(pressedChangedSpy.isValid()); + QSignalSpy menuRequestedSpy(client, &MockClient::menuRequested); + QVERIFY(menuRequestedSpy.isValid()); + + QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + pressEvent.setAccepted(false); + button.event(&pressEvent); + QCOMPARE(pressEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), true); + QCOMPARE(clickedSpy.count(), 0); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 0); + QCOMPARE(menuRequestedSpy.count(), 0); + QCOMPARE(pressedChangedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.first().first().toBool(), true); + + QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + releaseEvent.setAccepted(false); + button.event(&releaseEvent); + QCOMPARE(releaseEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), false); + QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.first().first().value(), Qt::LeftButton); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 1); + QVERIFY(menuRequestedSpy.wait()); + QCOMPARE(menuRequestedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.count(), 2); + QCOMPARE(pressedChangedSpy.last().first().toBool(), false); +} + +void DecorationButtonTest::testMenuDoubleClick() +{ + MockBridge bridge; + auto decoSettings = std::make_shared(&bridge); + MockDecoration mockDecoration(&bridge); + mockDecoration.setSettings(decoSettings); + MockClient *client = bridge.lastCreatedClient(); + MockButton button(KDecoration2::DecorationButtonType::Menu, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + + MockSettings *settings = bridge.lastCreatedSettings(); + QVERIFY(settings); + QSignalSpy closeOnDoubleClickOnMenuChangedSpy(decoSettings.get(), &KDecoration2::DecorationSettings::closeOnDoubleClickOnMenuChanged); + QVERIFY(closeOnDoubleClickOnMenuChangedSpy.isValid()); + settings->setCloseOnDoubleClickOnMenu(true); + QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.count(), 1); + QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.last().first().toBool(), true); + + // button used a queued connection, so we need to run event loop + QCoreApplication::processEvents(); + + QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked); + QVERIFY(clickedSpy.isValid()); + QSignalSpy doubleClickedSpy(&button, &KDecoration2::DecorationButton::doubleClicked); + QVERIFY(doubleClickedSpy.isValid()); + QSignalSpy closeRequestedSpy(client, &MockClient::closeRequested); + QVERIFY(closeRequestedSpy.isValid()); + QSignalSpy menuRequestedSpy(client, &MockClient::menuRequested); + QVERIFY(menuRequestedSpy.isValid()); + + QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + pressEvent.setAccepted(false); + button.event(&pressEvent); + QCOMPARE(pressEvent.isAccepted(), true); + QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + releaseEvent.setAccepted(false); + button.event(&releaseEvent); + QCOMPARE(releaseEvent.isAccepted(), true); + // should not have emitted a clicked + QCOMPARE(clickedSpy.count(), 0); + QCOMPARE(doubleClickedSpy.count(), 0); + + // another press should trigger the double click event + pressEvent.setAccepted(false); + button.event(&pressEvent); + QCOMPARE(pressEvent.isAccepted(), true); + QVERIFY(closeRequestedSpy.wait()); + QCOMPARE(doubleClickedSpy.count(), 1); + QCOMPARE(closeRequestedSpy.count(), 1); + QCOMPARE(menuRequestedSpy.count(), 0); + + releaseEvent.setAccepted(false); + button.event(&releaseEvent); + QCOMPARE(releaseEvent.isAccepted(), true); + QCOMPARE(clickedSpy.count(), 0); + // run events + QCoreApplication::processEvents(); + QCOMPARE(closeRequestedSpy.count(), 1); + QCOMPARE(menuRequestedSpy.count(), 0); + + // a double click of right button shouldn't trigger the double click event + QMouseEvent rightPressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::RightButton, Qt::RightButton, Qt::NoModifier); + rightPressEvent.setAccepted(false); + button.event(&rightPressEvent); + QCOMPARE(rightPressEvent.isAccepted(), true); + QMouseEvent rightReleaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::RightButton, Qt::NoButton, Qt::NoModifier); + rightReleaseEvent.setAccepted(false); + button.event(&rightReleaseEvent); + QCOMPARE(rightReleaseEvent.isAccepted(), true); + QCOMPARE(clickedSpy.count(), 1); + QVERIFY(menuRequestedSpy.wait()); + QCOMPARE(menuRequestedSpy.count(), 1); + // second click + rightPressEvent.setAccepted(false); + button.event(&rightPressEvent); + QCOMPARE(rightPressEvent.isAccepted(), true); + rightReleaseEvent.setAccepted(false); + button.event(&rightReleaseEvent); + QCOMPARE(rightReleaseEvent.isAccepted(), true); + QCOMPARE(clickedSpy.count(), 2); + QVERIFY(menuRequestedSpy.wait()); + QCOMPARE(menuRequestedSpy.count(), 2); +} + +void DecorationButtonTest::testMenuPressAndHold() +{ + MockBridge bridge; + auto decoSettings = std::make_shared(&bridge); + MockDecoration mockDecoration(&bridge); + mockDecoration.setSettings(decoSettings); + MockClient *client = bridge.lastCreatedClient(); + MockButton button(KDecoration2::DecorationButtonType::Menu, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + + MockSettings *settings = bridge.lastCreatedSettings(); + QVERIFY(settings); + QSignalSpy closeOnDoubleClickOnMenuChangedSpy(decoSettings.get(), &KDecoration2::DecorationSettings::closeOnDoubleClickOnMenuChanged); + QVERIFY(closeOnDoubleClickOnMenuChangedSpy.isValid()); + settings->setCloseOnDoubleClickOnMenu(true); + QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.count(), 1); + QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.last().first().toBool(), true); + + // button used a queued connection, so we need to run event loop + QCoreApplication::processEvents(); + + QSignalSpy menuRequestedSpy(client, &MockClient::menuRequested); + QVERIFY(menuRequestedSpy.isValid()); + QSignalSpy doubleClickedSpy(&button, &KDecoration2::DecorationButton::doubleClicked); + QVERIFY(doubleClickedSpy.isValid()); + QSignalSpy closeRequestedSpy(client, &MockClient::closeRequested); + QVERIFY(closeRequestedSpy.isValid()); + QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked); + QVERIFY(clickedSpy.isValid()); + + // send a press event + QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + pressEvent.setAccepted(false); + button.event(&pressEvent); + QCOMPARE(pressEvent.isAccepted(), true); + QCOMPARE(clickedSpy.count(), 0); + + // and wait + QVERIFY(menuRequestedSpy.wait()); + QCOMPARE(menuRequestedSpy.count(), 1); + QCOMPARE(clickedSpy.count(), 1); + + // send release event + QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + releaseEvent.setAccepted(false); + button.event(&releaseEvent); + QCOMPARE(releaseEvent.isAccepted(), true); + QCOMPARE(clickedSpy.count(), 1); + + QTest::qWait(QGuiApplication::styleHints()->mouseDoubleClickInterval() + 5); + + // and it shouldn't be a double click + pressEvent.setAccepted(false); + button.event(&pressEvent); + QCOMPARE(pressEvent.isAccepted(), true); + + // while waiting we disable click and hold + settings->setCloseOnDoubleClickOnMenu(false); + QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.count(), 2); + QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.last().first().toBool(), false); + // button used a queued connection, so we need to run event loop + QCoreApplication::processEvents(); + // and releasing should emit the menu signal + releaseEvent.setAccepted(false); + button.event(&releaseEvent); + QCOMPARE(releaseEvent.isAccepted(), true); + QCOMPARE(clickedSpy.count(), 2); + QVERIFY(menuRequestedSpy.wait()); + QCOMPARE(menuRequestedSpy.count(), 2); + // never got a dobule click + QCOMPARE(closeRequestedSpy.count(), 0); +} + +void DecorationButtonTest::testApplicationMenu() +{ + MockBridge bridge; + auto decoSettings = std::make_shared(&bridge); + MockDecoration mockDecoration(&bridge); + mockDecoration.setSettings(decoSettings); + MockClient *client = bridge.lastCreatedClient(); + MockButton button(KDecoration2::DecorationButtonType::ApplicationMenu, &mockDecoration); + button.setGeometry(QRect(0, 0, 10, 10)); + + QCOMPARE(button.isEnabled(), true); + QCOMPARE(button.isCheckable(), true); + QCOMPARE(button.isChecked(), false); + QCOMPARE(button.isVisible(), true); + QCOMPARE(button.acceptedButtons(), Qt::LeftButton); + + // clicking the button should trigger a request for application menu + QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked); + QVERIFY(clickedSpy.isValid()); + QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed); + QVERIFY(pressedSpy.isValid()); + QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released); + QVERIFY(releasedSpy.isValid()); + QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged); + QVERIFY(pressedChangedSpy.isValid()); + QSignalSpy applicationMenuRequestedSpy(client, &MockClient::applicationMenuRequested); + QVERIFY(applicationMenuRequestedSpy.isValid()); + + QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + pressEvent.setAccepted(false); + button.event(&pressEvent); + QCOMPARE(pressEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), true); + QCOMPARE(clickedSpy.count(), 0); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 0); + QCOMPARE(applicationMenuRequestedSpy.count(), 0); + QCOMPARE(pressedChangedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.first().first().toBool(), true); + + QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + releaseEvent.setAccepted(false); + button.event(&releaseEvent); + QCOMPARE(releaseEvent.isAccepted(), true); + QCOMPARE(button.isPressed(), false); + QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.first().first().value(), Qt::LeftButton); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 1); + QVERIFY(applicationMenuRequestedSpy.wait()); + QCOMPARE(applicationMenuRequestedSpy.count(), 1); + QCOMPARE(pressedChangedSpy.count(), 2); + QCOMPARE(pressedChangedSpy.last().first().toBool(), false); +} + +void DecorationButtonTest::testContains_data() +{ + QTest::addColumn("pos"); + QTest::addColumn("contains"); + + // Button geometry: QRectF(0, 0, 10, 10). + QTest::newRow("on left edge") << QPointF(0, 5) << true; + QTest::newRow("on top edge") << QPointF(5, 0) << true; + QTest::newRow("on right edge") << QPointF(9, 5) << true; + QTest::newRow("on bottom edge") << QPointF(5, 9) << true; + QTest::newRow("inside") << QPointF(5, 5) << true; + QTest::newRow("outside 1") << QPointF(-1, 5) << false; + QTest::newRow("outside 2") << QPointF(5, -1) << false; + QTest::newRow("outside 3") << QPointF(10, 5) << false; + QTest::newRow("outside 4") << QPointF(5, 10) << false; +} + +void DecorationButtonTest::testContains() +{ + MockBridge bridge; + MockDecoration mockDecoration(&bridge); + + MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration); + button.setGeometry(QRectF(0, 0, 10, 10)); + button.setEnabled(true); + button.setVisible(true); + + QFETCH(QPointF, pos); + QTEST(button.contains(pos), "contains"); +} + +QTEST_MAIN(DecorationButtonTest) +#include "decorationbuttontest.moc" diff --git a/autotests/decorationtest.cpp b/autotests/decorationtest.cpp new file mode 100644 index 0000000..09a87c8 --- /dev/null +++ b/autotests/decorationtest.cpp @@ -0,0 +1,151 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "../src/decorationsettings.h" +#include "mockbridge.h" +#include "mockclient.h" +#include "mockdecoration.h" +#include "mocksettings.h" +#include +#include +#include + +class DecorationTest : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void testCreate(); + void testOpaque(); + void testSection_data(); + void testSection(); +}; + +#ifdef _MSC_VER +QMap makeMap(const QString &key, const QVariant &value); +#endif +void DecorationTest::testCreate() +{ + // just test that creating the Decoration doesn't crash + MockBridge bridge; + const QString bridgeKey = QStringLiteral("bridge"); + MockDecoration deco1(nullptr, + QVariantList({ +#ifdef _MSC_VER + makeMap(bridgeKey, QVariant::fromValue(5)), +#else + QVariantMap({{bridgeKey, QVariant::fromValue(5)}}), +#endif + QVariant::fromValue(bridgeKey), + QVariantMap(), +#ifdef _MSC_VER + makeMap(bridgeKey, QVariant::fromValue(&bridge)), +#else + QVariantMap({{bridgeKey, QVariant::fromValue(&bridge)}}) +#endif + })); + QVERIFY(deco1.client()); +} + +void DecorationTest::testOpaque() +{ + MockBridge bridge; + MockDecoration deco(&bridge); + QSignalSpy opaqueChangedSpy(&deco, &KDecoration2::Decoration::opaqueChanged); + QVERIFY(opaqueChangedSpy.isValid()); + QCOMPARE(deco.isOpaque(), false); + deco.setOpaque(false); + QVERIFY(opaqueChangedSpy.isEmpty()); + deco.setOpaque(true); + QCOMPARE(opaqueChangedSpy.count(), 1); + QCOMPARE(opaqueChangedSpy.first().first().toBool(), true); + QCOMPARE(deco.isOpaque(), true); + deco.setOpaque(true); + QCOMPARE(opaqueChangedSpy.count(), 1); + deco.setOpaque(false); + QCOMPARE(opaqueChangedSpy.count(), 2); + QCOMPARE(opaqueChangedSpy.first().first().toBool(), true); + QCOMPARE(opaqueChangedSpy.last().first().toBool(), false); + QCOMPARE(deco.isOpaque(), false); +} + +Q_DECLARE_METATYPE(QMargins) +Q_DECLARE_METATYPE(Qt::WindowFrameSection) + +void DecorationTest::testSection_data() +{ + QTest::addColumn("titleBar"); + QTest::addColumn("margins"); + QTest::addColumn("pos"); + QTest::addColumn("expected"); + + QRect r(1, 1, 98, 8); + QMargins m(1, 10, 1, 1); + QTest::newRow("topLeft") << r << m << QPoint(0, 0) << Qt::TopLeftSection; + QTest::newRow("top@Left") << r << m << QPoint(1, 0) << Qt::TopSection; + QTest::newRow("top@Right") << r << m << QPoint(100, 0) << Qt::TopSection; + QTest::newRow("topRight") << r << m << QPoint(101, 0) << Qt::TopRightSection; + QTest::newRow("right@top") << r << m << QPoint(101, 1) << Qt::RightSection; + QTest::newRow("right@bottom") << r << m << QPoint(101, 109) << Qt::RightSection; + QTest::newRow("bottomRight") << r << m << QPoint(101, 110) << Qt::BottomRightSection; + QTest::newRow("bottom@right") << r << m << QPoint(100, 110) << Qt::BottomSection; + QTest::newRow("bottom@left") << r << m << QPoint(1, 110) << Qt::BottomSection; + QTest::newRow("bottomLeft") << r << m << QPoint(0, 110) << Qt::BottomLeftSection; + QTest::newRow("left@Top") << r << m << QPoint(0, 1) << Qt::LeftSection; + QTest::newRow("left@Bottom") << r << m << QPoint(0, 109) << Qt::LeftSection; + QTest::newRow("title") << r << m << QPoint(1, 1) << Qt::TitleBarArea; +} + +void DecorationTest::testSection() +{ + MockBridge bridge; + auto decoSettings = std::make_shared(&bridge); + MockDecoration deco(&bridge); + deco.setSettings(decoSettings); + + MockSettings *settings = bridge.lastCreatedSettings(); + settings->setLargeSpacing(0); + + MockClient *client = bridge.lastCreatedClient(); + client->setWidth(100); + client->setHeight(100); + QCOMPARE(deco.size(), QSize(100, 100)); + QCOMPARE(deco.borderLeft(), 0); + QCOMPARE(deco.borderTop(), 0); + QCOMPARE(deco.borderRight(), 0); + QCOMPARE(deco.borderBottom(), 0); + QCOMPARE(deco.titleBar(), QRect()); + QCOMPARE(deco.sectionUnderMouse(), Qt::NoSection); + + QFETCH(QRect, titleBar); + QFETCH(QMargins, margins); + deco.setBorders(margins); + QCOMPARE(deco.borderLeft(), margins.left()); + QCOMPARE(deco.borderTop(), margins.top()); + QCOMPARE(deco.borderRight(), margins.right()); + QCOMPARE(deco.borderBottom(), margins.bottom()); + deco.setTitleBar(titleBar); + QCOMPARE(deco.titleBar(), titleBar); + QCOMPARE(deco.size(), QSize(100 + deco.borderLeft() + deco.borderRight(), 100 + deco.borderTop() + deco.borderBottom())); + + QSignalSpy spy(&deco, &KDecoration2::Decoration::sectionUnderMouseChanged); + QVERIFY(spy.isValid()); + QFETCH(QPoint, pos); + QHoverEvent event(QEvent::HoverMove, QPointF(pos), QPointF(pos)); + QCoreApplication::sendEvent(&deco, &event); + QFETCH(Qt::WindowFrameSection, expected); + QCOMPARE(deco.sectionUnderMouse(), expected); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.first().first().value(), expected); + + QHoverEvent event2(QEvent::HoverMove, QPointF(50, 50), QPointF(50, 50)); + QCoreApplication::sendEvent(&deco, &event2); + QCOMPARE(deco.sectionUnderMouse(), Qt::NoSection); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.first().first().value(), expected); + QCOMPARE(spy.last().first().value(), Qt::NoSection); +} + +QTEST_MAIN(DecorationTest) +#include "decorationtest.moc" diff --git a/autotests/mockbridge.cpp b/autotests/mockbridge.cpp new file mode 100644 index 0000000..22a1d61 --- /dev/null +++ b/autotests/mockbridge.cpp @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "mockbridge.h" +#include "mockclient.h" +#include "mocksettings.h" +#include + +std::unique_ptr MockBridge::createClient(KDecoration2::DecoratedClient *client, KDecoration2::Decoration *decoration) +{ + auto ptr = std::make_unique(client, decoration); + m_lastCreatedClient = ptr.get(); + return ptr; +} + +std::unique_ptr MockBridge::settings(KDecoration2::DecorationSettings *parent) +{ + auto ptr = std::make_unique(parent); + m_lastCreatedSettings = ptr.get(); + return ptr; +} + +#include "moc_mockbridge.cpp" diff --git a/autotests/mockbridge.h b/autotests/mockbridge.h new file mode 100644 index 0000000..245a547 --- /dev/null +++ b/autotests/mockbridge.h @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +#include "../src/private/decorationbridge.h" +#include + +class MockClient; +class MockSettings; + +class MockBridge : public KDecoration2::DecorationBridge +{ + Q_OBJECT +public: + std::unique_ptr createClient(KDecoration2::DecoratedClient *client, KDecoration2::Decoration *decoration) override; + std::unique_ptr settings(KDecoration2::DecorationSettings *parent) override; + + MockClient *lastCreatedClient() const + { + return m_lastCreatedClient; + } + MockSettings *lastCreatedSettings() const + { + return m_lastCreatedSettings; + } + +private: + MockClient *m_lastCreatedClient = nullptr; + MockSettings *m_lastCreatedSettings = nullptr; +}; diff --git a/autotests/mockbutton.cpp b/autotests/mockbutton.cpp new file mode 100644 index 0000000..8e93435 --- /dev/null +++ b/autotests/mockbutton.cpp @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "mockbutton.h" + +MockButton::MockButton(KDecoration2::DecorationButtonType type, KDecoration2::Decoration *decoration, QObject *parent) + : DecorationButton(type, decoration, parent) +{ +} + +void MockButton::paint(QPainter *painter, const QRect &repaintRegion) +{ + Q_UNUSED(painter) + Q_UNUSED(repaintRegion) +} + +#include "moc_mockbutton.cpp" diff --git a/autotests/mockbutton.h b/autotests/mockbutton.h new file mode 100644 index 0000000..7f1e660 --- /dev/null +++ b/autotests/mockbutton.h @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +#include "../src/decorationbutton.h" + +class MockButton : public KDecoration2::DecorationButton +{ + Q_OBJECT +public: + MockButton(KDecoration2::DecorationButtonType type, KDecoration2::Decoration *decoration, QObject *parent = nullptr); + void paint(QPainter *painter, const QRect &repaintRegion) override; +}; diff --git a/autotests/mockclient.cpp b/autotests/mockclient.cpp new file mode 100644 index 0000000..89fbbce --- /dev/null +++ b/autotests/mockclient.cpp @@ -0,0 +1,292 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "mockclient.h" +#include + +#include + +MockClient::MockClient(KDecoration2::DecoratedClient *client, KDecoration2::Decoration *decoration) + : QObject() + , ApplicationMenuEnabledDecoratedClientPrivate(client, decoration) +{ +} + +Qt::Edges MockClient::adjacentScreenEdges() const +{ + return Qt::Edges(); +} + +QString MockClient::caption() const +{ + return QString(); +} + +WId MockClient::decorationId() const +{ + return 0; +} + +int MockClient::height() const +{ + return m_height; +} + +QIcon MockClient::icon() const +{ + return QIcon(); +} + +bool MockClient::isActive() const +{ + return false; +} + +bool MockClient::isCloseable() const +{ + return m_closeable; +} + +bool MockClient::isKeepAbove() const +{ + return m_keepAbove; +} + +bool MockClient::isKeepBelow() const +{ + return m_keepBelow; +} + +bool MockClient::isMaximizeable() const +{ + return m_maximizable; +} + +bool MockClient::isMaximized() const +{ + return isMaximizedHorizontally() && isMaximizedVertically(); +} + +bool MockClient::isMaximizedHorizontally() const +{ + return m_maximizedHorizontally; +} + +bool MockClient::isMaximizedVertically() const +{ + return m_maximizedVertically; +} + +bool MockClient::isMinimizeable() const +{ + return m_minimizable; +} + +bool MockClient::isModal() const +{ + return false; +} + +bool MockClient::isMoveable() const +{ + return false; +} + +bool MockClient::isOnAllDesktops() const +{ + return m_onAllDesktops; +} + +bool MockClient::isResizeable() const +{ + return false; +} + +bool MockClient::isShadeable() const +{ + return m_shadeable; +} + +bool MockClient::isShaded() const +{ + return m_shaded; +} + +QPalette MockClient::palette() const +{ + return QPalette(); +} + +bool MockClient::hasApplicationMenu() const +{ + return true; +} + +bool MockClient::isApplicationMenuActive() const +{ + return false; +} + +bool MockClient::providesContextHelp() const +{ + return m_contextHelp; +} + +void MockClient::requestClose() +{ + Q_EMIT closeRequested(); +} + +void MockClient::requestContextHelp() +{ + Q_EMIT quickHelpRequested(); +} + +void MockClient::requestToggleMaximization(Qt::MouseButtons buttons) +{ + bool maximizedHorizontally = m_maximizedHorizontally; + bool maximizedVertically = m_maximizedVertically; + if (buttons.testFlag(Qt::LeftButton)) { + maximizedHorizontally = !m_maximizedHorizontally; + maximizedVertically = !m_maximizedVertically; + } + if (buttons.testFlag(Qt::MiddleButton)) { + maximizedHorizontally = !m_maximizedHorizontally; + } + if (buttons.testFlag(Qt::RightButton)) { + maximizedVertically = !m_maximizedVertically; + } + const bool wasMaximized = isMaximized(); + if (m_maximizedHorizontally != maximizedHorizontally) { + m_maximizedHorizontally = maximizedHorizontally; + Q_EMIT client()->maximizedHorizontallyChanged(m_maximizedHorizontally); + } + if (m_maximizedVertically != maximizedVertically) { + m_maximizedVertically = maximizedVertically; + Q_EMIT client()->maximizedVerticallyChanged(m_maximizedVertically); + } + if (wasMaximized != isMaximized()) { + Q_EMIT client()->maximizedChanged(isMaximized()); + } +} + +void MockClient::requestMinimize() +{ + Q_EMIT minimizeRequested(); +} + +void MockClient::requestShowWindowMenu(const QRect &rect) +{ + Q_EMIT menuRequested(); +} + +void MockClient::requestShowApplicationMenu(const QRect &rect, int actionId) +{ + Q_UNUSED(rect); + Q_UNUSED(actionId); + Q_EMIT applicationMenuRequested(); // FIXME TODO pass geometry +} + +void MockClient::requestToggleKeepAbove() +{ + m_keepAbove = !m_keepAbove; + Q_EMIT client()->keepAboveChanged(m_keepAbove); +} + +void MockClient::requestToggleKeepBelow() +{ + m_keepBelow = !m_keepBelow; + Q_EMIT client()->keepBelowChanged(m_keepBelow); +} + +void MockClient::requestToggleOnAllDesktops() +{ + m_onAllDesktops = !m_onAllDesktops; + Q_EMIT client()->onAllDesktopsChanged(m_onAllDesktops); +} + +void MockClient::requestToggleShade() +{ + m_shaded = !m_shaded; + Q_EMIT client()->shadedChanged(m_shaded); +} + +void MockClient::requestShowToolTip(const QString &text) +{ + Q_UNUSED(text); +} + +void MockClient::requestHideToolTip() +{ +} + +QSize MockClient::size() const +{ + return QSize(m_width, m_height); +} + +int MockClient::width() const +{ + return m_width; +} + +QString MockClient::windowClass() const +{ + return QString(); +} + +WId MockClient::windowId() const +{ + return 0; +} + +void MockClient::setCloseable(bool set) +{ + m_closeable = set; + Q_EMIT client()->closeableChanged(set); +} + +void MockClient::setMinimizable(bool set) +{ + m_minimizable = set; + Q_EMIT client()->minimizeableChanged(set); +} + +void MockClient::setProvidesContextHelp(bool set) +{ + m_contextHelp = set; + Q_EMIT client()->providesContextHelpChanged(set); +} + +void MockClient::setShadeable(bool set) +{ + m_shadeable = set; + Q_EMIT client()->shadeableChanged(set); +} + +void MockClient::setMaximizable(bool set) +{ + m_maximizable = set; + Q_EMIT client()->maximizeableChanged(set); +} + +void MockClient::setWidth(int w) +{ + m_width = w; + Q_EMIT client()->widthChanged(w); +} + +void MockClient::setHeight(int h) +{ + m_height = h; + Q_EMIT client()->heightChanged(h); +} + +void MockClient::showApplicationMenu(int actionId) +{ + Q_UNUSED(actionId) +} + +#include "moc_mockclient.cpp" diff --git a/autotests/mockclient.h b/autotests/mockclient.h new file mode 100644 index 0000000..1a5c982 --- /dev/null +++ b/autotests/mockclient.h @@ -0,0 +1,91 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +#include "../src/private/decoratedclientprivate.h" + +#include + +class MockClient : public QObject, public KDecoration2::ApplicationMenuEnabledDecoratedClientPrivate +{ + Q_OBJECT +public: + explicit MockClient(KDecoration2::DecoratedClient *client, KDecoration2::Decoration *decoration); + + Qt::Edges adjacentScreenEdges() const override; + QString caption() const override; + WId decorationId() const override; + int height() const override; + QIcon icon() const override; + bool isActive() const override; + bool isCloseable() const override; + bool isKeepAbove() const override; + bool isKeepBelow() const override; + bool isMaximizeable() const override; + bool isMaximized() const override; + bool isMaximizedHorizontally() const override; + bool isMaximizedVertically() const override; + bool isMinimizeable() const override; + bool isModal() const override; + bool isMoveable() const override; + bool isOnAllDesktops() const override; + bool isResizeable() const override; + bool isShadeable() const override; + bool isShaded() const override; + QPalette palette() const override; + bool hasApplicationMenu() const override; + bool isApplicationMenuActive() const override; + bool providesContextHelp() const override; + void requestClose() override; + void requestContextHelp() override; + void requestToggleMaximization(Qt::MouseButtons buttons) override; + void requestMinimize() override; + void requestShowWindowMenu(const QRect &rect) override; + void requestShowApplicationMenu(const QRect &rect, int actionId) override; + void requestToggleKeepAbove() override; + void requestToggleKeepBelow() override; + void requestToggleOnAllDesktops() override; + void requestToggleShade() override; + void requestShowToolTip(const QString &text) override; + void requestHideToolTip() override; + QSize size() const override; + int width() const override; + WId windowId() const override; + QString windowClass() const override; + + void showApplicationMenu(int actionId) override; + + void setCloseable(bool set); + void setMinimizable(bool set); + void setProvidesContextHelp(bool set); + void setShadeable(bool set); + void setMaximizable(bool set); + + void setWidth(int w); + void setHeight(int h); + +Q_SIGNALS: + void closeRequested(); + void minimizeRequested(); + void quickHelpRequested(); + void menuRequested(); + void applicationMenuRequested(); + +private: + bool m_closeable = false; + bool m_minimizable = false; + bool m_contextHelp = false; + bool m_keepAbove = false; + bool m_keepBelow = false; + bool m_shadeable = false; + bool m_shaded = false; + bool m_maximizable = false; + bool m_maximizedVertically = false; + bool m_maximizedHorizontally = false; + bool m_onAllDesktops = false; + int m_width = 0; + int m_height = 0; +}; diff --git a/autotests/mockdecoration.cpp b/autotests/mockdecoration.cpp new file mode 100644 index 0000000..fe65929 --- /dev/null +++ b/autotests/mockdecoration.cpp @@ -0,0 +1,60 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "mockdecoration.h" +#include "mockbridge.h" + +#include +#include +#include + +MockDecoration::MockDecoration(QObject *parent, const QVariantList &args) + : Decoration(parent, args) +{ +} + +#ifdef _MSC_VER +QMap makeMap(const QString &key, const QVariant &value) +{ + QMap ret; + ret.insert(key, value); + return ret; +} +MockDecoration::MockDecoration(MockBridge *bridge) + : MockDecoration(nullptr, QVariantList({makeMap(QStringLiteral("bridge"), QVariant::fromValue(bridge))})) +#else +MockDecoration::MockDecoration(MockBridge *bridge) + : MockDecoration(nullptr, QVariantList({QVariantMap({{QStringLiteral("bridge"), QVariant::fromValue(bridge)}})})) +#endif +{ +} + +bool MockDecoration::init() +{ + return true; +} + +void MockDecoration::paint(QPainter *painter, const QRect &repaintRegion) +{ + Q_UNUSED(painter) + Q_UNUSED(repaintRegion) +} + +void MockDecoration::setOpaque(bool set) +{ + Decoration::setOpaque(set); +} + +void MockDecoration::setBorders(const QMargins &m) +{ + Decoration::setBorders(m); +} + +void MockDecoration::setTitleBar(const QRect &rect) +{ + Decoration::setTitleBar(rect); +} + +#include "moc_mockdecoration.cpp" diff --git a/autotests/mockdecoration.h b/autotests/mockdecoration.h new file mode 100644 index 0000000..23dcbde --- /dev/null +++ b/autotests/mockdecoration.h @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +#include "../src/decoration.h" + +class MockBridge; + +class MockDecoration : public KDecoration2::Decoration +{ + Q_OBJECT +public: + explicit MockDecoration(QObject *parent, const QVariantList &args); + explicit MockDecoration(MockBridge *bridge); + bool init() override; + void paint(QPainter *painter, const QRect &repaintRegion) override; + void setOpaque(bool set); + using Decoration::setBorders; + void setBorders(const QMargins &m); + using Decoration::setTitleBar; + void setTitleBar(const QRect &rect); +}; diff --git a/autotests/mocksettings.cpp b/autotests/mocksettings.cpp new file mode 100644 index 0000000..54e87f0 --- /dev/null +++ b/autotests/mocksettings.cpp @@ -0,0 +1,60 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "mocksettings.h" +#include "../src/decorationsettings.h" + +MockSettings::MockSettings(KDecoration2::DecorationSettings *parent) + : DecorationSettingsPrivate(parent) +{ +} + +KDecoration2::BorderSize MockSettings::borderSize() const +{ + return KDecoration2::BorderSize::Normal; +} + +QList MockSettings::decorationButtonsLeft() const +{ + return QList(); +} + +QList MockSettings::decorationButtonsRight() const +{ + return QList(); +} + +bool MockSettings::isAlphaChannelSupported() const +{ + return true; +} + +bool MockSettings::isCloseOnDoubleClickOnMenu() const +{ + return m_closeDoubleClickOnMenu; +} + +bool MockSettings::isOnAllDesktopsAvailable() const +{ + return m_onAllDesktopsAvailable; +} + +void MockSettings::setOnAllDesktopsAvailabe(bool set) +{ + if (m_onAllDesktopsAvailable == set) { + return; + } + m_onAllDesktopsAvailable = set; + Q_EMIT decorationSettings()->onAllDesktopsAvailableChanged(m_onAllDesktopsAvailable); +} + +void MockSettings::setCloseOnDoubleClickOnMenu(bool set) +{ + if (m_closeDoubleClickOnMenu == set) { + return; + } + m_closeDoubleClickOnMenu = set; + Q_EMIT decorationSettings()->closeOnDoubleClickOnMenuChanged(m_closeDoubleClickOnMenu); +} diff --git a/autotests/mocksettings.h b/autotests/mocksettings.h new file mode 100644 index 0000000..bf5d084 --- /dev/null +++ b/autotests/mocksettings.h @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +#include "../src/private/decorationsettingsprivate.h" + +class MockSettings : public KDecoration2::DecorationSettingsPrivate +{ +public: + explicit MockSettings(KDecoration2::DecorationSettings *parent); + + KDecoration2::BorderSize borderSize() const override; + QList decorationButtonsLeft() const override; + QList decorationButtonsRight() const override; + bool isAlphaChannelSupported() const override; + bool isCloseOnDoubleClickOnMenu() const override; + bool isOnAllDesktopsAvailable() const override; + + void setOnAllDesktopsAvailabe(bool set); + void setCloseOnDoubleClickOnMenu(bool set); + +private: + bool m_onAllDesktopsAvailable = false; + bool m_closeDoubleClickOnMenu = false; +}; diff --git a/autotests/shadowtest.cpp b/autotests/shadowtest.cpp new file mode 100644 index 0000000..c0aab64 --- /dev/null +++ b/autotests/shadowtest.cpp @@ -0,0 +1,129 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "../src/decorationshadow.h" +#include +#include + +Q_DECLARE_METATYPE(QMargins) + +class DecorationShadowTest : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void testPadding_data(); + void testPadding(); + void testSizes_data(); + void testSizes(); +}; + +void DecorationShadowTest::testPadding_data() +{ + QTest::addColumn("propertyName"); + QTest::addColumn("padding"); + + QTest::newRow("top") << QByteArrayLiteral("paddingTop") << QMargins(0, 10, 0, 0); + QTest::newRow("right") << QByteArrayLiteral("paddingRight") << QMargins(0, 0, 10, 0); + QTest::newRow("bottom") << QByteArrayLiteral("paddingBottom") << QMargins(0, 0, 0, 10); + QTest::newRow("left") << QByteArrayLiteral("paddingLeft") << QMargins(10, 0, 0, 0); +} + +void DecorationShadowTest::testPadding() +{ + using namespace KDecoration2; + DecorationShadow shadow; + + QFETCH(QByteArray, propertyName); + + const int propertyIndex = shadow.metaObject()->indexOfProperty(propertyName.constData()); + QVERIFY(propertyIndex != -1); + QMetaProperty metaProperty = shadow.metaObject()->property(propertyIndex); + QCOMPARE(metaProperty.isReadable(), true); + QCOMPARE(metaProperty.hasNotifySignal(), true); + QCOMPARE(metaProperty.type(), QVariant::Int); + QSignalSpy changedSpy(&shadow, &KDecoration2::DecorationShadow::paddingChanged); + QVERIFY(changedSpy.isValid()); + + QCOMPARE(shadow.property(propertyName.constData()).isValid(), true); + QCOMPARE(shadow.property(propertyName.constData()).toInt(), 0); + QFETCH(QMargins, padding); + shadow.setPadding(padding); + QCOMPARE(shadow.padding(), padding); + QCOMPARE(shadow.property(propertyName.constData()).toInt(), 10); + QCOMPARE(changedSpy.count(), 1); + + // trying to set to same value shouldn't emit the signal + shadow.setPadding(padding); + QCOMPARE(shadow.property(propertyName.constData()).toInt(), 10); + QCOMPARE(changedSpy.count(), 1); + + // changing to different value should emit signal + padding += 1; + shadow.setPadding(padding); + QCOMPARE(shadow.padding(), padding); + QCOMPARE(shadow.property(propertyName.constData()).toInt(), 11); + QCOMPARE(changedSpy.count(), 2); +} + +void DecorationShadowTest::testSizes_data() +{ + QTest::addColumn("propertyName"); + QTest::addColumn("innerShadowRect"); + QTest::addColumn("shadowRect"); + QTest::addColumn("shadowSize"); + + QTest::newRow("topLeft") << QByteArrayLiteral("topLeftGeometry") << QRect(1, 2, 5, 5) << QRect(0, 0, 1, 2) << QSize(6, 7); + QTest::newRow("top") << QByteArrayLiteral("topGeometry") << QRect(1, 2, 1, 5) << QRect(1, 0, 1, 2) << QSize(3, 7); + QTest::newRow("topRight") << QByteArrayLiteral("topRightGeometry") << QRect(0, 2, 2, 1) << QRect(2, 0, 1, 2) << QSize(3, 3); + QTest::newRow("right") << QByteArrayLiteral("rightGeometry") << QRect(0, 0, 1, 2) << QRect(1, 0, 1, 2) << QSize(2, 4); + QTest::newRow("bottomRight") << QByteArrayLiteral("bottomRightGeometry") << QRect(0, 0, 1, 4) << QRect(1, 4, 1, 2) << QSize(2, 6); + QTest::newRow("bottom") << QByteArrayLiteral("bottomGeometry") << QRect(0, 0, 1, 1) << QRect(0, 1, 1, 2) << QSize(1, 3); + QTest::newRow("bottomLeft") << QByteArrayLiteral("bottomLeftGeometry") << QRect(1, 0, 1, 1) << QRect(0, 1, 1, 2) << QSize(2, 3); + QTest::newRow("left") << QByteArrayLiteral("leftGeometry") << QRect(1, 0, 1, 2) << QRect(0, 0, 1, 2) << QSize(2, 2); +} + +void DecorationShadowTest::testSizes() +{ + using namespace KDecoration2; + DecorationShadow shadow; + + QFETCH(QByteArray, propertyName); + + const int propertyIndex = shadow.metaObject()->indexOfProperty(propertyName.constData()); + QVERIFY(propertyIndex != -1); + QMetaProperty metaProperty = shadow.metaObject()->property(propertyIndex); + QCOMPARE(metaProperty.isReadable(), true); + QCOMPARE(metaProperty.hasNotifySignal(), true); + QCOMPARE(metaProperty.type(), QVariant::Rect); + QSignalSpy changedSpy(&shadow, &KDecoration2::DecorationShadow::innerShadowRectChanged); + QVERIFY(changedSpy.isValid()); + + QCOMPARE(shadow.innerShadowRect(), QRect()); + QCOMPARE(shadow.property(propertyName.constData()).isValid(), true); + QCOMPARE(shadow.property(propertyName.constData()).toRect(), QRect()); + QFETCH(QRect, innerShadowRect); + QFETCH(QRect, shadowRect); + QFETCH(QSize, shadowSize); + shadow.setInnerShadowRect(innerShadowRect); + QCOMPARE(shadow.innerShadowRect(), innerShadowRect); + // property should still be invalid as the image is not yet set + QCOMPARE(shadow.property(propertyName.constData()).toRect(), QRect()); + shadow.setShadow(QImage(shadowSize, QImage::Format_ARGB32)); + QCOMPARE(shadow.property(propertyName.constData()).toRect(), shadowRect); + QCOMPARE(changedSpy.count(), 1); + + // trying to set to same value shouldn't emit the signal + shadow.setInnerShadowRect(innerShadowRect); + QCOMPARE(shadow.property(propertyName.constData()).toRect(), shadowRect); + QCOMPARE(changedSpy.count(), 1); + + // changing to different value should emit signal + shadow.setInnerShadowRect(innerShadowRect.adjusted(1, 1, 1, 1)); + QCOMPARE(changedSpy.count(), 2); + QCOMPARE(shadow.innerShadowRect(), innerShadowRect.adjusted(1, 1, 1, 1)); +} + +QTEST_MAIN(DecorationShadowTest) +#include "shadowtest.moc" diff --git a/metainfo.yaml b/metainfo.yaml new file mode 100644 index 0000000..c3adf2c --- /dev/null +++ b/metainfo.yaml @@ -0,0 +1,18 @@ +maintainer: graesslin +fancyname: KDecoration2 +description: Plugin based library to create window decorations. +irc: kwin +mailinglist: kwin +type: integration +platforms: + - name: Linux + - name: FreeBSD +portingAid: false +deprecated: false +release: false +libraries: + - cmake: KDecoration2::KDecoration +cmakename: KDecoration2 +group: plasma + +public_lib: true diff --git a/po/ar/kdecoration.po b/po/ar/kdecoration.po new file mode 100644 index 0000000..d1f9cfd --- /dev/null +++ b/po/ar/kdecoration.po @@ -0,0 +1,93 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# Zayed Al-Saidi , 2023. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2023-03-16 12:41+0400\n" +"Last-Translator: Zayed Al-Saidi \n" +"Language-Team: ar\n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "إجراءات أكثر لهذه النافذة" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "قائمة التّطبيق" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "على سطح مكتب واحد" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "على كلّ أسطح المكتب" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "صغّر" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "استعد" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "كبّر" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "أغلق" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "مساعدة السياقية" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "ألغ التظليل" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "ظلل" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "لا تبقها أسفل النوافذ الأخرى" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "أبقها أسفل النوافذ الأخرى" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "لا تبقها أعلى النوافذ الأخرى" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "أبقها أعلى النوافذ الأخرى" diff --git a/po/ast/kdecoration.po b/po/ast/kdecoration.po new file mode 100644 index 0000000..e0427ab --- /dev/null +++ b/po/ast/kdecoration.po @@ -0,0 +1,93 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# Enol P. , 2023. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2023-05-03 23:37+0200\n" +"Last-Translator: Enol P. \n" +"Language-Team: \n" +"Language: ast\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 23.04.0\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "" diff --git a/po/az/kdecoration.po b/po/az/kdecoration.po new file mode 100644 index 0000000..578deab --- /dev/null +++ b/po/az/kdecoration.po @@ -0,0 +1,102 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# Xəyyam Qocayev , 2020, 2021, 2022. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2022-07-03 13:56+0400\n" +"Last-Translator: Kheyyam \n" +"Language-Team: Azerbaijani \n" +"Language: az\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 22.04.2\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Bu pəncərə üçün daha çox əməllər" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Tətbiq menyusu" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "İş masasında" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Bütün İş Masalarında" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Kiçiltmək" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Bərpa etmək" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Tam açmaq" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Bağlamaq" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Uyğun kömək" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Kölgəsiz" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Kölgə" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Digər pəncərələrin altında tutmamaq" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Digər pəncərələrin altında tutmaq" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Digər pəncərələrin üzərində tutmamaq" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Digər pəncərələrin üzərində tutmaq" + +#~ msgid "Menu" +#~ msgstr "Menyu" + +#~ msgid "Keep below" +#~ msgstr "Aşağıda tutmaq" + +#~ msgid "Keep above" +#~ msgstr "Yuxarıda tutmaq" diff --git a/po/bg/kdecoration.po b/po/bg/kdecoration.po new file mode 100644 index 0000000..894391c --- /dev/null +++ b/po/bg/kdecoration.po @@ -0,0 +1,93 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# Mincho Kondarev , 2022. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2022-05-20 19:35+0200\n" +"Last-Translator: Mincho Kondarev \n" +"Language-Team: Bulgarian \n" +"Language: bg\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 22.04.0\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Допълнителни действия за този прозорец" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Меню на приложение" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "На един работен плот" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "На всички работни плотове" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Минимизиране" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Възстановяване" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Максимизиране" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Затваряне" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Контекстна помощ" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Разгъване" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Сгъване" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Без задържане под другите прозорци" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Задържане под другите прозорците" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Без задържане над другите прозорци" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Задържане над другите прозорци" diff --git a/po/ca/kdecoration.po b/po/ca/kdecoration.po new file mode 100644 index 0000000..b77859d --- /dev/null +++ b/po/ca/kdecoration.po @@ -0,0 +1,98 @@ +# Translation of kdecoration.po to Catalan +# Copyright (C) 2018-2021 This_file_is_part_of_KDE +# This file is distributed under the license LGPL version 2.1 or +# version 3 or later versions approved by the membership of KDE e.V. +# +# Josep M. Ferrer , 2018. +# Empar Montoro Martín , 2019. +# Antoni Bella Pérez , 2021. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-05 16:55+0200\n" +"Last-Translator: Antoni Bella Pérez \n" +"Language-Team: Catalan \n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 20.12.3\n" +"X-Accelerator-Marker: &\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Més accions per a aquesta finestra" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Menú d'aplicacions" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "A un escriptori" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "A tots els escriptoris" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimitza" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Restaura" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximitza" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Tanca" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Ajuda contextual" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Desplega" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Plega" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "No mantinguis per sota de les altres finestres" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Mantén per sota de les altres finestres" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "No mantinguis al damunt de les altres finestres" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Mantén al damunt de les altres finestres" diff --git a/po/ca@valencia/kdecoration.po b/po/ca@valencia/kdecoration.po new file mode 100644 index 0000000..71a013a --- /dev/null +++ b/po/ca@valencia/kdecoration.po @@ -0,0 +1,98 @@ +# Translation of kdecoration.po to Catalan (Valencian) +# Copyright (C) 2018-2021 This_file_is_part_of_KDE +# This file is distributed under the license LGPL version 2.1 or +# version 3 or later versions approved by the membership of KDE e.V. +# +# Josep M. Ferrer , 2018. +# Empar Montoro Martín , 2019. +# Antoni Bella Pérez , 2021. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-05 16:55+0200\n" +"Last-Translator: Antoni Bella Pérez \n" +"Language-Team: Catalan \n" +"Language: ca@valencia\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 20.12.3\n" +"X-Accelerator-Marker: &\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Més accions per a esta finestra" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Menú d'aplicacions" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "A un escriptori" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "A tots els escriptoris" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimitza" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Restaura" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximitza" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Tanca" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Ajuda contextual" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Desplega" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Plega" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "No mantinges per davall de les altres finestres" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Mantín per davall de les altres finestres" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "No mantinges al damunt de les altres finestres" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Mantín al damunt de les altres finestres" diff --git a/po/cs/kdecoration.po b/po/cs/kdecoration.po new file mode 100644 index 0000000..50e1655 --- /dev/null +++ b/po/cs/kdecoration.po @@ -0,0 +1,93 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# Vit Pelcak , 2018, 2020, 2021. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-13 13:38+0200\n" +"Last-Translator: Vit Pelcak \n" +"Language-Team: Czech \n" +"Language: cs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: Lokalize 21.04.0\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Více činností pro toto okno" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Nabídka aplikací" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Na pracovní ploÅ¡e" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Na vÅ¡ech plochách" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimalizovat" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Obnovit" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximalizovat" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Zavřít" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Kontextová nápověda" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Rozbalit" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Sbalit" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Neponechat pod ostatními okny" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Ponechat pod ostatními okny" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Neponechat nad jinými okny" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Podržet nad jinými okny" diff --git a/po/da/kdecoration.po b/po/da/kdecoration.po new file mode 100644 index 0000000..4aa090e --- /dev/null +++ b/po/da/kdecoration.po @@ -0,0 +1,104 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Martin Schlander , 2018, 2019. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2019-05-07 13:23+0100\n" +"Last-Translator: Martin Schlander \n" +"Language-Team: Danish \n" +"Language: da\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 2.0\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Programmenu" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "PÃ¥ et skrivebord" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "PÃ¥ alle skriveborde" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimér" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Genskab" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maksimér" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Luk" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Sammenhængsafhængig hjælp" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Skyg ikke" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Skyg" + +#: decorationbutton.cpp:329 +#, fuzzy, kde-format +#| msgid "Don't keep below" +msgid "Don't keep below other windows" +msgstr "Hold ikke under" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "" + +#: decorationbutton.cpp:334 +#, fuzzy, kde-format +#| msgid "Don't keep above" +msgid "Don't keep above other windows" +msgstr "Hold ikke over" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "" + +#~ msgid "Menu" +#~ msgstr "Menu" + +#~ msgid "Keep below" +#~ msgstr "Hold under" + +#~ msgid "Keep above" +#~ msgstr "Hold over" diff --git a/po/de/kdecoration.po b/po/de/kdecoration.po new file mode 100644 index 0000000..867838e --- /dev/null +++ b/po/de/kdecoration.po @@ -0,0 +1,102 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Frederik Schwarzer , 2018. +# Burkhard Lück , 2018, 2021. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-05 05:59+0200\n" +"Last-Translator: Burkhard Lück \n" +"Language-Team: German \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Weitere Aktionen für dieses Fenster" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Anwendungsmenü" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Auf einer Arbeitsfläche" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Auf allen Arbeitsflächen" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimieren" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Wiederherstellen" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximieren" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Schließen" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Kontexthilfe" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Einrollen rückgängig" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Einrollen" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Nicht hinter anderen Fenstern halten" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Fenster im Hintergrund halten" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Nicht vor anderen Fenstern halten" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Fenster im Vordergrund halten" + +#~ msgid "Menu" +#~ msgstr "Menü" + +#~ msgid "Keep below" +#~ msgstr "Im Hintergrund halten" + +#~ msgid "Keep above" +#~ msgstr "Im Vordergrund halten" diff --git a/po/el/kdecoration.po b/po/el/kdecoration.po new file mode 100644 index 0000000..84ea067 --- /dev/null +++ b/po/el/kdecoration.po @@ -0,0 +1,102 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# Stelios , 2020, 2021. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-06-14 16:27+0300\n" +"Last-Translator: Stelios \n" +"Language-Team: Greek \n" +"Language: el\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 20.04.2\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Περισσότερες ενέργειες για αυτό το παράθυρο" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Μενού εφαρμογής" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Σε μία επιφάνεια εργασίας" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Σε όλες τις επιφάνειες εργασίας" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Ελαχιστοποίηση" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Επαναφορά" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Μεγιστοποίηση" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Κλείσιμο" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Βοήθεια στο κείμενο" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Αναίρεση σκίασης" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Σκίαση" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Να μη μείνει κάτω από άλλα παράθυρα" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Να μείνει κάτω από άλλα παράθυρα" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Να μη μείνει πάνω από άλλα παράθυρα" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Να μείνει πάνω από άλλα παράθυρα" + +#~ msgid "Menu" +#~ msgstr "Μενού" + +#~ msgid "Keep below" +#~ msgstr "Να μείνει από κάτω" + +#~ msgid "Keep above" +#~ msgstr "Να μείνει από πάνω" diff --git a/po/en_GB/kdecoration.po b/po/en_GB/kdecoration.po new file mode 100644 index 0000000..3faba43 --- /dev/null +++ b/po/en_GB/kdecoration.po @@ -0,0 +1,102 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Steve Allewell , 2018, 2021. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-06-12 14:20+0100\n" +"Last-Translator: Steve Allewell \n" +"Language-Team: British English \n" +"Language: en_GB\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 21.04.1\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "More actions for this window" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Application menu" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "On one desktop" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "On all desktops" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimise" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Restore" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximise" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Close" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Context help" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Unshade" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Shade" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Do not keep below other windows" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Keep below other windows" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Do not keep above other windows" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Keep above other windows" + +#~ msgid "Menu" +#~ msgstr "Menu" + +#~ msgid "Keep below" +#~ msgstr "Keep below" + +#~ msgid "Keep above" +#~ msgstr "Keep above" diff --git a/po/eo/kdecoration.po b/po/eo/kdecoration.po new file mode 100644 index 0000000..68b3acb --- /dev/null +++ b/po/eo/kdecoration.po @@ -0,0 +1,92 @@ +# translation of kdecoration.pot to Esperanto +# Copyright (C) 2017 Free Software Foundation, Inc. +# Oliver Kellogg , 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2023-04-28 23:02+0100\n" +"Last-Translator: Oliver Kellogg \n" +"Language-Team: Esperanto \n" +"Language: eo\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Pliaj agoj por ĉi tiu fenestro" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Aplikaĵa menuo" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Sur unu labortablo" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Sur ĉiuj labortabloj" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimumigi" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "RestaÅ­ri" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maksimumigi" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Fermi" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Kunteksta helpo" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Malombrigi" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Ombrigi" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Ne teni sub aliaj fenestroj" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Teni sub aliaj fenestroj" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Ne teni super aliaj fenestroj" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Teni super aliaj fenestroj" diff --git a/po/es/kdecoration.po b/po/es/kdecoration.po new file mode 100644 index 0000000..7ea8233 --- /dev/null +++ b/po/es/kdecoration.po @@ -0,0 +1,104 @@ +# Spanish translations for kdecoration.po package. +# Copyright (C) 2018 This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Automatically generated, 2018. +# Eloy Cuadra , 2018, 2021. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-05 12:13+0200\n" +"Last-Translator: Eloy Cuadra \n" +"Language-Team: Spanish \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 21.04.0\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Más acciones para esta ventana" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Menú de la aplicación" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "En un escritorio" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "En todos los escritorios" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimizar" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Restaurar" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximizar" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Cerrar" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Ayuda de contexto" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Desenrollar" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Enrollar" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "No mantener por debajo de otras ventanas" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Mantener por debajo de otras ventanas" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "No mantener por encima de otras ventanas" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Mantener por encima de otras ventanas" + +#~ msgid "Menu" +#~ msgstr "Menú" + +#~ msgid "Keep below" +#~ msgstr "Mantener por debajo" + +#~ msgid "Keep above" +#~ msgstr "Mantener por encima" diff --git a/po/et/kdecoration.po b/po/et/kdecoration.po new file mode 100644 index 0000000..3b2949d --- /dev/null +++ b/po/et/kdecoration.po @@ -0,0 +1,104 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# Marek Laane , 2019. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2019-11-08 21:30+0200\n" +"Last-Translator: Marek Laane \n" +"Language-Team: Estonian \n" +"Language: et\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 19.08.1\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Rakenduste menüü" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Ühel töölaual" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Kõigil töölaudadel" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimeeri" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Taasta" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maksimeeri" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Sulge" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Kontekstiabi" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Keri lahti" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Keri kokku" + +#: decorationbutton.cpp:329 +#, fuzzy, kde-format +#| msgid "Don't keep below" +msgid "Don't keep below other windows" +msgstr "Ära hoia teiste all" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "" + +#: decorationbutton.cpp:334 +#, fuzzy, kde-format +#| msgid "Don't keep above" +msgid "Don't keep above other windows" +msgstr "Ära hoia teiste peal" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "" + +#~ msgid "Menu" +#~ msgstr "Menüü" + +#~ msgid "Keep below" +#~ msgstr "Hoia teiste all" + +#~ msgid "Keep above" +#~ msgstr "Hoia teiste peal" diff --git a/po/eu/kdecoration.po b/po/eu/kdecoration.po new file mode 100644 index 0000000..1ce6b5a --- /dev/null +++ b/po/eu/kdecoration.po @@ -0,0 +1,106 @@ +# Translation for kdecoration.po to Euskara/Basque (eu). +# Copyright (C) 2018, Free Software Foundation, Inc. +# Copyright (C) 2019-2021, This file is copyright: +# This file is distributed under the same license as kdecoration package. +# KDE euskaratzeko proiektuko arduraduna . +# +# Translators: +# Iñigo Salvador Azurmendi , 2018, 2021. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-07-26 19:57+0200\n" +"Last-Translator: Iñigo Salvador Azurmendi \n" +"Language-Team: Basque \n" +"Language: eu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 21.04.3\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Leiho honetarako ekintza gehiago" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Aplikazio-menua" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Mahaigain bakarrean" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Mahaigain guztietan" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimizatu" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Lehengoratu" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximizatu" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Itxi" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Testuinguru-laguntza" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Zabaldu" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Bildu" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Ez eutsi beste leihoen azpian" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Eutsi beste leihoen azpian" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Ez eutsi beste leihoen gainean" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Eutsi beste leiho batzuen gainean" + +#~ msgid "Menu" +#~ msgstr "Menua" + +#~ msgid "Keep below" +#~ msgstr "Egon azpian" + +#~ msgid "Keep above" +#~ msgstr "Egon gainean" diff --git a/po/fi/kdecoration.po b/po/fi/kdecoration.po new file mode 100644 index 0000000..b67ec93 --- /dev/null +++ b/po/fi/kdecoration.po @@ -0,0 +1,102 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# Tommi Nieminen , 2018, 2021. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-07 11:01+0300\n" +"Last-Translator: Tommi Nieminen \n" +"Language-Team: Finnish \n" +"Language: fi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 20.04.2\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Lisää toimintoja tälle ikkunalle" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Sovellusvalikko" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Yhdellä työpöydällä" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Kaikilla työpöydillä" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Pienennä" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Palauta" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Suurenna" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Sulje" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Kontekstiohje" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Avaa rullaus" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Rullaa" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Älä pidä muiden ikkunoiden alla" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Pidä muiden ikkunoiden alla" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Älä pidä muiden ikkunoiden yllä" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Pidä muiden ikkunoiden yllä" + +#~ msgid "Menu" +#~ msgstr "Valikko" + +#~ msgid "Keep below" +#~ msgstr "Pidä alinna" + +#~ msgid "Keep above" +#~ msgstr "Pidä ylinnä" diff --git a/po/fr/kdecoration.po b/po/fr/kdecoration.po new file mode 100644 index 0000000..ac6926d --- /dev/null +++ b/po/fr/kdecoration.po @@ -0,0 +1,103 @@ +# Yoann Laissus , 2018. +# Xavier Besnard , 2021. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-05 13:56+0200\n" +"Last-Translator: Xavier Besnard \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Lokalize 21.04.0\n" +"X-Environment: kde\n" +"X-Accelerator-Marker: &\n" +"X-Text-Markup: kde4\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Plus d'actions pour cette fenêtre" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Menu d'application" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Sur un seul bureau" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Sur tous les bureaux" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimiser" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Restaurer" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximiser" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Fermer" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Aide contextuelle" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Enlever l'ombrage" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Ombre" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Ne pas conserver en dessous des autres fenêtres" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Conserver en dessous des autres fenêtres" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Ne pas conserver en dessus des autres fenêtres" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Conserver en dessus des autres fenêtres" + +#~ msgid "Menu" +#~ msgstr "Menu" + +#~ msgid "Keep below" +#~ msgstr "Conserver au-dessous " + +#~ msgid "Keep above" +#~ msgstr "Conserver au-dessus " diff --git a/po/gl/kdecoration.po b/po/gl/kdecoration.po new file mode 100644 index 0000000..16b5b38 --- /dev/null +++ b/po/gl/kdecoration.po @@ -0,0 +1,102 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# Adrián Chaves (Gallaecio) , 2018, 2019, 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2023-04-28 17:26+0200\n" +"Last-Translator: Adrián Chaves (Gallaecio) \n" +"Language-Team: Galician \n" +"Language: gl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 23.04.0\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Máis accións para esta xanela" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Menú das aplicacións" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Nun escritorio" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "En todos os escritorios" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimizar" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Restaurar" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximizar" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Pechar" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Axuda contextual" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Desenrolar" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Enrolar" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Non manter debaixo doutras xanelas" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Manter debaixo doutras xanelas" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Non manter enriba doutras xanelas" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Manter enriba doutras xanelas" + +#~ msgid "Menu" +#~ msgstr "Menú" + +#~ msgid "Keep below" +#~ msgstr "Manter debaixo" + +#~ msgid "Keep above" +#~ msgstr "Manter enriba" diff --git a/po/he/kdecoration.po b/po/he/kdecoration.po new file mode 100644 index 0000000..f6fc1c6 --- /dev/null +++ b/po/he/kdecoration.po @@ -0,0 +1,94 @@ +# Copyright (C) 2024 This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# SPDX-FileCopyrightText: 2024 Yaron Shahrabani +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2024-03-19 08:16+0200\n" +"Last-Translator: Yaron Shahrabani \n" +"Language-Team: צוות התרגום של KDE ישראל\n" +"Language: he\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && " +"n % 10 == 0) ? 2 : 3));\n" +"X-Generator: Lokalize 23.08.5\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "פעולות נוספות לחלון הזה" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "תפריט היישום" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "בשולחן עבודה אחד" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "בכל שולחנות העבודה" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "מזעור" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "שחזור" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "הגדלה" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "סגירה" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "עזרה לפי הקשר" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "ביטול הצללה" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "הצללה" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "לא להסתיר מאחורי חלונות אחרים" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "להסתיר מאחורי חלונות אחרים" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "לא לקדם מעל חלונות אחרים" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "לקדם מעל חלונות אחרים" diff --git a/po/hi/kdecoration.po b/po/hi/kdecoration.po new file mode 100644 index 0000000..a94efad --- /dev/null +++ b/po/hi/kdecoration.po @@ -0,0 +1,97 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# Sameer Singh , 2021. +# Raghavendra Kamath , 2021. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-06-29 17:56+0530\n" +"Last-Translator: Raghavendra Kamath \n" +"Language-Team: kde-hindi\n" +"Language: hi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" +"X-Generator: Lokalize 21.04.2\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "इस विंडो के लिए और क्रियाएँ" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "अनुप्रयोग मेन्यू" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "एक डेस्कटॉप पर" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "सभी डेस्कटॉप पर" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "न्यूनतम" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "पुरानी स्तिथी में लाऐं" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "अधिकतम" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "बंद करें" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "प्रासंगिक सहायता" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "छाया हटाएँ" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "छाया" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "अन्य विंडो के नीचे न रखें" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "अन्य विंडो के नीचे रखें" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "अन्य विंडो के ऊपर न रखें" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "अन्य विंडो के ऊपर रखें" + +#~ msgid "Menu" +#~ msgstr "मेन्यू" diff --git a/po/hu/kdecoration.po b/po/hu/kdecoration.po new file mode 100644 index 0000000..98c4723 --- /dev/null +++ b/po/hu/kdecoration.po @@ -0,0 +1,103 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# Kristóf Kiszel , 2019. +# Kristof Kiszel , 2021. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-11-24 13:23+0100\n" +"Last-Translator: Kristof Kiszel \n" +"Language-Team: Hungarian \n" +"Language: hu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 21.08.3\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "További műveletek" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Alkalmazásmenü" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Egy asztalon" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Az összes asztalra" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimalizálás" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Visszaállítás" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximalizálás" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Bezárás" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Helyi súgó" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Világosítás" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Árnyékolás" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Ne maradjon más ablakok alatt" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Maradjon más ablakok alatt" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Ne maradjon más ablakok fölött" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Maradjon más ablakok fölött" + +#~ msgid "Menu" +#~ msgstr "Menü" + +#~ msgid "Keep below" +#~ msgstr "Mindig alul" + +#~ msgid "Keep above" +#~ msgstr "Mindig felül" diff --git a/po/ia/kdecoration.po b/po/ia/kdecoration.po new file mode 100644 index 0000000..60653cb --- /dev/null +++ b/po/ia/kdecoration.po @@ -0,0 +1,102 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# Giovanni Sora , 2019, 2020, 2021. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-11 23:13+0100\n" +"Last-Translator: Giovanni Sora \n" +"Language-Team: Interlingua \n" +"Language: ia\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 2.0\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Altere actiones per iste fenestra" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Menu de application" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Sur un scriptorio" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Super omne scriptorios" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimisa" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Restabili" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximiza" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Claude" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Adjuta de contexto" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "De-Umbra" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Umbra" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Non mantene infra altere fenestras" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Mantene infra altere fenestras" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Non mantene supra altere fenestras" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Mantene supra altere fenestras" + +#~ msgid "Menu" +#~ msgstr "Menu" + +#~ msgid "Keep below" +#~ msgstr "Mantene infra" + +#~ msgid "Keep above" +#~ msgstr "Mantene supra" diff --git a/po/id/kdecoration.po b/po/id/kdecoration.po new file mode 100644 index 0000000..54f53b2 --- /dev/null +++ b/po/id/kdecoration.po @@ -0,0 +1,103 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# Wantoyo , 2018, 2019, 2022. +# Aziz Adam Adrian <4.adam.adrian@gmail.com>, 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2022-09-27 17:54+0700\n" +"Last-Translator: Wantoyèk \n" +"Language-Team: Indonesian \n" +"Language: id\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 21.12.3\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Aksi selebihnya untuk jendela ini" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Menu aplikasi" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Pada satu desktop" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Pada semua desktop" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimalkan" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Kembalikan" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maksimalkan" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Tutup" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Bantuan konteks" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Tak bertirai" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Tiraikan" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Jangan tetap di bawah jendela lainnya" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Tetap di bawah jendela lainnya" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Jangan tetap di atas jendela lainnya" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Tetap di atas jendela lainnya" + +#~ msgid "Menu" +#~ msgstr "Menu" + +#~ msgid "Keep below" +#~ msgstr "Tetap di bawah" + +#~ msgid "Keep above" +#~ msgstr "Tetap di atas" diff --git a/po/is/kdecoration.po b/po/is/kdecoration.po new file mode 100644 index 0000000..8da1019 --- /dev/null +++ b/po/is/kdecoration.po @@ -0,0 +1,94 @@ +# Copyright (C) 2024 This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# Sveinn í Felli , 2023. +# SPDX-FileCopyrightText: 2024 Guðmundur Erlingsson +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2024-03-25 13:52+0000\n" +"Last-Translator: Guðmundur Erlingsson \n" +"Language-Team: Icelandic \n" +"Language: is\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 23.08.3\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Fleiri aðgerðir fyrir þennan glugga" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Forritavalmynd" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Á einu skjáborði" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Á öllum skjáborðum" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Fela" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Endurheimta" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Fullstækka" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Loka" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Samhengishjálp" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Rúlla niður" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Rúlla upp" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Ekki hafa undir öðrum gluggum" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Hafa undir öðrum gluggum" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Ekki hafa yfir öðrum gluggum" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Hafa yfir öðrum gluggum" diff --git a/po/it/kdecoration.po b/po/it/kdecoration.po new file mode 100644 index 0000000..1a40bb1 --- /dev/null +++ b/po/it/kdecoration.po @@ -0,0 +1,102 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the kdecoration package. +# Paolo Zamponi , 2018, 2021. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-12 08:49+0200\n" +"Last-Translator: Paolo Zamponi \n" +"Language-Team: Italian \n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 21.04.0\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Altre azioni per questa finestra" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Menu dell'applicazione" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Su un desktop" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Su tutti i desktop" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimizza" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Ripristina" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Massimizza" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Chiudi" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Aiuto contestuale" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Srotola" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Arrotola" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Non tenere sotto le altre finestre" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Tieni sotto le altre finestre" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Non tenere sopra le altre finestre" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Tieni sopra le altre finestre" + +#~ msgid "Menu" +#~ msgstr "Menu" + +#~ msgid "Keep below" +#~ msgstr "Tieni sotto" + +#~ msgid "Keep above" +#~ msgstr "Tieni sopra" diff --git a/po/ja/kdecoration.po b/po/ja/kdecoration.po new file mode 100644 index 0000000..ce2f501 --- /dev/null +++ b/po/ja/kdecoration.po @@ -0,0 +1,93 @@ +# Tomohiro Hyakutake , 2019. +# Ryuichi Yamada , 2023. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2023-05-18 00:36+0900\n" +"Last-Translator: Ryuichi Yamada \n" +"Language-Team: Japanese \n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Accelerator-Marker: &\n" +"X-Text-Markup: kde4\n" +"X-Generator: Lokalize 23.04.0\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "このウィンドウに対するその他のアクション" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "アプリケーションメニュー" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "一つのデスクトップに表示" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "すべてのデスクトップに表示" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "最小化" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "復元" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "最大化" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "閉じる" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "コンテキストヘルプ" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "シェード解除" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "シェード" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "他のウィンドウの下に保持しない" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "他のウィンドウより下に表示" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "他のウィンドウの上に保持しない" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "他のウィンドウより上に表示" diff --git a/po/ka/kdecoration.po b/po/ka/kdecoration.po new file mode 100644 index 0000000..6744058 --- /dev/null +++ b/po/ka/kdecoration.po @@ -0,0 +1,94 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2022-05-21 14:43+0200\n" +"Last-Translator: Temuri Doghonadze \n" +"Language-Team: Georgian \n" +"Language: ka\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.0.1\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "მეტი ქმედება ამ ფანჯრისთვის" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "პროგრამის მენიუ" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "1 სამუშაო მაგიდაზე" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "ყველა სამუშაო მაგიდაზე" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "ჩაკეცვა" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "აღდგენა" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "გადიდება" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "დახურვა" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "კონტექსტური დახმარება" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "განჩრდილვა" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "დაჩრდილვა" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "დანარჩენი ფანჯრების ქვემოთ ქონის გამორთვა" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "დანარჩენი ფანჯრების ქვემოთ ქონა" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "დანარჩენი ფანჯრების ზემოთ ქონის გამორთვა" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "დანარჩენი ფანჯრების ზემოთ ქონა" diff --git a/po/ko/kdecoration.po b/po/ko/kdecoration.po new file mode 100644 index 0000000..a465021 --- /dev/null +++ b/po/ko/kdecoration.po @@ -0,0 +1,102 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# Shinjo Park , 2018, 2020, 2021. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-16 21:48+0200\n" +"Last-Translator: Shinjo Park \n" +"Language-Team: Korean \n" +"Language: ko\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Lokalize 20.12.3\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "이 창의 더 많은 동작" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "앱 메뉴" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "한 바탕 화면에만" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "모든 바탕 화면에 두기" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "최소화" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "복원" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "최대화" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "닫기" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "문맥 도움말" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "풀어 내리기" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "말아 올리기" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "다른 ì°½ 아래에 두지 않기" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "다른 ì°½ 아래에 두기" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "다른 ì°½ 위에 두지 않기" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "다른 ì°½ 위에 두기" + +#~ msgid "Menu" +#~ msgstr "메뉴" + +#~ msgid "Keep below" +#~ msgstr "항상 아래에 두기" + +#~ msgid "Keep above" +#~ msgstr "항상 위에 두기" diff --git a/po/lt/kdecoration.po b/po/lt/kdecoration.po new file mode 100644 index 0000000..b88c1e3 --- /dev/null +++ b/po/lt/kdecoration.po @@ -0,0 +1,104 @@ +# Lithuanian translations for kdecoration package. +# Copyright (C) 2019 This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# Automatically generated, 2019. +# +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-06-15 22:43+0300\n" +"Last-Translator: Moo\n" +"Language-Team: lt\n" +"Language: lt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : n%10>=2 && (n%100<10 || n" +"%100>=20) ? 1 : n%10==0 || (n%100>10 && n%100<20) ? 2 : 3);\n" +"X-Generator: Poedit 3.0\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Daugiau veiksmų Å¡iam langui" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Programos meniu" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Viename darbalaukyje" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Visuose darbalaukiuose" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Suskleisti" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Grąžinti iÅ¡ suskleidimo" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "IÅ¡skleisti" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Užverti" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Kontekstinė pagalba" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Rodyti ne tik lango antraÅ¡tės juostą" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Rodyti tik lango antraÅ¡tės juostą" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Nelaikyti po kitais langais" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Laikyti po kitais langais" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Nelaikyti virÅ¡ kitų langų" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Laikyti virÅ¡ kitų langų" + +#~ msgid "Menu" +#~ msgstr "Meniu" + +#~ msgid "Keep below" +#~ msgstr "Laikyti apačioje" + +#~ msgid "Keep above" +#~ msgstr "Laikyti virÅ¡uje" diff --git a/po/lv/kdecoration.po b/po/lv/kdecoration.po new file mode 100644 index 0000000..3410bd6 --- /dev/null +++ b/po/lv/kdecoration.po @@ -0,0 +1,94 @@ +# Copyright (C) 2024 This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# SPDX-FileCopyrightText: 2024 Toms TrasÅ«ns +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2024-01-27 12:55+0200\n" +"Last-Translator: Toms TrasÅ«ns \n" +"Language-Team: Latvian \n" +"Language: lv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" +"X-Generator: Lokalize 23.08.4\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Vairāk darbÄ«bu Å¡im logam" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Programmas izvēlne" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Uz vienas darbvirsmas" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Uz visām darbvirsmām" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimizēt" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Atjaunot" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maksimizēt" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Aizvērt" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Konteksta palÄ«dzÄ«ba" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Atritināt" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Saritināt" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Neturēt zem citiem logiem" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Turēt zem citiem logiem" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Neturēt virs citiem logiem" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Turēt virs citiem logiem" diff --git a/po/ml/kdecoration.po b/po/ml/kdecoration.po new file mode 100644 index 0000000..8a1cbbb --- /dev/null +++ b/po/ml/kdecoration.po @@ -0,0 +1,94 @@ +# Malayalam translations for kdecoration package. +# Copyright (C) 2019 This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# Automatically generated, 2019. +# +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2018-08-16 09:14+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: Swathanthra|സ്വതന്ത്ര Malayalam|മലയാളം Computing|കമ്പ്യൂട്ടിങ്ങ് \n" +"Language: ml\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "" diff --git a/po/nl/kdecoration.po b/po/nl/kdecoration.po new file mode 100644 index 0000000..960e01b --- /dev/null +++ b/po/nl/kdecoration.po @@ -0,0 +1,102 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Freek de Kruijf , 2018, 2021. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-05 09:39+0200\n" +"Last-Translator: Freek de Kruijf \n" +"Language-Team: Dutch \n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 21.04.0\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Meer acties voor dit venster" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Menu van toepassing" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Op één bureaublad" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Op alle bureaubladen" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimaliseren" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Herstellen" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximaliseren" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Sluiten" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Contexthelp" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Schaduw weghalen" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Oprollen" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Niet onder andere vensters houden" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Onder andere vensters houden" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Niet boven andere vensters houden" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Boven andere vensters houden" + +#~ msgid "Menu" +#~ msgstr "Menu" + +#~ msgid "Keep below" +#~ msgstr "Altijd op achtergrond" + +#~ msgid "Keep above" +#~ msgstr "Altijd op voorgrond" diff --git a/po/nn/kdecoration.po b/po/nn/kdecoration.po new file mode 100644 index 0000000..53ad5b0 --- /dev/null +++ b/po/nn/kdecoration.po @@ -0,0 +1,96 @@ +# Translation of kdecoration to Norwegian Nynorsk +# +# Karl Ove Hufthammer , 2018, 2022. +# Øystein Steffensen-Alværvik , 2021. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2022-06-19 13:54+0200\n" +"Last-Translator: Karl Ove Hufthammer \n" +"Language-Team: Norwegian Nynorsk \n" +"Language: nn\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 22.04.2\n" +"X-Environment: kde\n" +"X-Accelerator-Marker: &\n" +"X-Text-Markup: kde4\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Fleire handlingar for vindauget" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Programmeny" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "PÃ¥ eitt skrivebord" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "PÃ¥ alle skriveborda" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimer" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Gjenopprett" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maksimer" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Lukk" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Emnehjelp" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Rull ned" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Rull opp" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Ikkje hald under andre vindauge" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Hald under andre vindauge" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Ikkje hald over andre vindauge" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Hald over andre vindauge" diff --git a/po/pa/kdecoration.po b/po/pa/kdecoration.po new file mode 100644 index 0000000..7a62f1e --- /dev/null +++ b/po/pa/kdecoration.po @@ -0,0 +1,93 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# A S Alam , 2023. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2023-05-19 20:09-0700\n" +"Last-Translator: A S Alam \n" +"Language-Team: Punjabi \n" +"Language: pa\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 23.04.1\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "ਇਸ ਵਿੰਡੋ ਲਈ ਹੋਰ ਕਾਰਵਾਈਆਂ" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "ਐਪਲੀਕੇਸ਼ਨ ਮੇਨੂ" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "ਇੱਕ ਡੈਸਕਟਾਪ ਉੱਤੇ" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "ਸਾਰੇ ਡੈਸਕਟਾਪਾਂ ਉੱਤੇ" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "ਘੱਟੋ-ਘੱਟ" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "ਬਹਾਲ ਕਰੋ" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "ਵੱਧੋ-ਵੱਧ" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "ਬੰਦ ਕਰੋ" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "ਪ੍ਰਸੰਗ ਮਦਦ" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "ਬਿਨਾਂ-ਸ਼ੇਡ" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "ਸ਼ੇਡ" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "ਹੋਰ ਵਿੰਡੋਆਂ ਦੇ ਹੇਠਾਂ ਨਾ ਰੱਖੋ" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "ਹੋਰ ਵਿੰਡੋਆਂ ਦੇ ਹੇਠਾਂ ਰੱਖੋ" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "ਹੋਰ ਵਿੰਡੋਆਂ ਦੇ ਉੱਤੇ ਨਾ ਰੱਖੋ" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "ਹੋਰ ਵਿੰਡੋਆਂ ਦੇ ਉੱਤੇ ਰੱਖੋ" diff --git a/po/pl/kdecoration.po b/po/pl/kdecoration.po new file mode 100644 index 0000000..623196f --- /dev/null +++ b/po/pl/kdecoration.po @@ -0,0 +1,102 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Łukasz Wojniłowicz , 2018, 2021. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-12-30 13:22+0100\n" +"Last-Translator: Łukasz Wojniłowicz \n" +"Language-Team: Polish \n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Więcej działań dla tego okna" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Menu programów" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Na pulpicie" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Na wszystkich pulpitach" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Zminimalizuj" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Przywróć" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Zmaksymalizuj" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Zamknij" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Pomoc podręczna" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Rozwiń" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Zwiń" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Nie utrzymuj pod innymi oknami" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Utrzymuj pod innymi oknami" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Nie utrzymuj nad innymi oknami" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Utrzymuj nad innymi oknami" + +#~ msgid "Menu" +#~ msgstr "Menu" + +#~ msgid "Keep below" +#~ msgstr "Zawsze pod spodem" + +#~ msgid "Keep above" +#~ msgstr "Zawsze na wierzchu" diff --git a/po/pt/kdecoration.po b/po/pt/kdecoration.po new file mode 100644 index 0000000..995ac14 --- /dev/null +++ b/po/pt/kdecoration.po @@ -0,0 +1,88 @@ +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-06 16:43+0100\n" +"Last-Translator: José Nuno Coelho Pires \n" +"Language-Team: Portuguese \n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Mais acções para esta janela" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Menu da aplicação" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Num ecrã" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Em todos os ecrãs" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimizar" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Repor" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximizar" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Fechar" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Ajuda de contexto" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Desenrolar" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Enrolar" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Não manter abaixo das outras janelas" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Manter abaixo das outras janelas" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Não manter acima das outras janelas" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Manter acima das outras janelas" diff --git a/po/pt_BR/kdecoration.po b/po/pt_BR/kdecoration.po new file mode 100644 index 0000000..4113caa --- /dev/null +++ b/po/pt_BR/kdecoration.po @@ -0,0 +1,102 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Luiz Fernando Ranghetti , 2018, 2021. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-06 14:05-0300\n" +"Last-Translator: Luiz Fernando Ranghetti \n" +"Language-Team: Brazilian Portuguese \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Lokalize 20.04.2\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Mais ações para esta janela" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Menu do aplicativo" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Em uma área de trabalho" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Em todas as áreas de trabalho" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimizar" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Restaurar" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximizar" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Fechar" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Ajuda de contexto" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Sem sombras" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Sombrear" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Não manter abaixo de outras janelas" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Manter abaixo de outras janelas" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Não manter acima de outras janelas" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Manter acima de outras janelas" + +#~ msgid "Menu" +#~ msgstr "Menu" + +#~ msgid "Keep below" +#~ msgstr "Manter abaixo" + +#~ msgid "Keep above" +#~ msgstr "Manter acima" diff --git a/po/ro/kdecoration.po b/po/ro/kdecoration.po new file mode 100644 index 0000000..2052a70 --- /dev/null +++ b/po/ro/kdecoration.po @@ -0,0 +1,103 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# Sergiu Bivol , 2020, 2021. +# +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-06-02 20:19+0100\n" +"Last-Translator: Sergiu Bivol \n" +"Language-Team: Romanian\n" +"Language: ro\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " +"20)) ? 1 : 2;\n" +"X-Generator: Lokalize 19.12.3\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Acțiuni suplimentare pentru această fereastră" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Meniul aplicației" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Pe un birou" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Pe toate birourile" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimizează" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Restabilește" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximizează" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Închide" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Ajutor contextual" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Desfășoară" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Strânge" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Nu ține sub alte ferestre" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Ține sub alte ferestre" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Nu ține deasupra altor ferestre" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Ține deasupra altor ferestre" + +#~ msgid "Menu" +#~ msgstr "Meniu" + +#~ msgid "Keep below" +#~ msgstr "Ține dedesubt" + +#~ msgid "Keep above" +#~ msgstr "Ține deasupra" diff --git a/po/ru/kdecoration.po b/po/ru/kdecoration.po new file mode 100644 index 0000000..afb429a --- /dev/null +++ b/po/ru/kdecoration.po @@ -0,0 +1,104 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Alexander Potashev , 2018. +# Alexander Yavorsky , 2021. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-06-08 16:54+0300\n" +"Last-Translator: Alexander Yavorsky \n" +"Language-Team: Russian \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n" +"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Lokalize 21.04.1\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Дополнительные действия для этого окна" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Меню приложения" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "На одном рабочем столе" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "На всех рабочих столах" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Свернуть" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Восстановить" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Распахнуть" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Закрыть" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Контекстная справка" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Развернуть из заголовка" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Свернуть в заголовок" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Не удерживать ниже других окон" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Удерживать ниже других окон" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Не удерживать поверх других окон" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Удерживать поверх других окон" + +#~ msgid "Menu" +#~ msgstr "Меню" + +#~ msgid "Keep below" +#~ msgstr "Поддерживать на заднем плане" + +#~ msgid "Keep above" +#~ msgstr "Поддерживать поверх других" diff --git a/po/sa/kdecoration.po b/po/sa/kdecoration.po new file mode 100644 index 0000000..8c8a827 --- /dev/null +++ b/po/sa/kdecoration.po @@ -0,0 +1,94 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2023-09-27 19:49+0530\n" +"Last-Translator: \n" +"Language-Team: Sanskrit \n" +"Language: sa\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.3.2\n" +"Plural-Forms: nplurals=2; plural=(n>2);\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "अस्य गवाक्ष कृते अधिकानि क्रियाणि" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "अनुप्रयोग सूचि" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "एकस्मिन् कार्यमुखे" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "सर्वेषु कार्यमुखेषु" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "न्यूनतमं करोतु" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "निर्यत्" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "अधिकतमं कुर्वन्तु" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "निमील्यताम्" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "सन्दर्भ सहाय्यम्" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "अनच्छाया" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "छाया" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "अन्येषां गवाक्षानां अधः न स्थापयन्तु" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "अन्येषां गवाक्षानां अधः स्थापयन्तु" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "अन्येषां गवाक्षानां उपरि न स्थापयन्तु" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "अन्येषां गवाक्षानां उपरि स्थापयन्तु" diff --git a/po/sk/kdecoration.po b/po/sk/kdecoration.po new file mode 100644 index 0000000..2bb8654 --- /dev/null +++ b/po/sk/kdecoration.po @@ -0,0 +1,101 @@ +# translation of kdecoration.po Slovak +# Roman Paholík , 2018. +# Matej Mrenica , 2019, 2021. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-07-20 17:50+0200\n" +"Last-Translator: Matej Mrenica \n" +"Language-Team: Slovak \n" +"Language: sk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 21.07.80\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Viac akcií pre toto okno" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Aplikačná ponuka" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Na jednej ploche" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Na vÅ¡etkých plochách" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "MinimalizovaÅ¥" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "ObnoviÅ¥" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "MaximalizovaÅ¥" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "ZavrieÅ¥" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Kontextový pomocník" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "OdtieňovaÅ¥" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "TieňovaÅ¥" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "NedržaÅ¥ pod ostatnými oknami" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "DržaÅ¥ pod ostatnými oknami" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "NedržaÅ¥ nad ostatnými oknami" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "DržaÅ¥ nad ostatnými oknami" + +#~ msgid "Menu" +#~ msgstr "Ponuka" + +#~ msgid "Keep below" +#~ msgstr "DržaÅ¥ pod" + +#~ msgid "Keep above" +#~ msgstr "DržaÅ¥ nad" diff --git a/po/sl/kdecoration.po b/po/sl/kdecoration.po new file mode 100644 index 0000000..6256e31 --- /dev/null +++ b/po/sl/kdecoration.po @@ -0,0 +1,103 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# Matjaž Jeran , 2020, 2021. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-08 08:39+0200\n" +"Last-Translator: Matjaž Jeran \n" +"Language-Team: Slovenian \n" +"Language: sl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 20.12.2\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n" +"%100==4 ? 3 : 0);\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Več dejavnosti za to okno" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Meni aplikacije" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Na enem namizju" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Na vseh namizjih" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Strni" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Obnovi" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Razpni" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Zapri" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Kontekstna pomoč" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Odpravi senčenje" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Osenči" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Ne zadržuj pod drugimi okni" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Zadržuj pod drugimi okni" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Ne zadržuj nad drugimi okni" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Zadržuj nad drugimi okni" + +#~ msgid "Menu" +#~ msgstr "Meni" + +#~ msgid "Keep below" +#~ msgstr "Zadržuj spodaj" + +#~ msgid "Keep above" +#~ msgstr "Zadržuj na vrhu" diff --git a/po/sv/kdecoration.po b/po/sv/kdecoration.po new file mode 100644 index 0000000..ac90980 --- /dev/null +++ b/po/sv/kdecoration.po @@ -0,0 +1,102 @@ +# Copyright (C) YEAR This_file_is_part_of_KDE +# This file is distributed under the same license as the PACKAGE package. +# +# Stefan Asserhäll , 2018, 2021. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-05 08:09+0200\n" +"Last-Translator: Stefan Asserhäll \n" +"Language-Team: Swedish \n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 20.08.1\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Fler Ã¥tgärder för fönstret" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Programmeny" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "PÃ¥ ett skrivbord" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "PÃ¥ alla skrivbord" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Minimera" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Återställ" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Maximera" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Stäng" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Sammanhangsberoende hjälp" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Rulla ner" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Rulla upp" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "BehÃ¥ll inte under andra fönster" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "BehÃ¥ll under andra fönster" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "BehÃ¥ll inte över andra fönster" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "BehÃ¥ll över andra fönster" + +#~ msgid "Menu" +#~ msgstr "Meny" + +#~ msgid "Keep below" +#~ msgstr "BehÃ¥ll under" + +#~ msgid "Keep above" +#~ msgstr "BehÃ¥ll över" diff --git a/po/ta/kdecoration.po b/po/ta/kdecoration.po new file mode 100644 index 0000000..7c7263a --- /dev/null +++ b/po/ta/kdecoration.po @@ -0,0 +1,93 @@ +# Copyright (C) 2024 This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# SPDX-FileCopyrightText: 2024 Kishore G +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2024-06-30 12:37+0530\n" +"Last-Translator: Kishore G \n" +"Language-Team: Tamil \n" +"Language: ta\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 24.05.1\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "இச்சாளரத்திற்கான கூடுதல் செயல்கள்" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "செயலி பட்டி" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "ஒரு பணிமேடையில்" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "அனைத்து பணிமேடைகளிலும்" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "ஒதுக்கு" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "மீட்டெடு" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "அதிகபட்ச பெரிதாக்கு" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "மூடு" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "சூழலை பொறுத்த உதவி" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "நிழல்நீக்கு" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "நிழலிடு" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "மற்ற சாளரங்களுக்கு கீழே வைக்க வேண்டாம்" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "மற்ற சாளரங்களுக்கு கீழே வை" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "மற்ற சாளரங்களுக்கு மேலே வைக்க வேண்டாம்" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "மற்ற சாளரங்களுக்கு மேலே வை" diff --git a/po/tr/kdecoration.po b/po/tr/kdecoration.po new file mode 100644 index 0000000..084b543 --- /dev/null +++ b/po/tr/kdecoration.po @@ -0,0 +1,93 @@ +# Copyright (C) 2024 This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# SPDX-FileCopyrightText: 2022, 2023, 2024 Emir SARI +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2024-06-20 13:53+0300\n" +"Last-Translator: Emir SARI \n" +"Language-Team: Turkish \n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Lokalize 24.07.70\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Bu pencere için daha fazla eylem" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Uygulama menüsü" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "Bir masaüstünde" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "Tüm masaüstlerinde" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Simge Durumuna Küçült" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Eski Haline Döndür" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Ekranı Kapla" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Kapat" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Bağlam Yardımı" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Panjuru Aç" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Panjuru Kapat" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Diğer pencerelerin altında tutma" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Diğer pencerelerin altında tut" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Diğer pencerelerin üzerinde tutma" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Diğer pencerelerin üzerinde tut" diff --git a/po/uk/kdecoration.po b/po/uk/kdecoration.po new file mode 100644 index 0000000..2259ad4 --- /dev/null +++ b/po/uk/kdecoration.po @@ -0,0 +1,105 @@ +# Translation of kdecoration.po to Ukrainian +# Copyright (C) 2018 This_file_is_part_of_KDE +# This file is distributed under the license LGPL version 2.1 or +# version 3 or later versions approved by the membership of KDE e.V. +# +# Yuri Chornoivan , 2018, 2021. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2021-05-05 08:29+0300\n" +"Last-Translator: Yuri Chornoivan \n" +"Language-Team: Ukrainian \n" +"Language: uk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n" +"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Lokalize 20.12.0\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "Додаткові дії для цього вікна" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "Меню програм" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "На одній стільниці" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "На всіх стільницях" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "Мінімізувати" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "Відновити" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "Максимізувати" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "Закрити" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "Контекстна довідка" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "Розгорнути" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "Згорнути" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "Не утримувати під іншими вікнами" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "Утримувати під іншими вікнами" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "Не утримувати над іншими вікнами" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "Утримувати над іншими вікнами" + +#~ msgid "Menu" +#~ msgstr "Меню" + +#~ msgid "Keep below" +#~ msgstr "Тримати знизу" + +#~ msgid "Keep above" +#~ msgstr "Тримати зверху" diff --git a/po/zh_CN/kdecoration.po b/po/zh_CN/kdecoration.po new file mode 100644 index 0000000..9430595 --- /dev/null +++ b/po/zh_CN/kdecoration.po @@ -0,0 +1,93 @@ +msgid "" +msgstr "" +"Project-Id-Version: kdeorg\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2024-04-22 15:58\n" +"Last-Translator: \n" +"Language-Team: Chinese Simplified\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Crowdin-Project: kdeorg\n" +"X-Crowdin-Project-ID: 269464\n" +"X-Crowdin-Language: zh-CN\n" +"X-Crowdin-File: /kf6-stable/messages/kdecoration/kdecoration.pot\n" +"X-Crowdin-File-ID: 52644\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "此窗口的更多操作" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "应用程序菜单" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "在一个桌面" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "在全部桌面" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "最小化" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "还原" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "最大化" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "关闭" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "相关帮助" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "展开" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "折叠" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "不要保持在其他窗口之下" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "保持在其他窗口之下" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "不要保持在其他窗口之上" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "保持在其他窗口之上" diff --git a/po/zh_TW/kdecoration.po b/po/zh_TW/kdecoration.po new file mode 100644 index 0000000..a18cb9a --- /dev/null +++ b/po/zh_TW/kdecoration.po @@ -0,0 +1,103 @@ +# Copyright (C) YEAR This file is copyright: +# This file is distributed under the same license as the kdecoration package. +# +# pan93412 , 2019. +# Kisaragi Hiu , 2023. +msgid "" +msgstr "" +"Project-Id-Version: kdecoration\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2024-02-10 00:40+0000\n" +"PO-Revision-Date: 2023-02-02 23:03+0900\n" +"Last-Translator: Kisaragi Hiu \n" +"Language-Team: Traditional Chinese \n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Lokalize 23.03.70\n" + +#: decorationbutton.cpp:303 +#, kde-format +msgid "More actions for this window" +msgstr "這個視窗的更多動作" + +#: decorationbutton.cpp:305 +#, kde-format +msgid "Application menu" +msgstr "應用程式選單" + +#: decorationbutton.cpp:308 +#, kde-format +msgid "On one desktop" +msgstr "僅在一個桌面上顯示" + +#: decorationbutton.cpp:310 +#, kde-format +msgid "On all desktops" +msgstr "在所有桌面上顯示" + +#: decorationbutton.cpp:312 +#, kde-format +msgid "Minimize" +msgstr "最小化" + +#: decorationbutton.cpp:315 +#, kde-format +msgid "Restore" +msgstr "回復大小" + +#: decorationbutton.cpp:317 +#, kde-format +msgid "Maximize" +msgstr "最大化" + +#: decorationbutton.cpp:319 +#, kde-format +msgid "Close" +msgstr "關閉" + +#: decorationbutton.cpp:321 +#, kde-format +msgid "Context help" +msgstr "內容說明" + +#: decorationbutton.cpp:324 +#, kde-format +msgid "Unshade" +msgstr "取消收起" + +#: decorationbutton.cpp:326 +#, kde-format +msgid "Shade" +msgstr "收起" + +#: decorationbutton.cpp:329 +#, kde-format +msgid "Don't keep below other windows" +msgstr "不要維持在其他視窗之下" + +#: decorationbutton.cpp:331 +#, kde-format +msgid "Keep below other windows" +msgstr "維持在其他視窗之下" + +#: decorationbutton.cpp:334 +#, kde-format +msgid "Don't keep above other windows" +msgstr "不要維持在其他視窗之上" + +#: decorationbutton.cpp:336 +#, kde-format +msgid "Keep above other windows" +msgstr "維持在其他視窗之上" + +#~ msgid "Menu" +#~ msgstr "選單" + +#~ msgid "Keep below" +#~ msgstr "保持於底部顯示" + +#~ msgid "Keep above" +#~ msgstr "保持於頂部顯示" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..eb07869 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,82 @@ +add_definitions(-DTRANSLATION_DOMAIN=\"kdecoration\") + +add_subdirectory(private) + +set(libkdecoration2_SRCS + decoratedclient.cpp + decoratedclient.h + decorationbutton.cpp + decorationbuttongroup.cpp + decorationbuttongroup.h + decorationbuttongroup_p.h + decorationbutton.h + decorationbutton_p.h + decoration.cpp + decorationdefines.h + decoration.h + decoration_p.h + decorationsettings.cpp + decorationsettings.h + decorationshadow.cpp + decorationshadow.h + decorationshadow_p.h + decorationthemeprovider.cpp + decorationthemeprovider.h + +) + +add_library(kdecorations2 SHARED ${libkdecoration2_SRCS}) +ecm_generate_export_header(kdecorations2 + VERSION ${PROJECT_VERSION} + EXPORT_FILE_NAME kdecoration2/kdecoration2_export.h + DEPRECATION_VERSIONS 5.21 + EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} +) + +add_library(KDecoration2::KDecoration ALIAS kdecorations2) + +target_link_libraries(kdecorations2 + PUBLIC + Qt::Core + Qt::Gui + PRIVATE + kdecorations2private + KF6::I18n +) + +target_include_directories(kdecorations2 INTERFACE "$" ) + +set_target_properties(kdecorations2 PROPERTIES VERSION ${KDECORATION2_VERSION} + SOVERSION ${KDECORATION2_SOVERSION} + EXPORT_NAME KDecoration +) + +ecm_generate_headers(KDecoration2_CamelCase_HEADERS + HEADER_NAMES + DecoratedClient + Decoration + DecorationButton + DecorationButtonGroup + DecorationSettings + DecorationShadow + DecorationThemeProvider + PREFIX + KDecoration2 + REQUIRED_HEADERS KDecoration2_HEADERS +) +install(FILES ${KDecoration2_CamelCase_HEADERS} + DESTINATION ${KDECORATION2_INCLUDEDIR}/KDecoration2 + COMPONENT Devel) + +install(TARGETS kdecorations2 EXPORT KDecoration2Targets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) + +install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/kdecoration2/kdecoration2_export.h + ${KDecoration2_HEADERS} + decorationdefines.h + DESTINATION + ${KDECORATION2_INCLUDEDIR}/kdecoration2 + COMPONENT + Devel +) diff --git a/src/Messages.sh b/src/Messages.sh new file mode 100644 index 0000000..f0f2522 --- /dev/null +++ b/src/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp -o $podir/kdecoration.pot diff --git a/src/decoratedclient.cpp b/src/decoratedclient.cpp new file mode 100644 index 0000000..e823c0d --- /dev/null +++ b/src/decoratedclient.cpp @@ -0,0 +1,192 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "decoratedclient.h" +#include "private/decoratedclientprivate.h" +#include "private/decorationbridge.h" + +#include + +namespace KDecoration2 +{ +DecoratedClient::DecoratedClient(Decoration *parent, DecorationBridge *bridge) + : QObject() + , d(bridge->createClient(this, parent)) +{ +} + +DecoratedClient::~DecoratedClient() = default; + +bool DecoratedClient::isActive() const +{ + return d->isActive(); +} + +QString DecoratedClient::caption() const +{ + return d->caption(); +} + +bool DecoratedClient::isOnAllDesktops() const +{ + return d->isOnAllDesktops(); +} + +bool DecoratedClient::isShaded() const +{ + return d->isShaded(); +} + +QIcon DecoratedClient::icon() const +{ + return d->icon(); +} + +bool DecoratedClient::isMaximized() const +{ + return d->isMaximized(); +} + +bool DecoratedClient::isMaximizedHorizontally() const +{ + return d->isMaximizedHorizontally(); +} + +bool DecoratedClient::isMaximizedVertically() const +{ + return d->isMaximizedVertically(); +} + +bool DecoratedClient::isKeepAbove() const +{ + return d->isKeepAbove(); +} + +bool DecoratedClient::isKeepBelow() const +{ + return d->isKeepBelow(); +} + +bool DecoratedClient::isCloseable() const +{ + return d->isCloseable(); +} + +bool DecoratedClient::isMaximizeable() const +{ + return d->isMaximizeable(); +} + +bool DecoratedClient::isMinimizeable() const +{ + return d->isMinimizeable(); +} + +bool DecoratedClient::providesContextHelp() const +{ + return d->providesContextHelp(); +} + +bool DecoratedClient::isModal() const +{ + return d->isModal(); +} + +bool DecoratedClient::isShadeable() const +{ + return d->isShadeable(); +} + +bool DecoratedClient::isMoveable() const +{ + return d->isMoveable(); +} + +bool DecoratedClient::isResizeable() const +{ + return d->isResizeable(); +} + +WId DecoratedClient::windowId() const +{ + return d->windowId(); +} + +WId DecoratedClient::decorationId() const +{ + return d->decorationId(); +} + +int DecoratedClient::width() const +{ + return d->width(); +} + +int DecoratedClient::height() const +{ + return d->height(); +} + +QSize DecoratedClient::size() const +{ + return d->size(); +} + +QPalette DecoratedClient::palette() const +{ + return d->palette(); +} + +Qt::Edges DecoratedClient::adjacentScreenEdges() const +{ + return d->adjacentScreenEdges(); +} + +QString DecoratedClient::windowClass() const +{ + return d->windowClass(); +} + +bool DecoratedClient::hasApplicationMenu() const +{ + if (const auto *appMenuEnabledPrivate = dynamic_cast(d.get())) { + return appMenuEnabledPrivate->hasApplicationMenu(); + } + return false; +} + +bool DecoratedClient::isApplicationMenuActive() const +{ + if (const auto *appMenuEnabledPrivate = dynamic_cast(d.get())) { + return appMenuEnabledPrivate->isApplicationMenuActive(); + } + return false; +} + +Decoration *DecoratedClient::decoration() const +{ + return d->decoration(); +} + +QColor DecoratedClient::color(QPalette::ColorGroup group, QPalette::ColorRole role) const +{ + return d->palette().color(group, role); +} + +QColor DecoratedClient::color(ColorGroup group, ColorRole role) const +{ + return d->color(group, role); +} + +void DecoratedClient::showApplicationMenu(int actionId) +{ + if (auto *appMenuEnabledPrivate = dynamic_cast(d.get())) { + appMenuEnabledPrivate->showApplicationMenu(actionId); + } +} + +} // namespace + +#include "moc_decoratedclient.cpp" diff --git a/src/decoratedclient.h b/src/decoratedclient.h new file mode 100644 index 0000000..76c3fcd --- /dev/null +++ b/src/decoratedclient.h @@ -0,0 +1,273 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +#include "decoration.h" +#include "decorationdefines.h" +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace KDecoration2 +{ +class DecorationBridge; +class DecoratedClientPrivate; + +/** + * @brief The Client which gets decorated. + * + * The DecoratedClient provides access to all the properties relevant for decorating the Client. + * Each DecoratedClient is bound to one Decoration and each Decoration is bound to this one + * DecoratedClient. + * + * The DecoratedClient only exports properties, it does not provide any means to change the state. + * To change state one needs to call the methods on Decoration. This is as the backend might + * disallow state changes. Therefore any changes should be bound to the change signals of the + * DecoratedClient and not be bound to state changes of input elements (such as a button). + */ +class KDECORATIONS2_EXPORT DecoratedClient : public QObject +{ + Q_OBJECT + /** + * The Decoration of this DecoratedClient + **/ + Q_PROPERTY(KDecoration2::Decoration *decoration READ decoration CONSTANT) + /** + * Whether the DecoratedClient is active (has focus) or is inactive. + **/ + Q_PROPERTY(bool active READ isActive NOTIFY activeChanged) + /** + * The caption of the DecoratedClient. + **/ + Q_PROPERTY(QString caption READ caption NOTIFY captionChanged) + /** + * Whether the DecoratedClient is on all desktops or on just one. + **/ + Q_PROPERTY(bool onAllDesktops READ isOnAllDesktops NOTIFY onAllDesktopsChanged) + /** + * Whether the DecoratedClient is shaded. Shaded means that the actual content is + * not visible, only the Decoration is visible. + **/ + Q_PROPERTY(bool shaded READ isShaded NOTIFY shadedChanged) + /** + * The icon of the DecoratedClient. This can be used as the icon for the window menu button. + **/ + Q_PROPERTY(QIcon icon READ icon NOTIFY iconChanged) + /** + * Whether the DecoratedClient is maximized. A DecoratedClient is maximized if it is both + * maximizedHorizontally and maximizedVertically. The Decoration of a maximized DecoratedClient + * should only consist of the title bar area. + **/ + Q_PROPERTY(bool maximized READ isMaximized NOTIFY maximizedChanged) + /** + * Whether the DecoratedClient is maximized horizontally. A horizontally maximized DecoratedClient + * uses the maximal possible width. + **/ + Q_PROPERTY(bool maximizedHorizontally READ isMaximizedHorizontally NOTIFY maximizedHorizontallyChanged) + /** + * Whether the DecoratedClient is maximized vertically. A vertically maximized DecoratedClient + * uses the maximal possible height. + **/ + Q_PROPERTY(bool maximizedVertically READ isMaximizedVertically NOTIFY maximizedVerticallyChanged) + /** + * Whether the DecoratedClient is set to be kept above other DecoratedClients. There can be multiple + * DecoratedClients which are set to be kept above. + **/ + Q_PROPERTY(bool keepAbove READ isKeepAbove NOTIFY keepAboveChanged) + /** + * Whether the DecoratedClient is set to be kept below other DecoratedClients. There can be multiple + * DecoratedClients which are set to be kept below. + **/ + Q_PROPERTY(bool keepBelow READ isKeepBelow NOTIFY keepBelowChanged) + + /** + * Whether the DecoratedClient can be closed. If this property is @c false a DecorationButton + * for closing the DecoratedClient should be disabled. + **/ + Q_PROPERTY(bool closeable READ isCloseable NOTIFY closeableChanged) + /** + * Whether the DecoratedClient can be maximized. If this property is @c false a DecorationButton + * for maximizing the DecoratedClient should be disabled. + **/ + Q_PROPERTY(bool maximizeable READ isMaximizeable NOTIFY maximizeableChanged) + /** + * Whether the DecoratedClient can be minimized. If this property is @c false a DecorationButton + * for minimizing the DecoratedClient should be disabled. + **/ + Q_PROPERTY(bool minimizeable READ isMinimizeable NOTIFY minimizeableChanged) + /** + * Whether the DecoratedClient provides context help. + * The Decoration should only show a context help button if this property is @c true. + **/ + Q_PROPERTY(bool providesContextHelp READ providesContextHelp NOTIFY providesContextHelpChanged) + /** + * Whether the DecoratedClient is a modal dialog. + **/ + Q_PROPERTY(bool modal READ isModal CONSTANT) + /** + * Whether the DecoratedClient can be shaded. If this property is @c false a DecorationButton + * for shading the DecoratedClient should be disabled. + **/ + Q_PROPERTY(bool shadeable READ isShadeable NOTIFY shadeableChanged) + /** + * Whether the DecoratedClient can be moved. + **/ + Q_PROPERTY(bool moveable READ isMoveable NOTIFY moveableChanged) + /** + * Whether the DecoratedClient can be resized. + **/ + Q_PROPERTY(bool resizeable READ isResizeable NOTIFY resizeableChanged) + + /** + * The width of the DecoratedClient. + **/ + Q_PROPERTY(int width READ width NOTIFY widthChanged) + /** + * The height of the DecoratedClient. + **/ + Q_PROPERTY(int height READ height NOTIFY heightChanged) + /** + * The size of the DecoratedClient. + **/ + Q_PROPERTY(QSize size READ size NOTIFY sizeChanged) + /** + * The palette this DecoratedClient uses. The palette might be different for each + * DecoratedClient and the Decoration should honor the palette. + **/ + Q_PROPERTY(QPalette palette READ palette NOTIFY paletteChanged) + /** + * The Edges which are adjacent to a screen edge. E.g. for a maximized DecoratedClient this + * will include all Edges. The Decoration can use this information to hide borders. + **/ + Q_PROPERTY(Qt::Edges adjacentScreenEdges READ adjacentScreenEdges NOTIFY adjacentScreenEdgesChanged) + /** + * Whether the DecoratedClient has an application menu + * @since 5.9 + */ + Q_PROPERTY(bool hasApplicationMenu READ hasApplicationMenu NOTIFY hasApplicationMenuChanged) + /** + * Whether the application menu for this DecoratedClient is currently shown to the user + * The Decoration can use this information to highlight the respective button. + * @since 5.9 + */ + Q_PROPERTY(bool applicationMenuActive READ isApplicationMenuActive NOTIFY applicationMenuActiveChanged) + + // TODO: properties for windowId and decorationId? + +public: + DecoratedClient() = delete; + ~DecoratedClient() override; + bool isActive() const; + QString caption() const; + bool isOnAllDesktops() const; + bool isShaded() const; + QIcon icon() const; + bool isMaximized() const; + bool isMaximizedHorizontally() const; + bool isMaximizedVertically() const; + bool isKeepAbove() const; + bool isKeepBelow() const; + + bool isCloseable() const; + bool isMaximizeable() const; + bool isMinimizeable() const; + bool providesContextHelp() const; + bool isModal() const; + bool isShadeable() const; + bool isMoveable() const; + bool isResizeable() const; + + Qt::Edges adjacentScreenEdges() const; + + WId windowId() const; + WId decorationId() const; + + QString windowClass() const; + + int width() const; + int height() const; + QSize size() const; + + Decoration *decoration() const; + QPalette palette() const; + /** + * Used to get colors in QPalette. + * @param group The color group + * @param role The color role + * @return palette().color(group, role) + * @since 5.3 + **/ + QColor color(QPalette::ColorGroup group, QPalette::ColorRole role) const; + /** + * Used to get additional colors that are not in QPalette. + * @param group The color group + * @param role The color role + * @return The color if provided for combination of group and role, otherwise invalid QColor. + * @since 5.3 + **/ + QColor color(ColorGroup group, ColorRole role) const; + + /** + * Whether the DecoratedClient has an application menu + * @since 5.9 + */ + bool hasApplicationMenu() const; + /** + * Whether the application menu for this DecoratedClient is currently shown to the user + * The Decoration can use this information to highlight the respective button. + * @since 5.9 + */ + bool isApplicationMenuActive() const; + + /** + * Request the application menu to be shown to the user + * @param actionId The DBus menu ID of the action that should be highlighted, 0 for none. + */ + void showApplicationMenu(int actionId); + +Q_SIGNALS: + void activeChanged(bool); + void captionChanged(QString); + void onAllDesktopsChanged(bool); + void shadedChanged(bool); + void iconChanged(QIcon); + void maximizedChanged(bool); + void maximizedHorizontallyChanged(bool); + void maximizedVerticallyChanged(bool); + void keepAboveChanged(bool); + void keepBelowChanged(bool); + + void closeableChanged(bool); + void maximizeableChanged(bool); + void minimizeableChanged(bool); + void providesContextHelpChanged(bool); + void shadeableChanged(bool); + void moveableChanged(bool); + void resizeableChanged(bool); + + void widthChanged(int); + void heightChanged(int); + void sizeChanged(const QSize &size); + void paletteChanged(const QPalette &palette); + void adjacentScreenEdgesChanged(Qt::Edges edges); + + void hasApplicationMenuChanged(bool); + void applicationMenuActiveChanged(bool); + +private: + friend class Decoration; + DecoratedClient(Decoration *parent, DecorationBridge *bridge); + const std::unique_ptr d; +}; + +} // namespace diff --git a/src/decoration.cpp b/src/decoration.cpp new file mode 100644 index 0000000..7178e0c --- /dev/null +++ b/src/decoration.cpp @@ -0,0 +1,497 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "decoration.h" +#include "decoratedclient.h" +#include "decoration_p.h" +#include "decorationbutton.h" +#include "decorationsettings.h" +#include "private/decoratedclientprivate.h" +#include "private/decorationbridge.h" + +#include +#include + +#include + +namespace KDecoration2 +{ +namespace +{ +DecorationBridge *findBridge(const QVariantList &args) +{ + for (const auto &arg : args) { + if (auto bridge = arg.toMap().value(QStringLiteral("bridge")).value()) { + return bridge; + } + } + Q_UNREACHABLE(); +} +} + +Decoration::Private::Private(Decoration *deco, const QVariantList &args) + : sectionUnderMouse(Qt::NoSection) + , bridge(findBridge(args)) + , client(std::shared_ptr(new DecoratedClient(deco, bridge))) + , opaque(false) + , q(deco) +{ +} + +void Decoration::Private::setSectionUnderMouse(Qt::WindowFrameSection section) +{ + if (sectionUnderMouse == section) { + return; + } + sectionUnderMouse = section; + Q_EMIT q->sectionUnderMouseChanged(sectionUnderMouse); +} + +void Decoration::Private::updateSectionUnderMouse(const QPoint &mousePosition) +{ + if (titleBar.contains(mousePosition)) { + setSectionUnderMouse(Qt::TitleBarArea); + return; + } + const QSize size = q->size(); + const int corner = 2 * settings->largeSpacing(); + const bool left = mousePosition.x() < borders.left(); + const bool top = mousePosition.y() < borders.top(); + const bool bottom = size.height() - mousePosition.y() <= borders.bottom(); + const bool right = size.width() - mousePosition.x() <= borders.right(); + if (left) { + if (top && mousePosition.y() < titleBar.top() + corner) { + setSectionUnderMouse(Qt::TopLeftSection); + } else if (size.height() - mousePosition.y() <= borders.bottom() + corner && mousePosition.y() > titleBar.bottom()) { + setSectionUnderMouse(Qt::BottomLeftSection); + } else { + setSectionUnderMouse(Qt::LeftSection); + } + return; + } + if (right) { + if (top && mousePosition.y() < titleBar.top() + corner) { + setSectionUnderMouse(Qt::TopRightSection); + } else if (size.height() - mousePosition.y() <= borders.bottom() + corner && mousePosition.y() > titleBar.bottom()) { + setSectionUnderMouse(Qt::BottomRightSection); + } else { + setSectionUnderMouse(Qt::RightSection); + } + return; + } + if (bottom) { + if (mousePosition.y() > titleBar.bottom()) { + if (mousePosition.x() < borders.left() + corner) { + setSectionUnderMouse(Qt::BottomLeftSection); + } else if (size.width() - mousePosition.x() <= borders.right() + corner) { + setSectionUnderMouse(Qt::BottomRightSection); + } else { + setSectionUnderMouse(Qt::BottomSection); + } + } else { + setSectionUnderMouse(Qt::TitleBarArea); + } + return; + } + if (top) { + if (mousePosition.y() < titleBar.top()) { + if (mousePosition.x() < borders.left() + corner) { + setSectionUnderMouse(Qt::TopLeftSection); + } else if (size.width() - mousePosition.x() <= borders.right() + corner) { + setSectionUnderMouse(Qt::TopRightSection); + } else { + setSectionUnderMouse(Qt::TopSection); + } + } else { + setSectionUnderMouse(Qt::TitleBarArea); + } + return; + } + setSectionUnderMouse(Qt::NoSection); +} + +void Decoration::Private::addButton(DecorationButton *button) +{ + Q_ASSERT(!buttons.contains(button)); + buttons << button; + QObject::connect(button, &QObject::destroyed, q, [this](QObject *o) { + auto it = buttons.begin(); + while (it != buttons.end()) { + if (*it == static_cast(o)) { + it = buttons.erase(it); + } else { + it++; + } + } + }); +} + +Decoration::Decoration(QObject *parent, const QVariantList &args) + : QObject(parent) + , d(new Private(this, args)) +{ + connect(this, &Decoration::bordersChanged, this, [this] { + update(); + }); +} + +Decoration::~Decoration() = default; + +DecoratedClient *Decoration::client() const +{ + return d->client.get(); +} + +void Decoration::requestClose() +{ + d->client->d->requestClose(); +} + +void Decoration::requestContextHelp() +{ + d->client->d->requestContextHelp(); +} + +void Decoration::requestMinimize() +{ + d->client->d->requestMinimize(); +} + +void Decoration::requestToggleOnAllDesktops() +{ + d->client->d->requestToggleOnAllDesktops(); +} + +void Decoration::requestToggleShade() +{ + d->client->d->requestToggleShade(); +} + +void Decoration::requestToggleKeepAbove() +{ + d->client->d->requestToggleKeepAbove(); +} + +void Decoration::requestToggleKeepBelow() +{ + d->client->d->requestToggleKeepBelow(); +} + +#if KDECORATIONS2_ENABLE_DEPRECATED_SINCE(5, 21) +void Decoration::requestShowWindowMenu() +{ + requestShowWindowMenu(QRect()); +} +#endif + +void Decoration::requestShowWindowMenu(const QRect &rect) +{ + d->client->d->requestShowWindowMenu(rect); +} + +void Decoration::requestShowToolTip(const QString &text) +{ + d->client->d->requestShowToolTip(text); +} + +void Decoration::requestHideToolTip() +{ + d->client->d->requestHideToolTip(); +} + +void Decoration::requestToggleMaximization(Qt::MouseButtons buttons) +{ + d->client->d->requestToggleMaximization(buttons); +} + +void Decoration::showApplicationMenu(int actionId) +{ + const auto it = std::find_if(d->buttons.constBegin(), d->buttons.constEnd(), [](DecorationButton *button) { + return button->type() == DecorationButtonType::ApplicationMenu; + }); + if (it != d->buttons.constEnd()) { + requestShowApplicationMenu((*it)->geometry().toRect(), actionId); + } +} + +void Decoration::requestShowApplicationMenu(const QRect &rect, int actionId) +{ + if (auto *appMenuEnabledPrivate = dynamic_cast(d->client->d.get())) { + appMenuEnabledPrivate->requestShowApplicationMenu(rect, actionId); + } +} + +void Decoration::setBlurRegion(const QRegion ®ion) +{ + if (d->blurRegion != region) { + d->blurRegion = region; + Q_EMIT blurRegionChanged(); + } +} + +void Decoration::setBorders(const QMargins &borders) +{ + if (d->borders != borders) { + d->borders = borders; + Q_EMIT bordersChanged(); + } +} + +void Decoration::setResizeOnlyBorders(const QMargins &borders) +{ + if (d->resizeOnlyBorders != borders) { + d->resizeOnlyBorders = borders; + Q_EMIT resizeOnlyBordersChanged(); + } +} + +void Decoration::setTitleBar(const QRect &rect) +{ + if (d->titleBar != rect) { + d->titleBar = rect; + Q_EMIT titleBarChanged(); + } +} + +void Decoration::setOpaque(bool opaque) +{ + if (d->opaque != opaque) { + d->opaque = opaque; + Q_EMIT opaqueChanged(opaque); + } +} + +void Decoration::setShadow(const std::shared_ptr &shadow) +{ + if (d->shadow != shadow) { + d->shadow = shadow; + Q_EMIT shadowChanged(shadow); + } +} + +QRegion Decoration::blurRegion() const +{ + return d->blurRegion; +} + +QMargins Decoration::borders() const +{ + return d->borders; +} + +QMargins Decoration::resizeOnlyBorders() const +{ + return d->resizeOnlyBorders; +} + +QRect Decoration::titleBar() const +{ + return d->titleBar; +} + +Qt::WindowFrameSection Decoration::sectionUnderMouse() const +{ + return d->sectionUnderMouse; +} + +std::shared_ptr Decoration::shadow() const +{ + return d->shadow; +} + +bool Decoration::isOpaque() const +{ + return d->opaque; +} + +int Decoration::borderLeft() const +{ + return d->borders.left(); +} + +int Decoration::resizeOnlyBorderLeft() const +{ + return d->resizeOnlyBorders.left(); +} + +int Decoration::borderRight() const +{ + return d->borders.right(); +} + +int Decoration::resizeOnlyBorderRight() const +{ + return d->resizeOnlyBorders.right(); +} + +int Decoration::borderTop() const +{ + return d->borders.top(); +} + +int Decoration::resizeOnlyBorderTop() const +{ + return d->resizeOnlyBorders.top(); +} + +int Decoration::borderBottom() const +{ + return d->borders.bottom(); +} + +int Decoration::resizeOnlyBorderBottom() const +{ + return d->resizeOnlyBorders.bottom(); +} + +QSize Decoration::size() const +{ + const QMargins &b = d->borders; + return QSize(d->client->width() + b.left() + b.right(), // + (d->client->isShaded() ? 0 : d->client->height()) + b.top() + b.bottom()); +} + +QRect Decoration::rect() const +{ + return QRect(QPoint(0, 0), size()); +} + +bool Decoration::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::HoverEnter: + hoverEnterEvent(static_cast(event)); + return true; + case QEvent::HoverLeave: + hoverLeaveEvent(static_cast(event)); + return true; + case QEvent::HoverMove: + hoverMoveEvent(static_cast(event)); + return true; + case QEvent::MouseButtonPress: + mousePressEvent(static_cast(event)); + return true; + case QEvent::MouseButtonRelease: + mouseReleaseEvent(static_cast(event)); + return true; + case QEvent::MouseMove: + mouseMoveEvent(static_cast(event)); + return true; + case QEvent::Wheel: + wheelEvent(static_cast(event)); + return true; + default: + return QObject::event(event); + } +} + +void Decoration::hoverEnterEvent(QHoverEvent *event) +{ + for (DecorationButton *button : d->buttons) { + QCoreApplication::instance()->sendEvent(button, event); + } + auto flooredPos = QPoint(std::floor(event->position().x()), std::floor(event->position().y())); + d->updateSectionUnderMouse(flooredPos); +} + +void Decoration::hoverLeaveEvent(QHoverEvent *event) +{ + for (DecorationButton *button : d->buttons) { + QCoreApplication::instance()->sendEvent(button, event); + } + d->setSectionUnderMouse(Qt::NoSection); +} + +void Decoration::hoverMoveEvent(QHoverEvent *event) +{ + for (DecorationButton *button : d->buttons) { + if (!button->isEnabled() || !button->isVisible()) { + continue; + } + const bool hovered = button->isHovered(); + const bool contains = button->contains(event->position()); + if (!hovered && contains) { + QHoverEvent e(QEvent::HoverEnter, event->position(), event->oldPosF(), event->modifiers()); + QCoreApplication::instance()->sendEvent(button, &e); + } else if (hovered && !contains) { + QHoverEvent e(QEvent::HoverLeave, event->position(), event->oldPosF(), event->modifiers()); + QCoreApplication::instance()->sendEvent(button, &e); + } else if (hovered && contains) { + QCoreApplication::instance()->sendEvent(button, event); + } + } + auto flooredPos = QPoint(std::floor(event->position().x()), std::floor(event->position().y())); + d->updateSectionUnderMouse(flooredPos); +} + +void Decoration::mouseMoveEvent(QMouseEvent *event) +{ + for (DecorationButton *button : d->buttons) { + if (button->isPressed()) { + QCoreApplication::instance()->sendEvent(button, event); + return; + } + } + // not handled, take care ourselves +} + +void Decoration::mousePressEvent(QMouseEvent *event) +{ + for (DecorationButton *button : d->buttons) { + if (button->isHovered()) { + if (button->acceptedButtons().testFlag(event->button())) { + QCoreApplication::instance()->sendEvent(button, event); + } + event->setAccepted(true); + return; + } + } +} + +void Decoration::mouseReleaseEvent(QMouseEvent *event) +{ + for (DecorationButton *button : d->buttons) { + if (button->isPressed() && button->acceptedButtons().testFlag(event->button())) { + QCoreApplication::instance()->sendEvent(button, event); + return; + } + } + // not handled, take care ourselves + d->updateSectionUnderMouse(event->pos()); +} + +void Decoration::wheelEvent(QWheelEvent *event) +{ + for (DecorationButton *button : d->buttons) { + if (button->contains(event->position())) { + QCoreApplication::instance()->sendEvent(button, event); + event->setAccepted(true); + } + } +} + +void Decoration::update(const QRect &r) +{ + Q_EMIT damaged(r.isNull() ? rect() : r); +} + +void Decoration::update() +{ + update(QRect()); +} + +void Decoration::setSettings(const std::shared_ptr &settings) +{ + d->settings = settings; +} + +std::shared_ptr Decoration::settings() const +{ + return d->settings; +} + +} // namespace + +#include "moc_decoration.cpp" diff --git a/src/decoration.h b/src/decoration.h new file mode 100644 index 0000000..45d637c --- /dev/null +++ b/src/decoration.h @@ -0,0 +1,248 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +#include "decorationshadow.h" +#include + +#include +#include +#include + +class QHoverEvent; +class QMouseEvent; +class QPainter; +class QWheelEvent; + +/** + * @brief Framework for creating window decorations. + * + **/ +namespace KDecoration2 +{ +class DecorationPrivate; +class DecoratedClient; +class DecorationButton; +class DecorationSettings; + +/** + * @brief Base class for the Decoration. + * + * To provide a Decoration one needs to inherit from this class. The framework will instantiate + * an instance of the inherited class for each DecoratedClient. + * + * The main tasks of the Decoration is to provide borders around the DecoratedClient. For this + * the Deocration provides border sizes: those should be adjusted depending on the state of the + * DecoratedClient. E.g. commonly a maximized DecoratedClient does not have borders on the side, + * only the title bar. + * + * Whenever the visual representation of the Decoration changes the slot @link Decoration::update @endlink + * should be invoked to request a repaint. The framework will in return invoke the + * @link Decoration::paint @endlink method. This method needs to be implemented by inheriting + * classes. + * + * A Decoration commonly provides buttons for interaction. E.g. a close button to close the + * DecoratedClient. For such actions the Decoration provides slots which should be connected to + * the clicked signals of the buttons. For convenience the framework provides the @link DecorationButton @endlink + * and the @link DecorationButtonGroup @endlink for easier layout. It is not required to use those, + * if one uses different ways to represent the actions one needs to filter the events accordingly. + * + * @see DecoratedClient + * @see DecorationButton + * @see DecorationButtonGroup + **/ +class KDECORATIONS2_EXPORT Decoration : public QObject +{ + Q_OBJECT + Q_PROPERTY(QMargins borders READ borders NOTIFY bordersChanged) + Q_PROPERTY(int borderLeft READ borderLeft NOTIFY bordersChanged) + Q_PROPERTY(int borderRight READ borderRight NOTIFY bordersChanged) + Q_PROPERTY(int borderTop READ borderTop NOTIFY bordersChanged) + Q_PROPERTY(int borderBottom READ borderBottom NOTIFY bordersChanged) + Q_PROPERTY(QMargins resizeOnlyBorders READ resizeOnlyBorders NOTIFY resizeOnlyBordersChanged) + Q_PROPERTY(int resizeOnlyBorderLeft READ resizeOnlyBorderLeft NOTIFY resizeOnlyBordersChanged) + Q_PROPERTY(int resizeOnlyBorderRight READ resizeOnlyBorderRight NOTIFY resizeOnlyBordersChanged) + Q_PROPERTY(int resizeOnlyBorderTop READ resizeOnlyBorderTop NOTIFY resizeOnlyBordersChanged) + Q_PROPERTY(int resizeOnlyBorderBottom READ resizeOnlyBorderBottom NOTIFY resizeOnlyBordersChanged) + /** + * This property denotes the part of the Decoration which is currently under the mouse pointer. + * It gets automatically updated whenever a QMouseEvent or QHoverEvent gets processed. + **/ + Q_PROPERTY(Qt::WindowFrameSection sectionUnderMouse READ sectionUnderMouse NOTIFY sectionUnderMouseChanged) + /** + * The titleBar is the area inside the Decoration containing all controls (e.g. Buttons) + * and the caption. The titleBar is the main interaction area, while all other areas of the + * Decoration are normally used as resize areas. + **/ + Q_PROPERTY(QRect titleBar READ titleBar NOTIFY titleBarChanged) + /** + * Whether the Decoration is fully opaque. By default a Decoration is considered to + * use the alpha channel and this property has the value @c false. But for e.g. a maximized + * DecoratedClient it is possible that the Decoration is fully opaque. In this case the + * Decoration should set this property to @c true. + **/ + Q_PROPERTY(bool opaque READ isOpaque NOTIFY opaqueChanged) +public: + ~Decoration() override; + + /** + * The DecoratedClient for this Decoration. + **/ + DecoratedClient *client() const; + + QMargins borders() const; + int borderLeft() const; + int borderRight() const; + int borderTop() const; + int borderBottom() const; + QMargins resizeOnlyBorders() const; + int resizeOnlyBorderLeft() const; + int resizeOnlyBorderRight() const; + int resizeOnlyBorderTop() const; + int resizeOnlyBorderBottom() const; + Qt::WindowFrameSection sectionUnderMouse() const; + QRect titleBar() const; + bool isOpaque() const; + + /** + * DecorationShadow for this Decoration. It is recommended that multiple Decorations share + * the same DecorationShadow. E.g one DecorationShadow for all inactive Decorations and one + * for the active Decoration. + **/ + std::shared_ptr shadow() const; + + /** + * The decoration's geometry in local coordinates. + * + * Basically the size of the DecoratedClient combined with the borders. + **/ + QRect rect() const; + QSize size() const; + + /** + * The decoration's blur region in local coordinates + */ + QRegion blurRegion() const; + + /** + * Invoked by the framework to set the Settings for this Decoration before + * init is invoked. + * @internal + **/ + void setSettings(const std::shared_ptr &settings); + /** + * @returns The DecorationSettings used for this Decoration. + **/ + std::shared_ptr settings() const; + + /** + * Implement this method in inheriting classes to provide the rendering. + * + * The @p painter is set up to paint on an internal QPaintDevice. The painting is + * implicitly double buffered. + * + * @param painter The painter which needs to be used for rendering + * @param repaintArea The region which needs to be repainted. + **/ + virtual void paint(QPainter *painter, const QRect &repaintArea) = 0; + + bool event(QEvent *event) override; + +public Q_SLOTS: + void requestClose(); + void requestToggleMaximization(Qt::MouseButtons buttons); + void requestMinimize(); + void requestContextHelp(); + void requestToggleOnAllDesktops(); + void requestToggleShade(); + void requestToggleKeepAbove(); + void requestToggleKeepBelow(); + +#if KDECORATIONS2_ENABLE_DEPRECATED_SINCE(5, 21) + /** + * @deprecated + * @see requestShowWindowMenu(const QRect &rect) + */ + KDECORATIONS2_DEPRECATED_VERSION(5, 21, "Use Decoration::requestShowWindowMenu(QRect)") + void requestShowWindowMenu(); +#endif + + /** + * @param rect the location at which to show the window menu + */ + void requestShowWindowMenu(const QRect &rect); + void requestShowToolTip(const QString &text); + void requestHideToolTip(); + + void showApplicationMenu(int actionId); + void requestShowApplicationMenu(const QRect &rect, int actionId); + + void update(const QRect &rect); + void update(); + + /** + * This method gets invoked from the framework once the Decoration is created and + * completely setup. + * + * An inheriting class should override this method and perform all initialization in + * this method instead of the constructor. + * + * @return true if initialization has been successful, + * false otherwise (for example, a QML component could not be loaded) + **/ + virtual bool init() = 0; + +Q_SIGNALS: + void blurRegionChanged(); + void bordersChanged(); + void resizeOnlyBordersChanged(); + void sectionUnderMouseChanged(Qt::WindowFrameSection); + void titleBarChanged(); + void opaqueChanged(bool); + void shadowChanged(const std::shared_ptr &shadow); + void damaged(const QRegion ®ion); + +protected: + /** + * Constructor for the Decoration. + * + * The @p args are used by the decoration framework to pass meta information + * to the Decoration. An inheriting class is supposed to pass the args to the + * parent class. + * + * @param parent The parent of the Decoration + * @param args Additional arguments passed in from the framework + **/ + explicit Decoration(QObject *parent, const QVariantList &args); + void setBorders(const QMargins &borders); + void setResizeOnlyBorders(const QMargins &borders); + void setBlurRegion(const QRegion ®ion); + /** + * An implementation has to invoke this method whenever the area + * containing the controls and caption changes. + * @param rect The new geometry of the titleBar in Decoration coordinates + **/ + void setTitleBar(const QRect &rect); + void setOpaque(bool opaque); + void setShadow(const std::shared_ptr &shadow); + + virtual void hoverEnterEvent(QHoverEvent *event); + virtual void hoverLeaveEvent(QHoverEvent *event); + virtual void hoverMoveEvent(QHoverEvent *event); + virtual void mouseMoveEvent(QMouseEvent *event); + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *event); + virtual void wheelEvent(QWheelEvent *event); + +private: + friend class DecorationButton; + class Private; + std::unique_ptr d; +}; + +} // namespace + +Q_DECLARE_METATYPE(KDecoration2::Decoration *) diff --git a/src/decoration_p.h b/src/decoration_p.h new file mode 100644 index 0000000..b827b43 --- /dev/null +++ b/src/decoration_p.h @@ -0,0 +1,57 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once +#include "decoration.h" + +// +// W A R N I N G +// ------------- +// +// This file is not part of the KDecoration2 API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +namespace KDecoration2 +{ +class Decoration; +class DecorationBridge; +class DecorationButton; +class DecoratedClient; +class DecorationSettings; +class DecorationShadow; + +class Q_DECL_HIDDEN Decoration::Private +{ +public: + Private(Decoration *decoration, const QVariantList &args); + + QMargins borders; + QMargins resizeOnlyBorders; + + Qt::WindowFrameSection sectionUnderMouse; + void setSectionUnderMouse(Qt::WindowFrameSection section); + void updateSectionUnderMouse(const QPoint &mousePosition); + + QRect titleBar; + QRegion blurRegion; + + void addButton(DecorationButton *button); + + std::shared_ptr settings; + DecorationBridge *bridge; + std::shared_ptr client; + bool opaque; + QList buttons; + std::shared_ptr shadow; + +private: + Decoration *q; +}; + +} // namespace diff --git a/src/decorationbutton.cpp b/src/decorationbutton.cpp new file mode 100644 index 0000000..294ba99 --- /dev/null +++ b/src/decorationbutton.cpp @@ -0,0 +1,601 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "decorationbutton.h" +#include "decoratedclient.h" +#include "decoration.h" +#include "decoration_p.h" +#include "decorationbutton_p.h" +#include "decorationsettings.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#ifndef K_DOXYGEN +size_t qHash(const KDecoration2::DecorationButtonType &type, size_t seed) +{ + return qHash(uint(type), seed); +} +#endif + +namespace KDecoration2 +{ + +DecorationButton::Private::Private(DecorationButtonType type, const QPointer &decoration, DecorationButton *parent) + : decoration(decoration) + , type(type) + , hovered(false) + , enabled(true) + , checkable(false) + , checked(false) + , visible(true) + , acceptedButtons(Qt::LeftButton) + , doubleClickEnabled(false) + , pressAndHold(false) + , q(parent) + , m_pressed(Qt::NoButton) +{ + init(); +} + +DecorationButton::Private::~Private() = default; + +void DecorationButton::Private::init() +{ + auto c = decoration->client(); + auto settings = decoration->settings(); + switch (type) { + case DecorationButtonType::Menu: + QObject::connect( + q, + &DecorationButton::clicked, + decoration.data(), + [this](Qt::MouseButton button) { + Q_UNUSED(button) + decoration->requestShowWindowMenu(q->geometry().toRect()); + }, + Qt::QueuedConnection); + QObject::connect(q, &DecorationButton::doubleClicked, decoration.data(), &Decoration::requestClose, Qt::QueuedConnection); + QObject::connect( + settings.get(), + &DecorationSettings::closeOnDoubleClickOnMenuChanged, + q, + [this](bool enabled) { + doubleClickEnabled = enabled; + setPressAndHold(enabled); + }, + Qt::QueuedConnection); + doubleClickEnabled = settings->isCloseOnDoubleClickOnMenu(); + setPressAndHold(settings->isCloseOnDoubleClickOnMenu()); + setAcceptedButtons(Qt::LeftButton | Qt::RightButton); + break; + case DecorationButtonType::ApplicationMenu: + setVisible(c->hasApplicationMenu()); + setCheckable(true); // will be "checked" whilst the menu is opened + // FIXME TODO connect directly and figure out the button geometry/offset stuff + QObject::connect( + q, + &DecorationButton::clicked, + decoration.data(), + [this] { + decoration->requestShowApplicationMenu(q->geometry().toRect(), 0 /* actionId */); + }, + Qt::QueuedConnection); //&Decoration::requestShowApplicationMenu, Qt::QueuedConnection); + QObject::connect(c, &DecoratedClient::hasApplicationMenuChanged, q, &DecorationButton::setVisible); + QObject::connect(c, &DecoratedClient::applicationMenuActiveChanged, q, &DecorationButton::setChecked); + break; + case DecorationButtonType::OnAllDesktops: + setVisible(settings->isOnAllDesktopsAvailable()); + setCheckable(true); + setChecked(c->isOnAllDesktops()); + QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestToggleOnAllDesktops, Qt::QueuedConnection); + QObject::connect(settings.get(), &DecorationSettings::onAllDesktopsAvailableChanged, q, &DecorationButton::setVisible); + QObject::connect(c, &DecoratedClient::onAllDesktopsChanged, q, &DecorationButton::setChecked); + break; + case DecorationButtonType::Minimize: + setEnabled(c->isMinimizeable()); + QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestMinimize, Qt::QueuedConnection); + QObject::connect(c, &DecoratedClient::minimizeableChanged, q, &DecorationButton::setEnabled); + break; + case DecorationButtonType::Maximize: + setEnabled(c->isMaximizeable()); + setCheckable(true); + setChecked(c->isMaximized()); + setAcceptedButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton); + QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestToggleMaximization, Qt::QueuedConnection); + QObject::connect(c, &DecoratedClient::maximizeableChanged, q, &DecorationButton::setEnabled); + QObject::connect(c, &DecoratedClient::maximizedChanged, q, &DecorationButton::setChecked); + break; + case DecorationButtonType::Close: + setEnabled(c->isCloseable()); + QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestClose, Qt::QueuedConnection); + QObject::connect(c, &DecoratedClient::closeableChanged, q, &DecorationButton::setEnabled); + break; + case DecorationButtonType::ContextHelp: + setVisible(c->providesContextHelp()); + QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestContextHelp, Qt::QueuedConnection); + QObject::connect(c, &DecoratedClient::providesContextHelpChanged, q, &DecorationButton::setVisible); + break; + case DecorationButtonType::KeepAbove: + setCheckable(true); + setChecked(c->isKeepAbove()); + QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestToggleKeepAbove, Qt::QueuedConnection); + QObject::connect(c, &DecoratedClient::keepAboveChanged, q, &DecorationButton::setChecked); + break; + case DecorationButtonType::KeepBelow: + setCheckable(true); + setChecked(c->isKeepBelow()); + QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestToggleKeepBelow, Qt::QueuedConnection); + QObject::connect(c, &DecoratedClient::keepBelowChanged, q, &DecorationButton::setChecked); + break; + case DecorationButtonType::Shade: + setEnabled(c->isShadeable()); + setCheckable(true); + setChecked(c->isShaded()); + QObject::connect(q, &DecorationButton::clicked, decoration.data(), &Decoration::requestToggleShade, Qt::QueuedConnection); + QObject::connect(c, &DecoratedClient::shadedChanged, q, &DecorationButton::setChecked); + QObject::connect(c, &DecoratedClient::shadeableChanged, q, &DecorationButton::setEnabled); + break; + case DecorationButtonType::Spacer: + setEnabled(false); + break; + default: + // nothing + break; + } +} + +void DecorationButton::Private::setHovered(bool set) +{ + if (hovered == set) { + return; + } + hovered = set; + Q_EMIT q->hoveredChanged(hovered); +} + +void DecorationButton::Private::setEnabled(bool set) +{ + if (enabled == set) { + return; + } + enabled = set; + Q_EMIT q->enabledChanged(enabled); + if (!enabled) { + setHovered(false); + if (isPressed()) { + m_pressed = Qt::NoButton; + Q_EMIT q->pressedChanged(false); + } + } +} + +void DecorationButton::Private::setVisible(bool set) +{ + if (visible == set) { + return; + } + visible = set; + Q_EMIT q->visibilityChanged(set); + if (!visible) { + setHovered(false); + if (isPressed()) { + m_pressed = Qt::NoButton; + Q_EMIT q->pressedChanged(false); + } + } +} + +void DecorationButton::Private::setChecked(bool set) +{ + if (!checkable || checked == set) { + return; + } + checked = set; + Q_EMIT q->checkedChanged(checked); +} + +void DecorationButton::Private::setCheckable(bool set) +{ + if (checkable == set) { + return; + } + if (!set) { + setChecked(false); + } + checkable = set; + Q_EMIT q->checkableChanged(checkable); +} + +void DecorationButton::Private::setPressed(Qt::MouseButton button, bool pressed) +{ + if (pressed) { + m_pressed = m_pressed | button; + } else { + m_pressed = m_pressed & ~button; + } + Q_EMIT q->pressedChanged(isPressed()); +} + +void DecorationButton::Private::setAcceptedButtons(Qt::MouseButtons buttons) +{ + if (acceptedButtons == buttons) { + return; + } + acceptedButtons = buttons; + Q_EMIT q->acceptedButtonsChanged(acceptedButtons); +} + +void DecorationButton::Private::startDoubleClickTimer() +{ + if (!doubleClickEnabled) { + return; + } + if (!m_doubleClickTimer) { + m_doubleClickTimer = std::make_unique(); + } + m_doubleClickTimer->start(); +} + +void DecorationButton::Private::invalidateDoubleClickTimer() +{ + if (!m_doubleClickTimer) { + return; + } + m_doubleClickTimer->invalidate(); +} + +bool DecorationButton::Private::wasDoubleClick() const +{ + if (!m_doubleClickTimer || !m_doubleClickTimer->isValid()) { + return false; + } + return !m_doubleClickTimer->hasExpired(QGuiApplication::styleHints()->mouseDoubleClickInterval()); +} + +void DecorationButton::Private::setPressAndHold(bool enable) +{ + if (pressAndHold == enable) { + return; + } + pressAndHold = enable; + if (!pressAndHold) { + m_pressAndHoldTimer.reset(); + } +} + +void DecorationButton::Private::startPressAndHold() +{ + if (!pressAndHold) { + return; + } + if (!m_pressAndHoldTimer) { + m_pressAndHoldTimer.reset(new QTimer()); + m_pressAndHoldTimer->setSingleShot(true); + QObject::connect(m_pressAndHoldTimer.get(), &QTimer::timeout, q, [this]() { + q->clicked(Qt::LeftButton); + }); + } + m_pressAndHoldTimer->start(QGuiApplication::styleHints()->mousePressAndHoldInterval()); +} + +void DecorationButton::Private::stopPressAndHold() +{ + if (m_pressAndHoldTimer) { + m_pressAndHoldTimer->stop(); + } +} + +QString DecorationButton::Private::typeToString(DecorationButtonType type) +{ + switch (type) { + case DecorationButtonType::Menu: + return i18n("More actions for this window"); + case DecorationButtonType::ApplicationMenu: + return i18n("Application menu"); + case DecorationButtonType::OnAllDesktops: + if (this->q->isChecked()) + return i18n("On one desktop"); + else + return i18n("On all desktops"); + case DecorationButtonType::Minimize: + return i18n("Minimize"); + case DecorationButtonType::Maximize: + if (this->q->isChecked()) + return i18n("Restore"); + else + return i18n("Maximize"); + case DecorationButtonType::Close: + return i18n("Close"); + case DecorationButtonType::ContextHelp: + return i18n("Context help"); + case DecorationButtonType::Shade: + if (this->q->isChecked()) + return i18n("Unshade"); + else + return i18n("Shade"); + case DecorationButtonType::KeepBelow: + if (this->q->isChecked()) + return i18n("Don't keep below other windows"); + else + return i18n("Keep below other windows"); + case DecorationButtonType::KeepAbove: + if (this->q->isChecked()) + return i18n("Don't keep above other windows"); + else + return i18n("Keep above other windows"); + default: + return QString(); + } +} + +DecorationButton::DecorationButton(DecorationButtonType type, Decoration *decoration, QObject *parent) + : QObject(parent) + , d(new Private(type, decoration, this)) +{ + decoration->d->addButton(this); + connect(this, &DecorationButton::geometryChanged, this, static_cast(&DecorationButton::update)); + auto updateSlot = static_cast(&DecorationButton::update); + connect(this, &DecorationButton::hoveredChanged, this, updateSlot); + connect(this, &DecorationButton::hoveredChanged, this, [this](bool hovered) { + if (hovered) { + // TODO: show tooltip if hovered and hide if not + const QString type = this->d->typeToString(this->type()); + this->decoration()->requestShowToolTip(type); + } else { + this->decoration()->requestHideToolTip(); + } + }); + connect(this, &DecorationButton::pressedChanged, this, updateSlot); + connect(this, &DecorationButton::pressedChanged, this, [this](bool pressed) { + if (pressed) { + this->decoration()->requestHideToolTip(); + } + }); + connect(this, &DecorationButton::checkedChanged, this, updateSlot); + connect(this, &DecorationButton::enabledChanged, this, updateSlot); + connect(this, &DecorationButton::visibilityChanged, this, updateSlot); + connect(this, &DecorationButton::hoveredChanged, this, [this](bool hovered) { + if (hovered) { + Q_EMIT pointerEntered(); + } else { + Q_EMIT pointerLeft(); + } + }); + connect(this, &DecorationButton::pressedChanged, this, [this](bool p) { + if (p) { + Q_EMIT pressed(); + } else { + Q_EMIT released(); + } + }); +} + +DecorationButton::~DecorationButton() = default; + +void DecorationButton::update(const QRectF &rect) +{ + decoration()->update(rect.isNull() ? geometry().toRect() : rect.toRect()); +} + +void DecorationButton::update() +{ + update(QRectF()); +} + +QSizeF DecorationButton::size() const +{ + return d->geometry.size(); +} + +bool DecorationButton::isPressed() const +{ + return d->isPressed(); +} + +bool DecorationButton::isHovered() const +{ + return d->hovered; +} + +bool DecorationButton::isEnabled() const +{ + return d->enabled; +} + +bool DecorationButton::isChecked() const +{ + return d->checked; +} + +bool DecorationButton::isCheckable() const +{ + return d->checkable; +} + +bool DecorationButton::isVisible() const +{ + return d->visible; +} + +QRectF DecorationButton::geometry() const +{ + return d->geometry; +} + +Decoration *DecorationButton::decoration() const +{ + return d->decoration; +} + +Qt::MouseButtons DecorationButton::acceptedButtons() const +{ + return d->acceptedButtons; +} + +DecorationButtonType DecorationButton::type() const +{ + return d->type; +} + +void DecorationButton::setAcceptedButtons(Qt::MouseButtons value) +{ + d->setAcceptedButtons(value); +} + +void DecorationButton::setEnabled(bool value) +{ + d->setEnabled(value); +} + +void DecorationButton::setChecked(bool value) +{ + d->setChecked(value); +} + +void DecorationButton::setCheckable(bool value) +{ + d->setCheckable(value); +} + +void DecorationButton::setVisible(bool value) +{ + d->setVisible(value); +} + +void DecorationButton::setGeometry(const QRectF &geometry) +{ + if (d->geometry == geometry) { + return; + } + d->geometry = geometry; + Q_EMIT geometryChanged(d->geometry); +} + +bool DecorationButton::contains(const QPointF &pos) const +{ + auto flooredPoint = QPoint(std::floor(pos.x()), std::floor(pos.y())); + return d->geometry.toRect().contains(flooredPoint); +} + +bool DecorationButton::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::HoverEnter: + hoverEnterEvent(static_cast(event)); + return true; + case QEvent::HoverLeave: + hoverLeaveEvent(static_cast(event)); + return true; + case QEvent::HoverMove: + hoverMoveEvent(static_cast(event)); + return true; + case QEvent::MouseButtonPress: + mousePressEvent(static_cast(event)); + return true; + case QEvent::MouseButtonRelease: + mouseReleaseEvent(static_cast(event)); + return true; + case QEvent::MouseMove: + mouseMoveEvent(static_cast(event)); + return true; + case QEvent::Wheel: + wheelEvent(static_cast(event)); + return true; + default: + return QObject::event(event); + } +} + +void DecorationButton::hoverEnterEvent(QHoverEvent *event) +{ + if (!d->enabled || !d->visible || !contains(event->position())) { + return; + } + d->setHovered(true); + event->setAccepted(true); +} + +void DecorationButton::hoverLeaveEvent(QHoverEvent *event) +{ + if (!d->enabled || !d->visible || !d->hovered || contains(event->position())) { + return; + } + d->setHovered(false); + event->setAccepted(true); +} + +void DecorationButton::hoverMoveEvent(QHoverEvent *event) +{ + Q_UNUSED(event) +} + +void DecorationButton::mouseMoveEvent(QMouseEvent *event) +{ + if (!d->enabled || !d->visible || !d->hovered) { + return; + } + if (!contains(event->position())) { + d->setHovered(false); + event->setAccepted(true); + } +} + +void DecorationButton::mousePressEvent(QMouseEvent *event) +{ + if (!d->enabled || !d->visible || !contains(event->position()) || !d->acceptedButtons.testFlag(event->button())) { + return; + } + d->setPressed(event->button(), true); + event->setAccepted(true); + if (d->doubleClickEnabled && event->button() == Qt::LeftButton) { + // check for double click + if (d->wasDoubleClick()) { + event->setAccepted(true); + Q_EMIT doubleClicked(); + } + d->invalidateDoubleClickTimer(); + } + if (d->pressAndHold && event->button() == Qt::LeftButton) { + d->startPressAndHold(); + } +} + +void DecorationButton::mouseReleaseEvent(QMouseEvent *event) +{ + if (!d->enabled || !d->visible || !d->isPressed(event->button())) { + return; + } + if (contains(event->position())) { + if (!d->pressAndHold || event->button() != Qt::LeftButton) { + Q_EMIT clicked(event->button()); + } else { + d->stopPressAndHold(); + } + } + d->setPressed(event->button(), false); + event->setAccepted(true); + + if (d->doubleClickEnabled && event->button() == Qt::LeftButton) { + d->startDoubleClickTimer(); + } +} + +void DecorationButton::wheelEvent(QWheelEvent *event) +{ + Q_UNUSED(event) +} + +} + +#include "moc_decorationbutton.cpp" diff --git a/src/decorationbutton.h b/src/decorationbutton.h new file mode 100644 index 0000000..96fd480 --- /dev/null +++ b/src/decorationbutton.h @@ -0,0 +1,179 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +#include "decorationdefines.h" +#include + +#include +#include + +class QHoverEvent; +class QMouseEvent; +class QPainter; +class QWheelEvent; + +namespace KDecoration2 +{ +class DecorationButtonPrivate; +class Decoration; + +/** + * @brief A button to be used in a Decoration. + * + * The DecorationButton is a simple Button which can be used (but doesn't have to) in a Decoration. + * It takes care of the input handling and triggers the correct state change methods on the + * Decoration. + * + * This simplifies the handling of DecorationButtons. A Decoration implementation just needs to + * subclass DecorationButton and implement the paint method. Everything else is handled by the + * DecorationButton. + * + * For positioning the DecorationButtons it's recommended to use a DecorationButtonGroup. + * + * @see Decoration + * @see DecorationButtonGroup + **/ +class KDECORATIONS2_EXPORT DecorationButton : public QObject +{ + Q_OBJECT + /** + * Whether the DecorationButton is visible. By default this is @c true, OnAllDesktops and + * QuickHelp depend on the DecoratedClient's state. + **/ + Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibilityChanged) + /** + * Whether the DecorationButton is currently pressed. + **/ + Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged) + /** + * Whether the DecorationButton is currently hovered. + **/ + Q_PROPERTY(bool hovered READ isHovered NOTIFY hoveredChanged) + /** + * Whether the DecorationButton is enabled. Only an enabled button accepts hover and mouse + * press events. + **/ + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) + /** + * Whether the DecorationButton can be checked. This is used for state aware DecorationButtons + * like Maximize, Shade, KeepAbove, KeepBelow and OnAllDesktops. + **/ + Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY checkableChanged) + /** + * Whether the DecorationButton is checked. A DecorationButton can only be checked if the + * DecorationButton is checkable. Note: the checked state is not changed by clicking the + * DecorationButton. It gets changed if the DecoratedClient changes it's state, though. + **/ + Q_PROPERTY(bool checked READ isChecked WRITE setChecked NOTIFY checkedChanged) + /** + * The geometry of the DecorationButton in Decoration-local coordinates. + **/ + Q_PROPERTY(QRectF geometry READ geometry NOTIFY geometryChanged) + /** + * The mouse buttons the DecorationButton accepts. By default the Qt::LeftButton gets accepted, + * for some types more buttons are accepted. + **/ + Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY acceptedButtonsChanged) +public: + ~DecorationButton() override; + + QRectF geometry() const; + QSizeF size() const; + void setGeometry(const QRectF &geometry); + + bool isVisible() const; + bool isPressed() const; + bool isHovered() const; + bool isEnabled() const; + bool isChecked() const; + bool isCheckable() const; + DecorationButtonType type() const; + + /** + * Returns @c true if @p pos is inside of the button, otherwise returns @c false. + **/ + bool contains(const QPointF &pos) const; + + Qt::MouseButtons acceptedButtons() const; + void setAcceptedButtons(Qt::MouseButtons buttons); + + /** + * Invoked for painting this DecorationButtons. Implementing sub-classes need to implement + * this method. The coordinate system of the QPainter is set to Decoration coordinates. + * + * This method will be invoked from the rendering thread. + * + * @param painter The QPainter to paint this DecorationButton. + * @param repaintArea The area which is going to be repainted in Decoration coordinates + **/ + virtual void paint(QPainter *painter, const QRect &repaintArea) = 0; + + Decoration *decoration() const; + + bool event(QEvent *event) override; + +public Q_SLOTS: + void setEnabled(bool enabled); + void setCheckable(bool checkable); + void setChecked(bool checked); + void setVisible(bool visible); + + /** + * Schedules a repaint of the DecorationButton. + * Calling update will eventually result in paint being invoked. + * + * @param rect The area to repaint in Decoration local coordinates, a null QRect updates the complete geometry + * @see paint + **/ + void update(const QRectF &rect); + /** + * Schedules a repaint of the DecorationButton. + * + * Overloaded method for convenience. + **/ + void update(); + +Q_SIGNALS: + void clicked(Qt::MouseButton); + void pressed(); + void released(); + void pointerEntered(); + void pointerLeft(); + void doubleClicked(); + + void pressedChanged(bool); + void hoveredChanged(bool); + void enabledChanged(bool); + void checkableChanged(bool); + void checkedChanged(bool); + void geometryChanged(const QRectF &); + void acceptedButtonsChanged(Qt::MouseButtons); + void visibilityChanged(bool); + +protected: + explicit DecorationButton(DecorationButtonType type, Decoration *decoration, QObject *parent = nullptr); + + virtual void hoverEnterEvent(QHoverEvent *event); + virtual void hoverLeaveEvent(QHoverEvent *event); + virtual void hoverMoveEvent(QHoverEvent *event); + virtual void mouseMoveEvent(QMouseEvent *event); + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *event); + virtual void wheelEvent(QWheelEvent *event); + +private: + class Private; + std::unique_ptr d; +}; + +} // namespace + +#ifndef K_DOXYGEN +size_t KDECORATIONS2_EXPORT qHash(const KDecoration2::DecorationButtonType &type, size_t seed = 0); +#endif + +Q_DECLARE_METATYPE(KDecoration2::DecorationButtonType) diff --git a/src/decorationbutton_p.h b/src/decorationbutton_p.h new file mode 100644 index 0000000..5ceeaaf --- /dev/null +++ b/src/decorationbutton_p.h @@ -0,0 +1,79 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +#include "decorationbutton.h" + +#include + +class QElapsedTimer; +class QTimer; + +// +// W A R N I N G +// ------------- +// +// This file is not part of the KDecoration2 API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +namespace KDecoration2 +{ +class Q_DECL_HIDDEN DecorationButton::Private +{ +public: + explicit Private(DecorationButtonType type, const QPointer &decoration, DecorationButton *parent); + ~Private(); + + bool isPressed() const + { + return m_pressed != Qt::NoButton; + } + bool isPressed(Qt::MouseButton button) const + { + return m_pressed.testFlag(button); + } + + void setHovered(bool hovered); + void setPressed(Qt::MouseButton, bool pressed); + void setAcceptedButtons(Qt::MouseButtons buttons); + void setEnabled(bool enabled); + void setChecked(bool checked); + void setCheckable(bool checkable); + void setVisible(bool visible); + void startDoubleClickTimer(); + void invalidateDoubleClickTimer(); + bool wasDoubleClick() const; + void setPressAndHold(bool enable); + void startPressAndHold(); + void stopPressAndHold(); + + QString typeToString(DecorationButtonType type); + + QPointer decoration; + DecorationButtonType type; + QRectF geometry; + bool hovered; + bool enabled; + bool checkable; + bool checked; + bool visible; + Qt::MouseButtons acceptedButtons; + bool doubleClickEnabled; + bool pressAndHold; + +private: + void init(); + DecorationButton *q; + Qt::MouseButtons m_pressed; + std::unique_ptr m_doubleClickTimer; + std::unique_ptr m_pressAndHoldTimer; +}; + +} diff --git a/src/decorationbuttongroup.cpp b/src/decorationbuttongroup.cpp new file mode 100644 index 0000000..8cc8ac1 --- /dev/null +++ b/src/decorationbuttongroup.cpp @@ -0,0 +1,244 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "decorationbuttongroup.h" +#include "decoration.h" +#include "decorationbuttongroup_p.h" +#include "decorationsettings.h" + +#include +#include + +namespace KDecoration2 +{ +DecorationButtonGroup::Private::Private(Decoration *decoration, DecorationButtonGroup *parent) + : decoration(decoration) + , spacing(0.0) + , q(parent) +{ +} + +DecorationButtonGroup::Private::~Private() = default; + +void DecorationButtonGroup::Private::setGeometry(const QRectF &geo) +{ + if (geometry == geo) { + return; + } + geometry = geo; + Q_EMIT q->geometryChanged(geometry); +} + +namespace +{ +static bool s_layoutRecursion = false; +} + +void DecorationButtonGroup::Private::updateLayout() +{ + if (s_layoutRecursion) { + return; + } + s_layoutRecursion = true; + const QPointF &pos = geometry.topLeft(); + // first calculate new size + qreal height = 0; + qreal width = 0; + for (auto it = buttons.constBegin(); it != buttons.constEnd(); ++it) { + if (!(*it)->isVisible()) { + continue; + } + height = qMax(height, qreal((*it)->size().height())); + width += (*it)->size().width(); + if (it + 1 != buttons.constEnd()) { + width += spacing; + } + } + setGeometry(QRectF(pos, QSizeF(width, height))); + + QGuiApplication* app = qobject_cast(QCoreApplication::instance()); + const auto layoutDirection = app ? app->layoutDirection() : Qt::LeftToRight; + + qreal leftPosition = pos.x(); + qreal rightPosition = pos.x() + width; + + if (layoutDirection == Qt::LeftToRight) + for (auto button : std::as_const(buttons)) { + if (!button->isVisible()) { + continue; + } + const auto size = button->size(); + const auto buttonPos = QPointF(leftPosition, pos.y()); + button->setGeometry(QRectF(buttonPos, size)); + leftPosition += size.width() + spacing; + } + else if (layoutDirection == Qt::RightToLeft) + for (auto button : std::as_const(buttons)) { + if (!button->isVisible()) { + continue; + } + const auto size = button->size(); + const auto buttonPos = QPointF(rightPosition - size.width(), pos.y()); + button->setGeometry(QRectF(buttonPos, size)); + rightPosition -= size.width() + spacing; + } + else { + qCritical() << "There's an unhandled layout direction! This is likely an issue of KDecoration2 not being updated to handle it\n" + << "or the application having an invalid layout direction set. Either way, this is a critical bug."; + } + + s_layoutRecursion = false; +} + +DecorationButtonGroup::DecorationButtonGroup(Decoration *parent) + : QObject(parent) + , d(new Private(parent, this)) +{ +} + +DecorationButtonGroup::DecorationButtonGroup(DecorationButtonGroup::Position type, + Decoration *parent, + std::function buttonCreator) + : QObject(parent) + , d(new Private(parent, this)) +{ + auto createButtons = [this, buttonCreator, type] { + const Qt::LayoutDirection layoutDirection = QGuiApplication::layoutDirection(); + const DecorationSettings *settings = d->decoration->settings().get(); + const auto &buttons = + (type == Position::Left) ? + (layoutDirection == Qt::LeftToRight ? settings->decorationButtonsLeft() : settings->decorationButtonsRight()) : + (layoutDirection == Qt::LeftToRight ? settings->decorationButtonsRight() : settings->decorationButtonsLeft()); + for (DecorationButtonType type : buttons) { + if (DecorationButton *b = buttonCreator(type, d->decoration, this)) { + addButton(b); + } + } + }; + createButtons(); + auto changed = type == Position::Left ? &DecorationSettings::decorationButtonsLeftChanged : &DecorationSettings::decorationButtonsRightChanged; + connect(parent->settings().get(), changed, this, [this, createButtons] { + qDeleteAll(d->buttons); + d->buttons.clear(); + createButtons(); + }); +} + +DecorationButtonGroup::~DecorationButtonGroup() = default; + +Decoration *DecorationButtonGroup::decoration() const +{ + return d->decoration; +} + +QRectF DecorationButtonGroup::geometry() const +{ + return d->geometry; +} + +bool DecorationButtonGroup::hasButton(DecorationButtonType type) const +{ + // TODO: check for deletion of button + auto it = std::find_if(d->buttons.begin(), d->buttons.end(), [type](DecorationButton *button) { + return button->type() == type; + }); + return it != d->buttons.end(); +} + +qreal DecorationButtonGroup::spacing() const +{ + return d->spacing; +} + +QPointF DecorationButtonGroup::pos() const +{ + return d->geometry.topLeft(); +} + +void DecorationButtonGroup::setPos(const QPointF &pos) +{ + if (d->geometry.topLeft() == pos) { + return; + } + d->setGeometry(QRectF(pos, d->geometry.size())); + d->updateLayout(); +} + +void DecorationButtonGroup::setSpacing(qreal spacing) +{ + if (d->spacing == spacing) { + return; + } + d->spacing = spacing; + Q_EMIT spacingChanged(d->spacing); + d->updateLayout(); +} + +void DecorationButtonGroup::addButton(DecorationButton *button) +{ + Q_ASSERT(button); + connect(button, &DecorationButton::visibilityChanged, this, [this]() { + d->updateLayout(); + }); + connect(button, &DecorationButton::geometryChanged, this, [this]() { + d->updateLayout(); + }); + d->buttons.append(button); + d->updateLayout(); +} + +QList DecorationButtonGroup::buttons() const +{ + return d->buttons; +} + +void DecorationButtonGroup::removeButton(DecorationButtonType type) +{ + bool needUpdate = false; + auto it = d->buttons.begin(); + while (it != d->buttons.end()) { + if ((*it)->type() == type) { + it = d->buttons.erase(it); + needUpdate = true; + } else { + it++; + } + } + if (needUpdate) { + d->updateLayout(); + } +} + +void DecorationButtonGroup::removeButton(DecorationButton *button) +{ + bool needUpdate = false; + auto it = d->buttons.begin(); + while (it != d->buttons.end()) { + if (*it == button) { + it = d->buttons.erase(it); + needUpdate = true; + } else { + it++; + } + } + if (needUpdate) { + d->updateLayout(); + } +} + +void DecorationButtonGroup::paint(QPainter *painter, const QRect &repaintArea) +{ + const auto &buttons = d->buttons; + for (auto button : buttons) { + if (!button->isVisible()) { + continue; + } + button->paint(painter, repaintArea); + } +} + +} // namespace + +#include "moc_decorationbuttongroup.cpp" diff --git a/src/decorationbuttongroup.h b/src/decorationbuttongroup.h new file mode 100644 index 0000000..f4317ee --- /dev/null +++ b/src/decorationbuttongroup.h @@ -0,0 +1,115 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once +#include "decorationbutton.h" +#include +#include + +class QPainter; + +namespace KDecoration2 +{ +class Decoration; +class DecorationButtonGroupPrivate; + +/** + * @brief Helper class to layout DecorationButton. + * + * A Decoration normally has two groups of DecorationButtons: one left of the caption and one + * right of the caption. The DecorationButtonGroup helps in positioning the DecorationButtons in + * these groups and to update the position of each of the DecorationButtons whenever the state + * changes in a way that they should be repositioned. + * + * A DecorationButtonGroup is a visual layout element not accepting input events. As a visual + * element it provides a paint method allowing a sub class to provide custom painting for the + * DecorationButtonGroup. + **/ +class KDECORATIONS2_EXPORT DecorationButtonGroup : public QObject +{ + Q_OBJECT + /** + * The spacing to use between the DecorationButtons + **/ + Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) + /** + * The geometry of the DecorationButtonGroup in Decoration-local coordinates. + * The size of the DecorationButtonGroup depends on the sizes of the individual + * DecorationButtons and the spacing. + **/ + Q_PROPERTY(QRectF geometry READ geometry NOTIFY geometryChanged) + // TODO: pos must consider whether it's left or right + /** + * The top left Position of the DecorationButtonGroup. This property needs to be + * changed to reposition the DecorationButtonGroup. An update should normally be + * triggered after e.g. a state change like maximization. + **/ + Q_PROPERTY(QPointF pos READ pos WRITE setPos NOTIFY posChanged) +public: + enum class Position { + Left, + Right, + }; + explicit DecorationButtonGroup(Position type, + Decoration *parent, + std::function buttonCreator); + explicit DecorationButtonGroup(Decoration *parent); + ~DecorationButtonGroup() override; + + /** + * Paints the DecorationButtonGroup. This method should normally be invoked from the + * Decoration's paint method. Base implementation just calls the paint method on each + * of the DecorationButtons. Overwriting sub classes need to either call the base + * implementation or ensure that the DecorationButtons are painted. + * + * @param painter The QPainter which is used to paint this DecorationButtonGroup + * @param repaintArea The area which is going to be repainted in Decoration coordinates + **/ + virtual void paint(QPainter *painter, const QRect &repaintArea); + + Decoration *decoration() const; + + qreal spacing() const; + void setSpacing(qreal spacing); + + QRectF geometry() const; + QPointF pos() const; + void setPos(const QPointF &pos); + + /** + * Adds @p button to the DecorationButtonGroup and triggers a re-layout of all + * DecorationButtons. + **/ + void addButton(DecorationButton *button); + /** + * Removes @p button from the DecorationButtonGroup and triggers a re-layout of all + * DecorationButtons. + **/ + void removeButton(DecorationButton *button); + /** + * Removes all DecorationButtons with @p type from the DecorationButtonGroup and + * triggers a re-layout of all DecorationButtons. + **/ + void removeButton(DecorationButtonType type); + /** + * @returns @c true if the DecorationButtonGroup contains a DecorationButton of @p type + **/ + bool hasButton(DecorationButtonType type) const; + /** + * @returns All DecorationButtons in this DecorationButtonGroup + **/ + QList buttons() const; + +Q_SIGNALS: + void spacingChanged(qreal); + void geometryChanged(const QRectF &); + void posChanged(const QPointF &); + +private: + class Private; + std::unique_ptr d; +}; + +} // namespace diff --git a/src/decorationbuttongroup_p.h b/src/decorationbuttongroup_p.h new file mode 100644 index 0000000..89604ec --- /dev/null +++ b/src/decorationbuttongroup_p.h @@ -0,0 +1,45 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once +#include "decorationbuttongroup.h" + +#include +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the KDecoration2 API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +namespace KDecoration2 +{ +class Decoration; + +class Q_DECL_HIDDEN DecorationButtonGroup::Private +{ +public: + explicit Private(Decoration *decoration, DecorationButtonGroup *parent); + ~Private(); + + void setGeometry(const QRectF &geometry); + void updateLayout(); + + Decoration *decoration; + QRectF geometry; + QList buttons; + qreal spacing; + +private: + DecorationButtonGroup *q; +}; + +} // namespace diff --git a/src/decorationdefines.h b/src/decorationdefines.h new file mode 100644 index 0000000..523c3cc --- /dev/null +++ b/src/decorationdefines.h @@ -0,0 +1,163 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +namespace KDecoration2 +{ +/** + * The DecorationButtonType is a helper type for the DecorationButton. + * A Decoration should provide a DecorationButton for each of the types, + * if it wants to provide further buttons it should use the Custom type. + * The DecorationButton gets configured depending on the type. E.g. the + * Close button gets disabled if the DecoratedClient is not closeable. + **/ +enum class DecorationButtonType { + /** + * The Menu button requests showing the window menu on left or right click. + **/ + Menu, + /** + * The ApplicationMenu button requests showing the application's menu on left or right click. + */ + ApplicationMenu, + /** + * The OnAllDesktops button requests toggling the DecoratedClient's on all desktops state. + * The DecoratedButton is only visible if multiple virtual desktops are available. + **/ + OnAllDesktops, + /** + * The Minimize button requests minimizing the DecoratedClient. The DecorationButton is only + * enabled if the DecoratedClient is minimizeable. + **/ + Minimize, + /** + * The Maximize button requests maximizing the DecoratedClient. The DecorationButton is checkable + * and if the DecoratedClient is maximized the DecorationButton is checked. The DecorationButton + * supports multiple mouse buttons to change horizontal, vertical and overall maximized state. + * + * The DecorationButton is only enabled if the DecoratedClient is maximizeable. + **/ + Maximize, + /** + * The Close button requests closing the DecoratedClient. The DecorationButton is only enabled + * if the DecoratedClient is closeable. + **/ + Close, + /** + * The ContextHelp button requests entering the context help mode. The DecorationButton is only + * visible if the DecoratedClient provides context help. + **/ + ContextHelp, + /** + * The Shade button requests toggling the DecoratedClient's shaded state. The DecoratedButton + * is only enabled if the DecoratedClient is shadeable. + **/ + Shade, + /** + * The KeepBelow button requests toggling the DecoratedClient's keep below state. + **/ + KeepBelow, + /** + * The KeepAbove button requests toggling the DecoratedClient's keep above state. + **/ + KeepAbove, + /** + * The Custom type allows a Decoration to provide custom DecorationButtons. + **/ + Custom, + /** + * The Spacer button provides some space between buttons. + */ + Spacer, +}; + +/** + * Border sizes are a combination of visual and accessibility features. + * Larger borders should be used to increase the non title bar borders to + * make it easier to resize the decoration + **/ +enum class BorderSize { + /** + * Border sizes of all non title bar sides should be set to 0. + **/ + None, + /** + * Border sizes of the sides should be set to 0. Title bar and + * the border on opposite side of the title bar should follow the + * Normal settings. + **/ + NoSides, + /** + * Borders should be smaller than Normal, e.g. a factor of 0.5. + **/ + Tiny, + /** + * The default border size with borders on each side. This should + * be the base for calculating other border sizes. + **/ + Normal, + /** + * Increased border sizes, considered a factor of 1.5. + **/ + Large, + /** + * Increased border sizes, considered a factor of 2.0. + **/ + VeryLarge, + /** + * Increased border sizes, considered a factor of 2.5. + **/ + Huge, + /** + * Increased border sizes, considered a factor of 3.0. + **/ + VeryHuge, + /** + * Increased border sizes, considered a factor of 5.0. + **/ + Oversized, +}; + +/** + * Color groups are used for DecoratedClient::color(). + * @since 5.3 + **/ +enum class ColorGroup { + /** + * Inactive color, used for unfocused windows. + **/ + Inactive, + /** + * Active color, used for focused windows. + **/ + Active, + /** + * Warning color, can only be used with ColorRole::Foreground. If used with other roles, + * a invalid QColor is returned. It can be used for close buttons and is typically red. + **/ + Warning, +}; + +/** + * Color roles are used for DecoratedClient::color(). + * @since 5.3 + **/ +enum class ColorRole { + /** + * The decoration's frame background color. + **/ + Frame, + /** + * The decoration's title bar background color + **/ + TitleBar, + /** + * The decoration's title bar forground color + **/ + Foreground, +}; + +} diff --git a/src/decorationsettings.cpp b/src/decorationsettings.cpp new file mode 100644 index 0000000..f71f25a --- /dev/null +++ b/src/decorationsettings.cpp @@ -0,0 +1,96 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "decorationsettings.h" +#include "private/decorationbridge.h" +#include "private/decorationsettingsprivate.h" + +#include + +namespace KDecoration2 +{ +DecorationSettings::DecorationSettings(DecorationBridge *bridge, QObject *parent) + : QObject(parent) + , d(bridge->settings(this)) +{ + auto updateUnits = [this] { + int gridUnit = QFontMetrics(font()).boundingRect(QLatin1Char('M')).height(); + ; + if (gridUnit % 2 != 0) { + gridUnit++; + } + if (gridUnit != d->gridUnit()) { + d->setGridUnit(gridUnit); + Q_EMIT gridUnitChanged(gridUnit); + } + if (gridUnit != d->largeSpacing()) { + d->setSmallSpacing(qMax(2, (int)(gridUnit / 4))); // 1/4 of gridUnit, at least 2 + d->setLargeSpacing(gridUnit); // msize.height + Q_EMIT spacingChanged(); + } + }; + updateUnits(); + connect(this, &DecorationSettings::fontChanged, this, updateUnits); +} + +DecorationSettings::~DecorationSettings() = default; + +bool DecorationSettings::isOnAllDesktopsAvailable() const +{ + return d->isOnAllDesktopsAvailable(); +} + +bool DecorationSettings::isAlphaChannelSupported() const +{ + return d->isAlphaChannelSupported(); +} + +bool DecorationSettings::isCloseOnDoubleClickOnMenu() const +{ + return d->isCloseOnDoubleClickOnMenu(); +} + +QList DecorationSettings::decorationButtonsLeft() const +{ + return d->decorationButtonsLeft(); +} + +QList DecorationSettings::decorationButtonsRight() const +{ + return d->decorationButtonsRight(); +} + +BorderSize DecorationSettings::borderSize() const +{ + return d->borderSize(); +} + +QFont DecorationSettings::font() const +{ + return d->font(); +} + +QFontMetricsF DecorationSettings::fontMetrics() const +{ + return d->fontMetrics(); +} + +int DecorationSettings::gridUnit() const +{ + return d->gridUnit(); +} + +int DecorationSettings::smallSpacing() const +{ + return d->smallSpacing(); +} + +int DecorationSettings::largeSpacing() const +{ + return d->largeSpacing(); +} +} + +#include "moc_decorationsettings.cpp" diff --git a/src/decorationsettings.h b/src/decorationsettings.h new file mode 100644 index 0000000..bc13e31 --- /dev/null +++ b/src/decorationsettings.h @@ -0,0 +1,132 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +#include "decorationbutton.h" +#include + +#include +#include + +#include + +namespace KDecoration2 +{ +class DecorationBridge; +class DecorationSettingsPrivate; + +/** + * @brief Common settings for the Decoration. + * + * This class gets injected into the Decoration and provides recommendations for the + * Decoration. The Decoration is suggested to honor the settings, but may decide that some + * settings don't fit the design and ignore them. + * + * @see Decoration + **/ +class KDECORATIONS2_EXPORT DecorationSettings : public QObject +{ + Q_OBJECT + /** + * Whether the feature to put a DecoratedClient on all desktops is available. + * + * If this feature is not available a Decoration might decide to not show the + * DecorationButtonType::OnAllDesktops. + **/ + Q_PROPERTY(bool onAllDesktopsAvailable READ isOnAllDesktopsAvailable NOTIFY onAllDesktopsAvailableChanged) + /** + * Whether the Decoration will be rendered with an alpha channel. + * + * If no alpha channel is available a Decoration should not use round borders. + **/ + Q_PROPERTY(bool alphaChannelSupported READ isAlphaChannelSupported NOTIFY alphaChannelSupportedChanged) + /** + * Whether the Decoration should close the DecoratedClient when double clicking on the + * DecorationButtonType::Menu. + **/ + Q_PROPERTY(bool closeOnDoubleClickOnMenu READ isCloseOnDoubleClickOnMenu NOTIFY closeOnDoubleClickOnMenuChanged) + /** + * The suggested ordering of the decoration buttons on the left. + **/ + Q_PROPERTY(QList decorationButtonsLeft READ decorationButtonsLeft NOTIFY decorationButtonsLeftChanged) + /** + * The suggested ordering of the decoration buttons on the right. + **/ + Q_PROPERTY(QList decorationButtonsRight READ decorationButtonsRight NOTIFY decorationButtonsRightChanged) + /** + * The suggested border size. + **/ + Q_PROPERTY(KDecoration2::BorderSize borderSize READ borderSize NOTIFY borderSizeChanged) + /** + * The fundamental unit of space that should be used for sizes, expressed in pixels. + * Given the screen has an accurate DPI settings, it corresponds to a millimeter + */ + Q_PROPERTY(int gridUnit READ gridUnit NOTIFY gridUnitChanged) + /** + * The recommended font for the Decoration's caption. + **/ + Q_PROPERTY(QFont font READ font NOTIFY fontChanged) + /** + * smallSpacing is the amount of spacing that should be used around smaller UI elements, + * for example as spacing in Columns. Internally, this size depends on the size of + * the default font as rendered on the screen, so it takes user-configured font size and DPI + * into account. + */ + Q_PROPERTY(int smallSpacing READ smallSpacing NOTIFY spacingChanged) + + /** + * largeSpacing is the amount of spacing that should be used inside bigger UI elements, + * for example between an icon and the corresponding text. Internally, this size depends on + * the size of the default font as rendered on the screen, so it takes user-configured font + * size and DPI into account. + */ + Q_PROPERTY(int largeSpacing READ largeSpacing NOTIFY spacingChanged) +public: + explicit DecorationSettings(DecorationBridge *bridge, QObject *parent = nullptr); + ~DecorationSettings() override; + bool isOnAllDesktopsAvailable() const; + bool isAlphaChannelSupported() const; + bool isCloseOnDoubleClickOnMenu() const; + QList decorationButtonsLeft() const; + QList decorationButtonsRight() const; + BorderSize borderSize() const; + + QFont font() const; + /** + * The fontMetrics for the recommended font. + * @see font + **/ + QFontMetricsF fontMetrics() const; + + int gridUnit() const; + int smallSpacing() const; + int largeSpacing() const; + +Q_SIGNALS: + void onAllDesktopsAvailableChanged(bool); + void alphaChannelSupportedChanged(bool); + void closeOnDoubleClickOnMenuChanged(bool); + void decorationButtonsLeftChanged(const QList &); + void decorationButtonsRightChanged(const QList &); + void borderSizeChanged(KDecoration2::BorderSize size); + void fontChanged(const QFont &font); + void gridUnitChanged(int); + void spacingChanged(); + + /** + * This signal is emitted when the backend got reconfigured. + * If the plugin uses custom settings, it is recommended to re-read + * them after this signal got emitted. + **/ + void reconfigured(); + +private: + const std::unique_ptr d; +}; + +} + +Q_DECLARE_METATYPE(KDecoration2::BorderSize) diff --git a/src/decorationshadow.cpp b/src/decorationshadow.cpp new file mode 100644 index 0000000..9a3c36d --- /dev/null +++ b/src/decorationshadow.cpp @@ -0,0 +1,173 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "decorationshadow.h" +#include "decorationshadow_p.h" + +namespace KDecoration2 +{ +DecorationShadow::Private::Private(DecorationShadow *parent) + : q(parent) +{ +} + +DecorationShadow::Private::~Private() = default; + +DecorationShadow::DecorationShadow() + : QObject() + , d(new Private(this)) +{ +} + +DecorationShadow::~DecorationShadow() = default; + +QRect DecorationShadow::topLeftGeometry() const +{ + if (d->innerShadowRect.isNull() || d->shadow.isNull()) { + return QRect(); + } + return QRect(0, 0, d->innerShadowRect.left(), d->innerShadowRect.top()); +} + +QRect DecorationShadow::topGeometry() const +{ + if (d->innerShadowRect.isNull() || d->shadow.isNull()) { + return QRect(); + } + return QRect(d->innerShadowRect.left(), 0, d->innerShadowRect.width(), d->innerShadowRect.top()); +} + +QRect DecorationShadow::topRightGeometry() const +{ + if (d->innerShadowRect.isNull() || d->shadow.isNull()) { + return QRect(); + } + return QRect(d->innerShadowRect.left() + d->innerShadowRect.width(), + 0, + d->shadow.width() - d->innerShadowRect.width() - d->innerShadowRect.left(), + d->innerShadowRect.top()); +} + +QRect DecorationShadow::rightGeometry() const +{ + if (d->innerShadowRect.isNull() || d->shadow.isNull()) { + return QRect(); + } + return QRect(d->innerShadowRect.left() + d->innerShadowRect.width(), + d->innerShadowRect.top(), + d->shadow.width() - d->innerShadowRect.width() - d->innerShadowRect.left(), + d->innerShadowRect.height()); +} + +QRect DecorationShadow::bottomRightGeometry() const +{ + if (d->innerShadowRect.isNull() || d->shadow.isNull()) { + return QRect(); + } + return QRect(d->innerShadowRect.left() + d->innerShadowRect.width(), + d->innerShadowRect.top() + d->innerShadowRect.height(), + d->shadow.width() - d->innerShadowRect.width() - d->innerShadowRect.left(), + d->shadow.height() - d->innerShadowRect.top() - d->innerShadowRect.height()); +} + +QRect DecorationShadow::bottomGeometry() const +{ + if (d->innerShadowRect.isNull() || d->shadow.isNull()) { + return QRect(); + } + return QRect(d->innerShadowRect.left(), + d->innerShadowRect.top() + d->innerShadowRect.height(), + d->innerShadowRect.width(), + d->shadow.height() - d->innerShadowRect.top() - d->innerShadowRect.height()); +} + +QRect DecorationShadow::bottomLeftGeometry() const +{ + if (d->innerShadowRect.isNull() || d->shadow.isNull()) { + return QRect(); + } + return QRect(0, + d->innerShadowRect.top() + d->innerShadowRect.height(), + d->innerShadowRect.left(), + d->shadow.height() - d->innerShadowRect.top() - d->innerShadowRect.height()); +} + +QRect DecorationShadow::leftGeometry() const +{ + if (d->innerShadowRect.isNull() || d->shadow.isNull()) { + return QRect(); + } + return QRect(0, d->innerShadowRect.top(), d->innerShadowRect.left(), d->innerShadowRect.height()); +} + +#ifndef K_DOXYGEN + +QImage DecorationShadow::shadow() const +{ + return d->shadow; +} + +QMargins DecorationShadow::padding() const +{ + return d->padding; +} + +QRect DecorationShadow::innerShadowRect() const +{ + return d->innerShadowRect; +} + +int DecorationShadow::paddingTop() const +{ + return d->padding.top(); +} + +int DecorationShadow::paddingBottom() const +{ + return d->padding.bottom(); +} + +int DecorationShadow::paddingRight() const +{ + return d->padding.right(); +} + +int DecorationShadow::paddingLeft() const +{ + return d->padding.left(); +} + +void DecorationShadow::setShadow(const QImage &shadow) +{ + if (d->shadow == shadow) { + return; + } + d->shadow = shadow; + Q_EMIT shadowChanged(d->shadow); +} + +#endif + +void DecorationShadow::setPadding(const QMargins &margins) +{ + if (d->padding == margins) { + return; + } + d->padding = margins; + Q_EMIT paddingChanged(); +} + +void DecorationShadow::setInnerShadowRect(const QRect &rect) +{ + if (d->innerShadowRect == rect) { + return; + } + d->innerShadowRect = rect; + Q_EMIT innerShadowRectChanged(); +} + +} + +#include "moc_decorationshadow.cpp" diff --git a/src/decorationshadow.h b/src/decorationshadow.h new file mode 100644 index 0000000..fb6a3fc --- /dev/null +++ b/src/decorationshadow.h @@ -0,0 +1,128 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +#include + +#include +#include +#include + +namespace KDecoration2 +{ +class DecorationShadowPrivate; + +/** + * @brief A wrapper to define the shadow around the Decoration. + * + * The shadow around the Decoration should not be rendered as part of the Decoration. + * Instead a DecorationShadow should be used. That way a backend can optimize the + * rendering of the shadow in a better way. If the shadow were part of the Decoration + * directly it would need to be updated when the rendering changes. By using a dedicated + * DecorationShadow the same shadow can be shared between multiple DecoratedClients. + * + * The DecorationShadow consists of a shadow QImage which is composed of multiple parts: + * @li topLeft: rendered as it is + * @li top: stretched in x direction + * @li topRight: rendered as it is + * @li right: stretched in y direction + * @li bottomRight: rendered as it is + * @li bottom: stretched in x direction + * @li bottomLeft: rendered as it is + * @li left: stretched in y direction + * + * The sizes of these parts is denoted in the property innerShadowRect and the layout is the + * following: + * ####################################### + * # topLeft # top # topRight # + * ####################################### + * # left # # right # + * ####################################### + * # bottomLeft # bottom # bottomRight # + * ####################################### + * + * The innerShadowRect property is a QRect of the geometry of the areas not covered by any of the + * elements. This means that: + * @li x/y of the rect is the same as the size of the topLeft element + * @li width of the rect is the same as the width of the top and bottom element + * @li height of the rect is the same as the height of the left and the right element + * By that the actual sizes of all elements can be derived out of the size of the shadow image + * and the innerShadowRect. + * + * The position of the rendering depends on the values; + * @li paddingTop + * @li paddingRight + * @li paddingBottom + * @li paddingLeft + * + * The top left element is rendered with an offset of paddingLeft and paddingTop. + * The non-stretched elements are rendered in the size as specified, the area + * between two non-stretched elements (e.g. between topLeft and topRight) is filled + * by the element with one direction stretched and the other direction fixed at the + * corresponding padding value. E.g. the top element is stretched in x direction and + * fixed at paddingTop value. If stretching the side elements is not wanted one needs + * to provide a shadow image with those elements at a size that stretching is not + * required. + * + * If the padding values are smaller than the sizes of the shadow elements the shadow + * will overlap with the Decoration and be rendered behind the Decoration. + * + **/ +class KDECORATIONS2_EXPORT DecorationShadow : public QObject +{ + Q_OBJECT + Q_PROPERTY(QImage shadow READ shadow WRITE setShadow NOTIFY shadowChanged) + Q_PROPERTY(QRect innerShadowRect READ innerShadowRect WRITE setInnerShadowRect NOTIFY innerShadowRectChanged) + Q_PROPERTY(QRect topLeftGeometry READ topLeftGeometry NOTIFY innerShadowRectChanged) + Q_PROPERTY(QRect topGeometry READ topGeometry NOTIFY innerShadowRectChanged) + Q_PROPERTY(QRect topRightGeometry READ topRightGeometry NOTIFY innerShadowRectChanged) + Q_PROPERTY(QRect rightGeometry READ rightGeometry NOTIFY innerShadowRectChanged) + Q_PROPERTY(QRect bottomRightGeometry READ bottomRightGeometry NOTIFY innerShadowRectChanged) + Q_PROPERTY(QRect bottomGeometry READ bottomGeometry NOTIFY innerShadowRectChanged) + Q_PROPERTY(QRect bottomLeftGeometry READ bottomLeftGeometry NOTIFY innerShadowRectChanged) + Q_PROPERTY(QRect leftGeometry READ leftGeometry NOTIFY innerShadowRectChanged) + Q_PROPERTY(int paddingTop READ paddingTop NOTIFY paddingChanged) + Q_PROPERTY(int paddingRight READ paddingRight NOTIFY paddingChanged) + Q_PROPERTY(int paddingBottom READ paddingBottom NOTIFY paddingChanged) + Q_PROPERTY(int paddingLeft READ paddingLeft NOTIFY paddingChanged) + Q_PROPERTY(QMargins padding READ padding WRITE setPadding NOTIFY paddingChanged) +public: + explicit DecorationShadow(); + ~DecorationShadow() override; + + QImage shadow() const; + QRect innerShadowRect() const; + QRect topLeftGeometry() const; + QRect topGeometry() const; + QRect topRightGeometry() const; + QRect rightGeometry() const; + QRect bottomRightGeometry() const; + QRect bottomGeometry() const; + QRect bottomLeftGeometry() const; + QRect leftGeometry() const; + int paddingTop() const; + int paddingRight() const; + int paddingBottom() const; + int paddingLeft() const; + QMargins padding() const; + + void setShadow(const QImage &image); + void setInnerShadowRect(const QRect &rect); + void setPadding(const QMargins &margins); + +Q_SIGNALS: + void shadowChanged(const QImage &); + void innerShadowRectChanged(); + void paddingChanged(); + +private: + class Private; + std::unique_ptr d; +}; + +} + +Q_DECLARE_METATYPE(KDecoration2::DecorationShadow *) diff --git a/src/decorationshadow_p.h b/src/decorationshadow_p.h new file mode 100644 index 0000000..d4b4458 --- /dev/null +++ b/src/decorationshadow_p.h @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +// +// W A R N I N G +// ------------- +// +// This file is not part of the KDecoration2 API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "decorationshadow.h" + +#include + +namespace KDecoration2 +{ +class Q_DECL_HIDDEN DecorationShadow::Private +{ +public: + explicit Private(DecorationShadow *parent); + ~Private(); + QImage shadow; + QRect innerShadowRect; + QMargins padding; + +private: + DecorationShadow *q; +}; + +} diff --git a/src/decorationthemeprovider.cpp b/src/decorationthemeprovider.cpp new file mode 100644 index 0000000..5270020 --- /dev/null +++ b/src/decorationthemeprovider.cpp @@ -0,0 +1,87 @@ +/* + * SPDX-FileCopyrightText: 2021 Alexander Lohnau + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ + +#include "decorationthemeprovider.h" + +class DecorationThemeMetaDataPrivate : public QSharedData +{ +public: + QString visibleName; + QString themeName; + QString configurationName; + QString pluginId; + KDecoration2::BorderSize borderSize = KDecoration2::BorderSize::Normal; +}; + +using namespace KDecoration2; + +DecorationThemeMetaData::DecorationThemeMetaData() + : d(new DecorationThemeMetaDataPrivate()) +{ +} + +DecorationThemeMetaData::~DecorationThemeMetaData() = default; + +QString DecorationThemeMetaData::visibleName() const +{ + return d->visibleName; +} + +void DecorationThemeMetaData::setVisibleName(const QString &name) +{ + d->visibleName = name; +} + +QString DecorationThemeMetaData::themeName() const +{ + return d->themeName; +} + +void DecorationThemeMetaData::setThemeName(const QString &name) +{ + d->themeName = name; +} + +QString DecorationThemeMetaData::configurationName() const +{ + return d->configurationName; +} + +void DecorationThemeMetaData::setConfigurationName(const QString &name) +{ + d->configurationName = name; +} + +void DecorationThemeMetaData::setBorderSize(KDecoration2::BorderSize size) +{ + d->borderSize = size; +} + +KDecoration2::BorderSize DecorationThemeMetaData::borderSize() const +{ + return d->borderSize; +} + +QString DecorationThemeMetaData::pluginId() const +{ + return d->pluginId; +} + +void DecorationThemeMetaData::setPluginId(const QString &id) +{ + d->pluginId = id; +} + +DecorationThemeProvider::DecorationThemeProvider(QObject *parent) + : QObject(parent) +{ +} + +DecorationThemeMetaData::DecorationThemeMetaData(const DecorationThemeMetaData &other) = default; + +DecorationThemeMetaData &DecorationThemeMetaData::operator=(const DecorationThemeMetaData &other) = default; + +#include "moc_decorationthemeprovider.cpp" diff --git a/src/decorationthemeprovider.h b/src/decorationthemeprovider.h new file mode 100644 index 0000000..1f2c90d --- /dev/null +++ b/src/decorationthemeprovider.h @@ -0,0 +1,76 @@ +/* + * SPDX-FileCopyrightText: 2021 Alexander Lohnau + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ + +#pragma once + +#include "decorationdefines.h" +#include +#include +#include + +class KPluginMetaData; +class DecorationThemeMetaDataPrivate; + +namespace KDecoration2 +{ +/** + * Class providing type-safe access to data of themes + * + * @since 5.23 + * @author Alexander Lohnau + */ +class KDECORATIONS2_EXPORT DecorationThemeMetaData +{ +public: + explicit DecorationThemeMetaData(); + virtual ~DecorationThemeMetaData(); + DecorationThemeMetaData(const DecorationThemeMetaData &other); + DecorationThemeMetaData &operator=(const DecorationThemeMetaData &other); + + /// User-visible name of the theme + QString visibleName() const; + void setVisibleName(const QString &name); + + /// Internal name of the theme + QString themeName() const; + void setThemeName(const QString &name); + + /// Name of the kcm to configure the decoration theme + QString configurationName() const; + void setConfigurationName(const QString &name); + + /// Border size of the decoration, this gets set based on the "recommendedBorderSize" key in the json metadata + /// @internal + KDecoration2::BorderSize borderSize() const; + void setBorderSize(KDecoration2::BorderSize size); + + /// plugin id of theme provider + /// @see KPluginMetaData::pluginId + QString pluginId() const; + void setPluginId(const QString &id); + +private: + QSharedDataPointer d; +}; +/** + * Class to give the KWin decorationmodel access to the plugin's themes. + * + * @since 5.23 + * @author Alexander Lohnau + */ +class KDECORATIONS2_EXPORT DecorationThemeProvider : public QObject +{ + Q_OBJECT + +public: + explicit DecorationThemeProvider(QObject *parent); + + /** + * List containing information of supported themes + */ + virtual QList themes() const = 0; +}; +} diff --git a/src/private/CMakeLists.txt b/src/private/CMakeLists.txt new file mode 100644 index 0000000..47a91ef --- /dev/null +++ b/src/private/CMakeLists.txt @@ -0,0 +1,58 @@ +set(libkdecoration2Private_SRCS + decoratedclientprivate.cpp + decoratedclientprivate.h + decorationbridge.cpp + decorationbridge.h + decorationsettingsprivate.cpp + decorationsettingsprivate.h +) + +add_library(kdecorations2private SHARED ${libkdecoration2Private_SRCS}) + +generate_export_header( + kdecorations2private +BASE_NAME + KDECORATIONS_PRIVATE +EXPORT_FILE_NAME + kdecoration2/private/kdecoration2_private_export.h +) + +add_library(KDecoration2::KDecorationPrivate ALIAS kdecorations2private) + +target_link_libraries(kdecorations2private + PUBLIC + Qt::Core + Qt::Gui +) + +target_include_directories(kdecorations2private INTERFACE "$" ) + +set_target_properties(kdecorations2private PROPERTIES VERSION ${KDECORATION2_VERSION} + SOVERSION 11 + EXPORT_NAME KDecoration2Private +) + +ecm_generate_headers(KDecoration2Private_CamelCase_HEADERS + HEADER_NAMES + DecoratedClientPrivate + DecorationBridge + DecorationSettingsPrivate + PREFIX + KDecoration2/Private + REQUIRED_HEADERS KDecoration2Private_HEADERS +) +install(FILES ${KDecoration2Private_CamelCase_HEADERS} + DESTINATION ${KDECORATION2_INCLUDEDIR}/KDecoration2/Private + COMPONENT Devel) + +install(TARGETS kdecorations2private EXPORT KDecoration2Targets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) + +install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/kdecoration2/private/kdecoration2_private_export.h + ${KDecoration2Private_HEADERS} + DESTINATION + ${KDECORATION2_INCLUDEDIR}/kdecoration2/private + COMPONENT + Devel +) diff --git a/src/private/decoratedclientprivate.cpp b/src/private/decoratedclientprivate.cpp new file mode 100644 index 0000000..de895b2 --- /dev/null +++ b/src/private/decoratedclientprivate.cpp @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "decoratedclientprivate.h" + +#include + +namespace KDecoration2 +{ +class Q_DECL_HIDDEN DecoratedClientPrivate::Private +{ +public: + explicit Private(DecoratedClient *client, Decoration *decoration); + DecoratedClient *client; + Decoration *decoration; +}; + +DecoratedClientPrivate::Private::Private(DecoratedClient *client, Decoration *decoration) + : client(client) + , decoration(decoration) +{ +} + +DecoratedClientPrivate::DecoratedClientPrivate(DecoratedClient *client, Decoration *decoration) + : d(new Private(client, decoration)) +{ +} + +DecoratedClientPrivate::~DecoratedClientPrivate() = default; + +Decoration *DecoratedClientPrivate::decoration() +{ + return d->decoration; +} + +Decoration *DecoratedClientPrivate::decoration() const +{ + return d->decoration; +} + +DecoratedClient *DecoratedClientPrivate::client() +{ + return d->client; +} + +QColor DecoratedClientPrivate::color(ColorGroup group, ColorRole role) const +{ + Q_UNUSED(role) + Q_UNUSED(group) + + return QColor(); +} + +ApplicationMenuEnabledDecoratedClientPrivate::ApplicationMenuEnabledDecoratedClientPrivate(DecoratedClient *client, Decoration *decoration) + : DecoratedClientPrivate(client, decoration) +{ +} + +ApplicationMenuEnabledDecoratedClientPrivate::~ApplicationMenuEnabledDecoratedClientPrivate() = default; + +} diff --git a/src/private/decoratedclientprivate.h b/src/private/decoratedclientprivate.h new file mode 100644 index 0000000..7a66dd4 --- /dev/null +++ b/src/private/decoratedclientprivate.h @@ -0,0 +1,105 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +#include "../decorationdefines.h" +#include + +#include +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the KDecoration2 API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +namespace KDecoration2 +{ +class Decoration; +class DecoratedClient; + +class KDECORATIONS_PRIVATE_EXPORT DecoratedClientPrivate +{ +public: + virtual ~DecoratedClientPrivate(); + virtual bool isActive() const = 0; + virtual QString caption() const = 0; + virtual bool isOnAllDesktops() const = 0; + virtual bool isShaded() const = 0; + virtual QIcon icon() const = 0; + virtual bool isMaximized() const = 0; + virtual bool isMaximizedHorizontally() const = 0; + virtual bool isMaximizedVertically() const = 0; + virtual bool isKeepAbove() const = 0; + virtual bool isKeepBelow() const = 0; + + virtual bool isCloseable() const = 0; + virtual bool isMaximizeable() const = 0; + virtual bool isMinimizeable() const = 0; + virtual bool providesContextHelp() const = 0; + virtual bool isModal() const = 0; + virtual bool isShadeable() const = 0; + virtual bool isMoveable() const = 0; + virtual bool isResizeable() const = 0; + + virtual WId windowId() const = 0; + virtual WId decorationId() const = 0; + + virtual int width() const = 0; + virtual int height() const = 0; + virtual QSize size() const = 0; + virtual QPalette palette() const = 0; + virtual Qt::Edges adjacentScreenEdges() const = 0; + + virtual void requestShowToolTip(const QString &text) = 0; + virtual void requestHideToolTip() = 0; + virtual void requestClose() = 0; + virtual void requestToggleMaximization(Qt::MouseButtons buttons) = 0; + virtual void requestMinimize() = 0; + virtual void requestContextHelp() = 0; + virtual void requestToggleOnAllDesktops() = 0; + virtual void requestToggleShade() = 0; + virtual void requestToggleKeepAbove() = 0; + virtual void requestToggleKeepBelow() = 0; + virtual void requestShowWindowMenu(const QRect &rect) = 0; + + Decoration *decoration(); + Decoration *decoration() const; + + virtual QColor color(ColorGroup group, ColorRole role) const; + virtual QString windowClass() const = 0; + +protected: + explicit DecoratedClientPrivate(DecoratedClient *client, Decoration *decoration); + DecoratedClient *client(); + +private: + class Private; + const std::unique_ptr d; +}; + +class KDECORATIONS_PRIVATE_EXPORT ApplicationMenuEnabledDecoratedClientPrivate : public DecoratedClientPrivate +{ +public: + ~ApplicationMenuEnabledDecoratedClientPrivate() override; + + virtual bool hasApplicationMenu() const = 0; + virtual bool isApplicationMenuActive() const = 0; + + virtual void showApplicationMenu(int actionId) = 0; + virtual void requestShowApplicationMenu(const QRect &rect, int actionId) = 0; + +protected: + explicit ApplicationMenuEnabledDecoratedClientPrivate(DecoratedClient *client, Decoration *decoration); +}; + +} // namespace diff --git a/src/private/decorationbridge.cpp b/src/private/decorationbridge.cpp new file mode 100644 index 0000000..d95bb9d --- /dev/null +++ b/src/private/decorationbridge.cpp @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "decorationbridge.h" + +Q_DECLARE_METATYPE(Qt::MouseButton) + +namespace KDecoration2 +{ +DecorationBridge::DecorationBridge(QObject *parent) + : QObject(parent) +{ + qRegisterMetaType(); +} + +DecorationBridge::~DecorationBridge() = default; + +} + +#include "moc_decorationbridge.cpp" diff --git a/src/private/decorationbridge.h b/src/private/decorationbridge.h new file mode 100644 index 0000000..1d0e919 --- /dev/null +++ b/src/private/decorationbridge.h @@ -0,0 +1,50 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +#include + +#include + +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the KDecoration2 API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +class QRect; + +namespace KDecoration2 +{ +class Decoration; +class DecorationSettings; +class DecorationSettingsPrivate; +class DecoratedClient; +class DecoratedClientPrivate; + +class KDECORATIONS_PRIVATE_EXPORT DecorationBridge : public QObject +{ + Q_OBJECT +public: + ~DecorationBridge() override; + + virtual std::unique_ptr createClient(DecoratedClient *client, Decoration *decoration) = 0; + virtual std::unique_ptr settings(DecorationSettings *parent) = 0; + +protected: + explicit DecorationBridge(QObject *parent = nullptr); +}; + +} // namespace + +Q_DECLARE_METATYPE(KDecoration2::DecorationBridge *) diff --git a/src/private/decorationsettingsprivate.cpp b/src/private/decorationsettingsprivate.cpp new file mode 100644 index 0000000..abcda80 --- /dev/null +++ b/src/private/decorationsettingsprivate.cpp @@ -0,0 +1,85 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#include "decorationsettingsprivate.h" +#include + +namespace KDecoration2 +{ +class Q_DECL_HIDDEN DecorationSettingsPrivate::Private +{ +public: + explicit Private(DecorationSettings *settings); + DecorationSettings *settings; + int gridUnit = -1; + int smallSpacing = -1; + int largeSpacing = -1; +}; + +DecorationSettingsPrivate::Private::Private(DecorationSettings *settings) + : settings(settings) +{ +} + +DecorationSettingsPrivate::DecorationSettingsPrivate(DecorationSettings *parent) + : d(new Private(parent)) +{ +} + +DecorationSettingsPrivate::~DecorationSettingsPrivate() +{ +} + +DecorationSettings *DecorationSettingsPrivate::decorationSettings() +{ + return d->settings; +} + +const DecorationSettings *DecorationSettingsPrivate::decorationSettings() const +{ + return d->settings; +} + +QFont DecorationSettingsPrivate::font() const +{ + return QFontDatabase::systemFont(QFontDatabase::TitleFont); +} + +QFontMetricsF DecorationSettingsPrivate::fontMetrics() const +{ + return QFontMetricsF(font()); +} + +int DecorationSettingsPrivate::gridUnit() const +{ + return d->gridUnit; +} + +int DecorationSettingsPrivate::smallSpacing() const +{ + return d->smallSpacing; +} + +int DecorationSettingsPrivate::largeSpacing() const +{ + return d->largeSpacing; +} + +void DecorationSettingsPrivate::setGridUnit(int unit) +{ + d->gridUnit = unit; +} + +void DecorationSettingsPrivate::setLargeSpacing(int spacing) +{ + d->largeSpacing = spacing; +} + +void DecorationSettingsPrivate::setSmallSpacing(int spacing) +{ + d->smallSpacing = spacing; +} + +} diff --git a/src/private/decorationsettingsprivate.h b/src/private/decorationsettingsprivate.h new file mode 100644 index 0000000..d0ef6e1 --- /dev/null +++ b/src/private/decorationsettingsprivate.h @@ -0,0 +1,60 @@ +/* + * SPDX-FileCopyrightText: 2014 Martin Gräßlin + * + * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL + */ +#pragma once + +#include "../decorationdefines.h" +#include +#include +#include +#include +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the KDecoration2 API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +namespace KDecoration2 +{ +class DecorationSettings; + +class KDECORATIONS_PRIVATE_EXPORT DecorationSettingsPrivate +{ +public: + virtual ~DecorationSettingsPrivate(); + virtual bool isOnAllDesktopsAvailable() const = 0; + virtual bool isAlphaChannelSupported() const = 0; + virtual bool isCloseOnDoubleClickOnMenu() const = 0; + virtual QList decorationButtonsLeft() const = 0; + virtual QList decorationButtonsRight() const = 0; + virtual BorderSize borderSize() const = 0; + virtual QFont font() const; + virtual QFontMetricsF fontMetrics() const; + + DecorationSettings *decorationSettings(); + const DecorationSettings *decorationSettings() const; + + int gridUnit() const; + int smallSpacing() const; + int largeSpacing() const; + void setGridUnit(int unit); + void setLargeSpacing(int spacing); + void setSmallSpacing(int spacing); + +protected: + explicit DecorationSettingsPrivate(DecorationSettings *parent); + +private: + class Private; + const std::unique_ptr d; +}; +} -- 2.30.2