From 36cbb591d0d01c0b5b04cf8e55a082017e9c1290 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Mon, 10 Oct 2022 05:24:18 +0000 Subject: [PATCH 001/141] Initial commit --- LICENSE | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..f288702d --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU 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. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. From 9dffa1dda46e473bb84a44761c13d61504fa0947 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Fri, 21 Oct 2022 00:51:22 -0600 Subject: [PATCH 002/141] Create LICENSE --- LICENSE | 899 ++++++++++++++++++-------------------------------------- 1 file changed, 282 insertions(+), 617 deletions(-) diff --git a/LICENSE b/LICENSE index f288702d..d159169d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,622 +1,281 @@ GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 + Version 2, June 1991 - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 1989, 1991 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. Preamble - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to this License. - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or + 7. 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 convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will +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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. +Each version is given a distinguishing version number. If the Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS @@ -628,15 +287,15 @@ free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least +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. Copyright (C) - This program is free software: you can redistribute it and/or modify + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or + the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -644,31 +303,37 @@ the "copyright" line and a pointer to where the full notice is found. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see . + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. From dda9f08f5e6c49fbbe625ee8df3e90cae3dee23d Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 27 Oct 2022 03:19:38 -0600 Subject: [PATCH 003/141] Finished Project --- FancyTasks.png | Bin 0 -> 4334 bytes LICENSE | 899 +++++++++++++++++-------- README.MD | 8 + contents/config/config.qml | 27 + contents/config/main.xml | 238 +++++++ contents/ui/AudioStream.qml | 173 +++++ contents/ui/Badge.qml | 62 ++ contents/ui/ConfigAppearance.qml | 200 ++++++ contents/ui/ConfigBehavior.qml | 244 +++++++ contents/ui/ConfigIndicators.qml | 151 +++++ contents/ui/ContextMenu.qml | 771 +++++++++++++++++++++ contents/ui/GroupDialog.qml | 147 ++++ contents/ui/GroupExpanderOverlay.qml | 82 +++ contents/ui/IndicatorOverlay.qml | 137 ++++ contents/ui/MouseHandler.qml | 186 +++++ contents/ui/PipeWireThumbnail.qml | 40 ++ contents/ui/PlayerController.qml | 121 ++++ contents/ui/PulseAudio.qml | 104 +++ contents/ui/ScrollableTextWrapper.qml | 53 ++ contents/ui/Task.qml | 843 +++++++++++++++++++++++ contents/ui/TaskBadgeOverlay.qml | 85 +++ contents/ui/TaskList.qml | 38 ++ contents/ui/TaskProgressOverlay.qml | 36 + contents/ui/ToolTipDelegate.qml | 124 ++++ contents/ui/ToolTipInstance.qml | 439 ++++++++++++ contents/ui/ToolTipWindowMouseArea.qml | 37 + contents/ui/code/layout.js | 237 +++++++ contents/ui/code/tools.js | 288 ++++++++ contents/ui/main.qml | 538 +++++++++++++++ metadata.json | 181 +++++ 30 files changed, 6207 insertions(+), 282 deletions(-) create mode 100644 FancyTasks.png create mode 100644 README.MD create mode 100644 contents/config/config.qml create mode 100644 contents/config/main.xml create mode 100644 contents/ui/AudioStream.qml create mode 100644 contents/ui/Badge.qml create mode 100644 contents/ui/ConfigAppearance.qml create mode 100644 contents/ui/ConfigBehavior.qml create mode 100644 contents/ui/ConfigIndicators.qml create mode 100644 contents/ui/ContextMenu.qml create mode 100644 contents/ui/GroupDialog.qml create mode 100644 contents/ui/GroupExpanderOverlay.qml create mode 100644 contents/ui/IndicatorOverlay.qml create mode 100644 contents/ui/MouseHandler.qml create mode 100644 contents/ui/PipeWireThumbnail.qml create mode 100644 contents/ui/PlayerController.qml create mode 100644 contents/ui/PulseAudio.qml create mode 100644 contents/ui/ScrollableTextWrapper.qml create mode 100644 contents/ui/Task.qml create mode 100644 contents/ui/TaskBadgeOverlay.qml create mode 100644 contents/ui/TaskList.qml create mode 100644 contents/ui/TaskProgressOverlay.qml create mode 100644 contents/ui/ToolTipDelegate.qml create mode 100644 contents/ui/ToolTipInstance.qml create mode 100644 contents/ui/ToolTipWindowMouseArea.qml create mode 100644 contents/ui/code/layout.js create mode 100644 contents/ui/code/tools.js create mode 100644 contents/ui/main.qml create mode 100644 metadata.json diff --git a/FancyTasks.png b/FancyTasks.png new file mode 100644 index 0000000000000000000000000000000000000000..0de6fd732eee927c7adaa37c91d5839224c2bbf9 GIT binary patch literal 4334 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 Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it -in new free programs; and that you know you can do these things. +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -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 give any other recipients of the Program a copy of this License -along with the Program. - -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 Program or any portion -of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -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 Program, 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 Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) 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; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, 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 executable. However, as a -special exception, the source code 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. - -If distribution of executable or 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 counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program 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. - - 5. 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 Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program 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 to + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of this License. - 7. 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 + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program 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 Program. - -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. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program 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. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 Program -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 Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, 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 - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. END OF TERMS AND CONDITIONS @@ -287,15 +628,15 @@ free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. 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 +state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -303,37 +644,31 @@ the "copyright" line and a pointer to where the full notice is found. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + You should have received a copy of the GNU General Public License + along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.MD b/README.MD new file mode 100644 index 00000000..79401c4e --- /dev/null +++ b/README.MD @@ -0,0 +1,8 @@ +# Customized KDE Task Manager +Features improvements tweaks and options to the original task manager plasmoid made by Eike Hein. +* Implemented adjustable task width. +* Implemented switching between taskbar types. + +### Todo +* Implement marker changes and task designs +* Allow coloring based on icon dominant color \ No newline at end of file diff --git a/contents/config/config.qml b/contents/config/config.qml new file mode 100644 index 00000000..5d2042f5 --- /dev/null +++ b/contents/config/config.qml @@ -0,0 +1,27 @@ +/* + SPDX-FileCopyrightText: 2013 Eike Hein + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.0 + +import org.kde.plasma.configuration 2.0 + +ConfigModel { + ConfigCategory { + name: i18n("Appearance") + icon: "preferences-desktop-color" + source: "ConfigAppearance.qml" + } + ConfigCategory { + name: i18n("Behavior") + icon: "preferences-desktop" + source: "ConfigBehavior.qml" + } + ConfigCategory { + name: i18n("Indicators") + icon: "preferences-desktop-navigation" + source: "ConfigIndicators.qml" + } +} diff --git a/contents/config/main.xml b/contents/config/main.xml new file mode 100644 index 00000000..cdb6a0b9 --- /dev/null +++ b/contents/config/main.xml @@ -0,0 +1,238 @@ + + + + + + + + false + + + + true + + + + true + + + + false + + + + true + + + + 1 + + + + 1 + + + + 0 + + + + true + + + + true + + + + + + + + + + + + 1 + + + + true + + + + 2 + 1 + + + + 200 + 1 + + + + false + + + + true + + + + true + + + + true + + + + true + + + + applications:systemsettings.desktop,applications:org.kde.discover.desktop,preferred://filemanager,preferred://browser + + + + + + + + + + + + 2 + + + + true + + + + true + + + + 0 + + + + true + + + + false + + + + 1 + + + + 0 + + + + 1 + + + + 0 + + + + 0 + + + + 0 + + + + 4 + + + + 8 + + + + 0 + + + + 4 + + + + false + + + + true + + + + white + + + + True + + + + 0 + + + + false + + + + true + + + + #FFFFFF + + + + false + + + + + + + + + + 0 + + + + + + + + + + 0 + + + + false + + + + false + + + + + diff --git a/contents/ui/AudioStream.qml b/contents/ui/AudioStream.qml new file mode 100644 index 00000000..41bfd135 --- /dev/null +++ b/contents/ui/AudioStream.qml @@ -0,0 +1,173 @@ +/* + SPDX-FileCopyrightText: 2017 Kai Uwe Broulik + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 + +import org.kde.plasma.core 2.0 as PlasmaCore + +MouseArea { + id: audioStreamIconBox + hoverEnabled: true + onClicked: toggleMuted() + + // Using States rather than a simple Behavior we can apply different transitions, + // which allows us to delay showing the icon but hide it instantly still. + states: [ + State { + name: "playing" + when: task.playingAudio && !task.muted + PropertyChanges { + target: audioStreamIconBox + opacity: 1 + } + PropertyChanges { + target: audioStreamIcon + elementId: "audio-volume-high" + } + }, + State { + name: "muted" + when: task.muted + PropertyChanges { + target: audioStreamIconBox + opacity: 1 + } + PropertyChanges { + target: audioStreamIcon + elementId: "audio-volume-muted" + } + } + ] + + transitions: [ + Transition { + from: "" + to: "playing" + SequentialAnimation { + // Delay showing the play indicator so we don't flash it for brief sounds. + PauseAnimation { + duration: !task.delayAudioStreamIndicator || inPopup ? 0 : 2000 + } + NumberAnimation { + property: "opacity" + duration: PlasmaCore.Units.longDuration + } + } + }, + Transition { + from: "" + to: "muted" + SequentialAnimation { + NumberAnimation { + property: "opacity" + duration: PlasmaCore.Units.longDuration + } + } + }, + Transition { + to: "" + NumberAnimation { + property: "opacity" + duration: PlasmaCore.Units.longDuration + } + } + ] + + opacity: 0 + visible: opacity > 0 + + PlasmaCore.FrameSvgItem { + anchors.fill: audioStreamIcon + visible: parent.containsMouse + imagePath: "widgets/viewitem" + prefix: "hover" + } + + PlasmaCore.Svg { + id: audioSvg + imagePath: "icons/audio" + } + + PlasmaCore.SvgItem { + id: audioStreamIcon + + // Need audio indicator twice, to keep iconBox in the center. + readonly property var requiredSpace: Math.min(iconBox.width, iconBox.height) + + Math.min(Math.min(iconBox.width, iconBox.height), PlasmaCore.Units.iconSizes.smallMedium) * 2 + svg: audioSvg + smooth: false + + height: Math.round(Math.min(parent.height * indicatorScale, PlasmaCore.Units.iconSizes.smallMedium)) + width: height + + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + + states: [ + State { + name: "verticalIconsOnly" + when: tasks.vertical && frame.width < audioStreamIcon.requiredSpace + + PropertyChanges { + target: audioStreamIconLoader + anchors.rightMargin: Math.round(taskFrame.margins.right * indicatorScale) + } + }, + + State { + name: "horizontal" + when: frame.width > audioStreamIcon.requiredSpace + + AnchorChanges { + target: audioStreamIconLoader + + anchors.top: undefined + anchors.verticalCenter: frame.verticalCenter + } + + PropertyChanges { + target: audioStreamIconLoader + width: PlasmaCore.Units.roundToIconSize(Math.min(Math.min(iconBox.width, iconBox.height), PlasmaCore.Units.iconSizes.smallMedium)) + } + + PropertyChanges { + target: audioStreamIcon + + height: parent.height + width: parent.width + } + }, + + State { + name: "vertical" + when: frame.height > audioStreamIcon.requiredSpace + + AnchorChanges { + target: audioStreamIconLoader + + anchors.right: undefined + anchors.horizontalCenter: frame.horizontalCenter + } + + PropertyChanges { + target: audioStreamIconLoader + + anchors.topMargin: taskFrame.margins.top + width: PlasmaCore.Units.roundToIconSize(Math.min(Math.min(iconBox.width, iconBox.height), PlasmaCore.Units.iconSizes.smallMedium)) + } + + PropertyChanges { + target: audioStreamIcon + + height: parent.height + width: parent.width + } + } + ] + } +} diff --git a/contents/ui/Badge.qml b/contents/ui/Badge.qml new file mode 100644 index 00000000..b3258f75 --- /dev/null +++ b/contents/ui/Badge.qml @@ -0,0 +1,62 @@ +/* + SPDX-FileCopyrightText: 2018 Kai Uwe Broulik + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 3.0 as PlasmaComponents3 + +// This top-level item is an opaque background that goes behind the colored +// background, for contrast. It's not an Item since that it would be square, +// and not round, as required here +Rectangle { + id: badgeRect + + property alias text: label.text + property alias textColor: label.color + property int number: 0 + + implicitWidth: Math.max(height, Math.round(label.contentWidth + radius / 2)) // Add some padding around. + implicitHeight: implicitWidth + + radius: height / 2 + + color: PlasmaCore.Theme.backgroundColor + + // Colored background + Rectangle { + readonly property color color_: PlasmaCore.Theme.highlightColor + + anchors.fill: parent + radius: height / 2 + + color: Qt.rgba(color_.r, color_.g, color_.b, 0.3) + border.color: color_ + border.width: PlasmaCore.Units.devicePixelRatio + } + + // Number + PlasmaComponents3.Label { + id: label + anchors.centerIn: parent + width: height + height: Math.min(PlasmaCore.Units.gridUnit * 2, Math.round(parent.height)) + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + fontSizeMode: Text.VerticalFit + font.pointSize: 1024 + minimumPointSize: 5 + text: { + if (badgeRect.number < 0) { + return i18nc("Invalid number of new messages, overlay, keep short", "—"); + } else if (badgeRect.number > 9999) { + return i18nc("Over 9999 new messages, overlay, keep short", "9,999+"); + } else { + return badgeRect.number.toLocaleString(Qt.locale(), 'f', 0); + } + } + } +} diff --git a/contents/ui/ConfigAppearance.qml b/contents/ui/ConfigAppearance.qml new file mode 100644 index 00000000..6fc81996 --- /dev/null +++ b/contents/ui/ConfigAppearance.qml @@ -0,0 +1,200 @@ +/* + SPDX-FileCopyrightText: 2013 Eike Hein + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import org.kde.kirigami 2.19 as Kirigami +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.plasmoid 2.0 +import org.kde.kquickcontrols 2.0 as KQControls + + +Kirigami.FormLayout { + anchors.left: parent.left + anchors.right: parent.right + + readonly property bool plasmaPaAvailable: Qt.createComponent("PulseAudio.qml").status === Component.Ready + readonly property bool plasmoidVertical: Plasmoid.formFactor === PlasmaCore.Types.Vertical + readonly property bool iconOnly: plasmoid.configuration.iconOnly + + property alias cfg_showToolTips: showToolTips.checked + property alias cfg_highlightWindows: highlightWindows.checked + property bool cfg_indicateAudioStreams + property alias cfg_maxStripes: maxStripes.value + property bool cfg_forceStripes + property alias cfg_maxLength: maxLength.value + property int cfg_iconSpacing: 0 + + property alias cfg_useBorders: useBorders.checked + property alias cfg_taskSpacingSize: taskSpacingSize.value + + property alias cfg_buttonColorize: buttonColorize.checked + property alias cfg_buttonColorizeDominant: buttonColorizeDominant.checked + property alias cfg_buttonColorizeCustom: buttonColorizeCustom.color + + property alias cfg_overridePlasmaButtonDirection: overridePlasmaButtonDirection.checked + property alias cfg_plasmaButtonDirection: plasmaButtonDirection.currentIndex + + CheckBox { + id: showToolTips + Kirigami.FormData.label: i18n("General:") + text: i18n("Show tooltips") + } + + RowLayout { + // HACK: Workaround for Kirigami bug 434625 + // due to which a simple Layout.leftMargin on CheckBox doesn't work + Item { implicitWidth: Kirigami.Units.gridUnit } + CheckBox { + id: highlightWindows + text: i18n("Highlight windows when hovering over task tooltips") + enabled: showToolTips.checked + } + } + + CheckBox { + id: indicateAudioStreams + text: i18n("Mark applications that play audio") + checked: cfg_indicateAudioStreams && plasmaPaAvailable + onCheckedChanged: cfg_indicateAudioStreams = checked + enabled: plasmaPaAvailable + } + + CheckBox { + id: useBorders + text: i18n("Use plasma borders") + } + + Item { + Kirigami.FormData.isSection: true + } + + CheckBox { + id: buttonColorize + text: i18n("Colorize buttons") + } + + CheckBox { + enabled: buttonColorize.checked + id: buttonColorizeDominant + text: i18n("Use dominant icon color") + } + + KQControls.ColorButton { + Layout.leftMargin: Kirigami.Units.GridUnit + enabled: buttonColorize.checked & !buttonColorizeDominant.checked + id: buttonColorizeCustom + Kirigami.FormData.label: i18n("Custom Color:") + showAlphaChannel: true + } + + Item { + Kirigami.FormData.isSection: true + } + + CheckBox { + id: overridePlasmaButtonDirection + Kirigami.FormData.label: i18n("Plasma Button Direction:") + text: i18n("Override") + } + + ComboBox { + id: plasmaButtonDirection + enabled: overridePlasmaButtonDirection.checked + //Kirigami.FormData.label: i18n("Indicator Location:") + model: [ + i18n("North"), + i18n("South"), + i18n("West"), + i18n("East") + ] + } + + Item { + Kirigami.FormData.isSection: true + } + + SpinBox { + id: maxStripes + Kirigami.FormData.label: plasmoidVertical ? i18n("Maximum columns:") : i18n("Maximum rows:") + from: 1 + } + + CheckBox {//This setting defaults to on now when there is only 1 stripe because it makes no sense otherwise. + id: forceStripes + text: plasmoidVertical ? i18n("Always arrange tasks in rows of as many columns") : i18n("Always arrange tasks in columns of as many rows") + enabled: maxStripes.value > 1 + checked: cfg_forceStripes || maxStripes.value === 1 + onCheckedChanged: cfg_forceStripes = checked + } + + SpinBox { + visible: !plasmoidVertical && !iconOnly + id: maxLength + Kirigami.FormData.label: i18n("Maximum button length (px):") + from: 1 + to: 9999 + } + + SpinBox { + id: taskSpacingSize + Kirigami.FormData.label: i18n("Space between taskbar items (px):") + from: 0 + to: 99 + } + Label { + text: i18n("Press OK to fix layout issues.") + font: Kirigami.Theme.smallFont + } + + Item { + Kirigami.FormData.isSection: true + } + + ComboBox { + visible: iconOnly + Kirigami.FormData.label: i18n("Spacing between icons:") + + model: [ + { + "label": i18nc("@item:inlistbox Icon spacing", "Small"), + "spacing": 0 + }, + { + "label": i18nc("@item:inlistbox Icon spacing", "Normal"), + "spacing": 1 + }, + { + "label": i18nc("@item:inlistbox Icon spacing", "Large"), + "spacing": 3 + }, + ] + + textRole: "label" + enabled: !Kirigami.Settings.tabletMode + + currentIndex: { + if (Kirigami.Settings.tabletMode) { + return 2; // Large + } + + switch (cfg_iconSpacing) { + case 0: return 0; // Small + case 1: return 1; // Normal + case 3: return 2; // Large + } + } + onActivated: cfg_iconSpacing = model[currentIndex]["spacing"]; + } + + Label { + visible: Kirigami.Settings.tabletMode + text: i18nc("@info:usagetip under a set of radio buttons when Touch Mode is on", "Automatically set to Large when in Touch Mode") + font: Kirigami.Theme.smallFont + } +} diff --git a/contents/ui/ConfigBehavior.qml b/contents/ui/ConfigBehavior.qml new file mode 100644 index 00000000..8dd89216 --- /dev/null +++ b/contents/ui/ConfigBehavior.qml @@ -0,0 +1,244 @@ +/* + SPDX-FileCopyrightText: 2013 Eike Hein + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import org.kde.kirigami 2.19 as Kirigami +import org.kde.plasma.core 2.0 as PlasmaCore + +import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet + +Item { + width: childrenRect.width + height: childrenRect.height + + property alias cfg_groupingStrategy: groupingStrategy.currentIndex + property alias cfg_groupedTaskVisualization: groupedTaskVisualization.currentIndex + property alias cfg_groupPopups: groupPopups.checked + property alias cfg_onlyGroupWhenFull: onlyGroupWhenFull.checked + property alias cfg_sortingStrategy: sortingStrategy.currentIndex + property alias cfg_separateLaunchers: separateLaunchers.checked + property alias cfg_middleClickAction: middleClickAction.currentIndex + property alias cfg_wheelEnabled: wheelEnabled.checked + property alias cfg_wheelSkipMinimized: wheelSkipMinimized.checked + property alias cfg_showOnlyCurrentScreen: showOnlyCurrentScreen.checked + property alias cfg_showOnlyCurrentDesktop: showOnlyCurrentDesktop.checked + property alias cfg_showOnlyCurrentActivity: showOnlyCurrentActivity.checked + property alias cfg_showOnlyMinimized: showOnlyMinimized.checked + property alias cfg_minimizeActiveTaskOnClick: minimizeActive.checked + property alias cfg_unhideOnAttention: unhideOnAttention.checked + property alias cfg_reverseMode: reverseMode.checked + property alias cfg_iconOnly: iconOnly.currentIndex + + TaskManagerApplet.Backend { + id: backend + } + + Kirigami.FormLayout { + anchors.left: parent.left + anchors.right: parent.right + + ComboBox { + id: iconOnly + Kirigami.FormData.label: i18n("Display:") + Layout.fillWidth: true + Layout.minimumWidth: Kirigami.Units.gridUnit * 14 + model: [i18n("Show task names"), i18n("Show icons only")] + } + + ComboBox { + id: groupingStrategy + Kirigami.FormData.label: i18n("Group:") + Layout.fillWidth: true + Layout.minimumWidth: Kirigami.Units.gridUnit * 14 + model: [i18n("Do not group"), i18n("By program name")] + } + + ComboBox { + id: groupedTaskVisualization + Kirigami.FormData.label: i18n("Clicking grouped task:") + Layout.fillWidth: true + Layout.minimumWidth: Kirigami.Units.gridUnit * 14 + + enabled: groupingStrategy.currentIndex !== 0 + + model: [ + i18nc("Completes the sentence 'Clicking grouped task cycles through tasks' ", "Cycles through tasks"), + i18nc("Completes the sentence 'Clicking grouped task shows tooltip window thumbnails' ", "Shows tooltip window thumbnails"), + i18nc("Completes the sentence 'Clicking grouped task shows windows side by side' ", "Shows windows side by side"), + i18nc("Completes the sentence 'Clicking grouped task shows textual list' ", "Shows textual list"), + ] + } + // "You asked for Tooltips but Tooltips are disabled" message + Kirigami.InlineMessage { + Layout.fillWidth: true + visible: groupedTaskVisualization.currentIndex === 1 && !plasmoid.configuration.showToolTips && backend.windowViewAvailable + type: Kirigami.MessageType.Warning + text: i18n("Tooltips are disabled, so the windows will be displayed side by side instead.") + } + // "You asked for Tooltips but Tooltips are disabled and Window View is not available" message + Kirigami.InlineMessage { + Layout.fillWidth: true + visible: groupedTaskVisualization.currentIndex === 1 && !plasmoid.configuration.showToolTips && !backend.windowViewAvailable + type: Kirigami.MessageType.Warning + text: i18n("Tooltips are disabled, and the compositor does not support displaying windows side by side, so a textual list will be displayed instead") + } + // "You asked for Window View but Window View is not available" message + Kirigami.InlineMessage { + Layout.fillWidth: true + visible: groupedTaskVisualization.currentIndex === 2 && !backend.windowViewAvailable + type: Kirigami.MessageType.Warning + text: i18n("The compositor does not support displaying windows side by side, so a textual list will be displayed instead.") + } + + Item { + Kirigami.FormData.isSection: true + } + + CheckBox { + id: groupPopups + visible: (!plasmoid.configuration.iconOnly) + text: i18n("Combine into single button") + enabled: groupingStrategy.currentIndex > 0 + } + + CheckBox { + id: onlyGroupWhenFull + visible: (!plasmoid.configuration.iconOnly) + text: i18n("Group only when the Task Manager is full") + enabled: groupingStrategy.currentIndex > 0 && groupPopups.checked + } + + Item { + Kirigami.FormData.isSection: true + visible: (!plasmoid.configuration.iconOnly) + } + + ComboBox { + id: sortingStrategy + Kirigami.FormData.label: i18n("Sort:") + Layout.fillWidth: true + Layout.minimumWidth: Kirigami.Units.gridUnit * 14 + model: [i18n("Do not sort"), i18n("Manually"), i18n("Alphabetically"), i18n("By desktop"), i18n("By activity")] + } + + CheckBox { + id: separateLaunchers + visible: (!plasmoid.configuration.iconOnly) + text: i18n("Keep launchers separate") + enabled: sortingStrategy.currentIndex == 1 + } + + Item { + Kirigami.FormData.isSection: true + visible: (!plasmoid.configuration.iconOnly) + } + + CheckBox { + id: minimizeActive + Kirigami.FormData.label: i18nc("Part of a sentence: 'Clicking active task minimizes the task'", "Clicking active task:") + text: i18nc("Part of a sentence: 'Clicking active task minimizes the task'", "Minimizes the task") + } + + ComboBox { + id: middleClickAction + Kirigami.FormData.label: i18n("Middle-clicking any task:") + Layout.fillWidth: true + Layout.minimumWidth: Kirigami.Units.gridUnit * 14 + model: [ + i18nc("Part of a sentence: 'Middle-clicking any task does nothing'", "Does nothing"), + i18nc("Part of a sentence: 'Middle-clicking any task closes window or group'", "Closes window or group"), + i18nc("Part of a sentence: 'Middle-clicking any task opens a new window'", "Opens a new window"), + i18nc("Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'", "Minimizes/Restores window or group"), + i18nc("Part of a sentence: 'Middle-clicking any task toggles grouping'", "Toggles grouping"), + i18nc("Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'", "Brings it to the current virtual desktop") + ] + } + + Item { + Kirigami.FormData.isSection: true + } + + CheckBox { + id: wheelEnabled + Kirigami.FormData.label: i18nc("Part of a sentence: 'Mouse wheel cycles through tasks'", "Mouse wheel:") + text: i18nc("Part of a sentence: 'Mouse wheel cycles through tasks'", "Cycles through tasks") + } + + RowLayout { + // HACK: Workaround for Kirigami bug 434625 + // due to which a simple Layout.leftMargin on CheckBox doesn't work + Item { implicitWidth: Kirigami.Units.gridUnit } + CheckBox { + id: wheelSkipMinimized + text: i18n("Skip minimized tasks") + enabled: wheelEnabled.checked + } + } + + Item { + Kirigami.FormData.isSection: true + } + + CheckBox { + id: showOnlyCurrentScreen + Kirigami.FormData.label: i18n("Show only tasks:") + text: i18n("From current screen") + } + + CheckBox { + id: showOnlyCurrentDesktop + text: i18n("From current desktop") + } + + CheckBox { + id: showOnlyCurrentActivity + text: i18n("From current activity") + } + + CheckBox { + id: showOnlyMinimized + text: i18n("That are minimized") + } + + Item { + Kirigami.FormData.isSection: true + } + + CheckBox { + id: unhideOnAttention + Kirigami.FormData.label: i18n("When panel is hidden:") + text: i18n("Unhide when a window wants attention") + } + + Item { + Kirigami.FormData.isSection: true + } + + ButtonGroup { + id: reverseModeRadioButtonGroup + } + + RadioButton { + Kirigami.FormData.label: i18n("New tasks appear:") + checked: !reverseMode.checked + text: Qt.application.layoutDirection === Qt.LeftToRight ? i18n("To the right") : i18n("To the left") + ButtonGroup.group: reverseModeRadioButtonGroup + visible: reverseMode.visible + } + + RadioButton { + id: reverseMode + checked: plasmoid.configuration.reverseMode === true + text: Qt.application.layoutDirection === Qt.RightToLeft ? i18n("To the right") : i18n("To the left") + ButtonGroup.group: reverseModeRadioButtonGroup + visible: plasmoid.formFactor === PlasmaCore.Types.Horizontal + } + + } +} diff --git a/contents/ui/ConfigIndicators.qml b/contents/ui/ConfigIndicators.qml new file mode 100644 index 00000000..6efbc81f --- /dev/null +++ b/contents/ui/ConfigIndicators.qml @@ -0,0 +1,151 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import org.kde.kirigami 2.19 as Kirigami +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.kquickcontrols 2.0 as KQControls + +import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet + +Kirigami.FormLayout { + anchors.left: parent.left + anchors.right: parent.right + + property alias cfg_indicatorsEnabled: indicatorsEnabled.currentIndex + property alias cfg_groupIconEnabled: groupIconEnabled.currentIndex + property alias cfg_indicatorLocation: indicatorLocation.currentIndex + property alias cfg_indicatorReverse: indicatorReverse.checked + property alias cfg_indicatorOverride: indicatorOverride.checked + property alias cfg_indicatorStyle: indicatorStyle.currentIndex + property alias cfg_indicatorSize: indicatorSize.value + property alias cfg_indicatorLength: indicatorLength.value + property alias cfg_indicatorRadius: indicatorRadius.value + property alias cfg_indicatorShrink: indicatorShrink.value + property alias cfg_indicatorDominantColor: indicatorDominantColor.checked + property alias cfg_indicatorAccentColor: indicatorAccentColor.checked + property alias cfg_indicatorCustomColor: indicatorCustomColor.color + + ComboBox { + id: indicatorsEnabled + Kirigami.FormData.label: i18n("Indicators:") + model: [i18n("Disabled"), i18n("Enabled")] + } + + ComboBox { + id: groupIconEnabled + Kirigami.FormData.label: i18n("Group Overlay:") + model: [i18n("Disabled"), i18n("Enabled")] + } + Label { + text: i18n("Takes effect on next time plasma groups tasks.") + font: Kirigami.Theme.smallFont + } + + Item { + Kirigami.FormData.isSection: true + } + + CheckBox { + enabled: indicatorsEnabled.currentIndex && !indicatorOverride.checked + id: indicatorReverse + Kirigami.FormData.label: i18n("Indicator Location:") + text: i18n("Reverse shown side") + } + + CheckBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorOverride + text: i18n("Override location") + } + + ComboBox { + enabled: indicatorsEnabled.currentIndex + visible: indicatorOverride.checked + id: indicatorLocation + model: [ + i18n("Bottom"), + i18n("Left"), + i18n("Right"), + i18n("Top") + ] + } + + Item { + Kirigami.FormData.isSection: true + } + + ComboBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorStyle + Kirigami.FormData.label: i18n("Indicator Style:") + Layout.fillWidth: true + Layout.minimumWidth: Kirigami.Units.gridUnit * 14 + model: [ + i18n("Metro"), + i18n("Ciliora"), + i18n("Dashes") + ] + } + + SpinBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorSize + Kirigami.FormData.label: i18n("Indicator size (px):") + from: 1 + to: 999 + } + + SpinBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorLength + Kirigami.FormData.label: i18n("Indicator length (px):") + from: 1 + to: 999 + } + + SpinBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorRadius + Kirigami.FormData.label: i18n("Indicator Radius (%):") + from: 0 + to: 100 + } + + SpinBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorShrink + Kirigami.FormData.label: i18n("Indicator margin (px):") + from: 0 + to: 999 + } + + + Item { + Kirigami.FormData.isSection: true + } + + CheckBox { + enabled: indicatorsEnabled.currentIndex & !indicatorAccentColor.checked + id: indicatorDominantColor + Kirigami.FormData.label: i18n("Indicator Color:") + text: i18n("Use dominant icon color") + } + + CheckBox { + enabled: indicatorsEnabled.currentIndex & !indicatorDominantColor.checked + id: indicatorAccentColor + text: i18n("Use plasma accent color") + } + + KQControls.ColorButton { + enabled: indicatorsEnabled.currentIndex & !indicatorDominantColor.checked & !indicatorAccentColor.checked + id: indicatorCustomColor + Kirigami.FormData.label: i18n("Custom Color:") + showAlphaChannel: true + } + + Item { + Kirigami.FormData.isSection: true + } +} \ No newline at end of file diff --git a/contents/ui/ContextMenu.qml b/contents/ui/ContextMenu.qml new file mode 100644 index 00000000..ce4f47e1 --- /dev/null +++ b/contents/ui/ContextMenu.qml @@ -0,0 +1,771 @@ +/* + SPDX-FileCopyrightText: 2012-2016 Eike Hein + SPDX-FileCopyrightText: 2016 Kai Uwe Broulik + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 + +import org.kde.plasma.plasmoid 2.0 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents + +import org.kde.taskmanager 0.1 as TaskManager + +import "code/layout.js" as LayoutManager + +PlasmaComponents.ContextMenu { + id: menu + + property QtObject backend + property QtObject mpris2Source + property var modelIndex + readonly property var atm: TaskManager.AbstractTasksModel + + property bool showAllPlaces: false + + placement: { + if (plasmoid.location === PlasmaCore.Types.LeftEdge) { + return PlasmaCore.Types.RightPosedTopAlignedPopup; + } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { + return PlasmaCore.Types.BottomPosedLeftAlignedPopup; + } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { + return PlasmaCore.Types.LeftPosedTopAlignedPopup; + } else { + return PlasmaCore.Types.TopPosedLeftAlignedPopup; + } + } + + minimumWidth: visualParent.width + + onStatusChanged: { + if (visualParent && get(atm.LauncherUrlWithoutIcon) != "" && status == PlasmaComponents.DialogStatus.Open) { + activitiesDesktopsMenu.refresh(); + + } else if (status == PlasmaComponents.DialogStatus.Closed) { + menu.destroy(); + backend.ungrabMouse(visualParent); + } + } + + Component.onCompleted: { + // Cannot have "Connections" as child of PlasmaCoponents.ContextMenu. + backend.showAllPlaces.connect(showContextMenuWithAllPlaces); + } + + Component.onDestruction: { + backend.showAllPlaces.disconnect(showContextMenuWithAllPlaces); + } + + function showContextMenuWithAllPlaces() { + visualParent.showContextMenu({showAllPlaces: true}); + } + + function get(modelProp) { + return tasksModel.data(modelIndex, modelProp) + } + + function show() { + loadDynamicLaunchActions(get(atm.LauncherUrlWithoutIcon)); + openRelative(); + } + + function newMenuItem(parent) { + return Qt.createQmlObject(` + import org.kde.plasma.components 2.0 as PlasmaComponents + + PlasmaComponents.MenuItem {} + `, parent); + } + + function newSeparator(parent) { + return Qt.createQmlObject(` + import org.kde.plasma.components 2.0 as PlasmaComponents + + PlasmaComponents.MenuItem { separator: true } + `, parent); + } + + function loadDynamicLaunchActions(launcherUrl) { + var sections = [ + { + title: i18n("Places"), + group: "places", + actions: backend.placesActions(launcherUrl, showAllPlaces, menu) + }, + { + title: i18n("Recent Files"), + group: "recents", + actions: backend.recentDocumentActions(launcherUrl, menu) + }, + { + title: i18n("Actions"), + group: "actions", + actions: backend.jumpListActions(launcherUrl, menu) + } + ] + + // C++ can override section heading by returning a QString as first action + sections.forEach((section) => { + if (typeof section.actions[0] === "string") { + section.title = section.actions.shift(); // take first + } + }); + + // QMenu does not limit its width automatically. Even if we set a maximumWidth + // it would just cut off text rather than eliding. So we do this manually. + var textMetrics = Qt.createQmlObject("import QtQuick 2.4; TextMetrics {}", menu); + var maximumWidth = LayoutManager.maximumContextMenuTextWidth(); + + sections.forEach(function (section) { + if (section["actions"].length > 0 || section["group"] == "actions") { + // Don't add the "Actions" header if the menu has nothing but actions + // in it, because then it's redundant (all menus have actions) + if ( + (section["group"] != "actions") || + (section["group"] == "actions" && (sections[0]["actions"].length > 0 || sections[1]["actions"].length > 0)) + ) { + var sectionHeader = newMenuItem(menu); + sectionHeader.text = section["title"]; + sectionHeader.section = true; + menu.addMenuItem(sectionHeader, startNewInstanceItem); + } + } + + for (var i = 0; i < section["actions"].length; ++i) { + var item = newMenuItem(menu); + item.action = section["actions"][i]; + + // Crude way of manually eliding... + var elided = false; + textMetrics.text = Qt.binding(function() { + return item.action.text; + }); + + while (textMetrics.width > maximumWidth) { + item.action.text = item.action.text.slice(0, -1); + elided = true; + } + + if (elided) { + item.action.text += "…"; + } + + menu.addMenuItem(item, startNewInstanceItem); + } + }); + + // Add Media Player control actions + var sourceName = mpris2Source.sourceNameForLauncherUrl(launcherUrl, get(atm.AppPid)); + + if (sourceName && !(get(atm.WinIdList) !== undefined && get(atm.WinIdList).length > 1)) { + var playerData = mpris2Source.data[sourceName] + + if (playerData.CanControl) { + var playing = (playerData.PlaybackStatus === "Playing"); + var menuItem = menu.newMenuItem(menu); + menuItem.text = i18nc("Play previous track", "Previous Track"); + menuItem.icon = "media-skip-backward"; + menuItem.enabled = Qt.binding(function() { + return playerData.CanGoPrevious; + }); + menuItem.clicked.connect(function() { + mpris2Source.goPrevious(sourceName); + }); + menu.addMenuItem(menuItem, startNewInstanceItem); + + menuItem = menu.newMenuItem(menu); + // PlasmaCore Menu doesn't actually handle icons or labels changing at runtime... + menuItem.text = Qt.binding(function() { + // if CanPause, toggle the menu entry between Play & Pause, otherwise always use Play + return playing && playerData.CanPause ? i18nc("Pause playback", "Pause") : i18nc("Start playback", "Play"); + }); + menuItem.icon = Qt.binding(function() { + return playing && playerData.CanPause ? "media-playback-pause" : "media-playback-start"; + }); + menuItem.enabled = Qt.binding(function() { + return playing ? playerData.CanPause : playerData.CanPlay; + }); + menuItem.clicked.connect(function() { + if (playing) { + mpris2Source.pause(sourceName); + } else { + mpris2Source.play(sourceName); + } + }); + menu.addMenuItem(menuItem, startNewInstanceItem); + + menuItem = menu.newMenuItem(menu); + menuItem.text = i18nc("Play next track", "Next Track"); + menuItem.icon = "media-skip-forward"; + menuItem.enabled = Qt.binding(function() { + return playerData.CanGoNext; + }); + menuItem.clicked.connect(function() { + mpris2Source.goNext(sourceName); + }); + menu.addMenuItem(menuItem, startNewInstanceItem); + + menuItem = menu.newMenuItem(menu); + menuItem.text = i18nc("Stop playback", "Stop"); + menuItem.icon = "media-playback-stop"; + menuItem.enabled = Qt.binding(function() { + return playerData.PlaybackStatus !== "Stopped"; + }); + menuItem.clicked.connect(function() { + mpris2Source.stop(sourceName); + }); + menu.addMenuItem(menuItem, startNewInstanceItem); + + // Technically media controls and audio streams are separate but for the user they're + // semantically related, don't add a separator inbetween. + if (!menu.visualParent.hasAudioStream) { + menu.addMenuItem(newSeparator(menu), startNewInstanceItem); + } + + // If we don't have a window associated with the player but we can quit + // it through MPRIS we'll offer a "Quit" option instead of "Close" + if (!closeWindowItem.visible && playerData.CanQuit) { + menuItem = menu.newMenuItem(menu); + menuItem.text = i18nc("Quit media player app", "Quit"); + menuItem.icon = "application-exit"; + menuItem.visible = Qt.binding(function() { + return !closeWindowItem.visible; + }); + menuItem.clicked.connect(function() { + mpris2Source.quit(sourceName); + }); + menu.addMenuItem(menuItem); + } + + // If we don't have a window associated with the player but we can raise + // it through MPRIS we'll offer a "Restore" option + if (get(atm.IsLauncher) === true && !startNewInstanceItem.visible && playerData.CanRaise) { + menuItem = menu.newMenuItem(menu); + menuItem.text = i18nc("Open or bring to the front window of media player app", "Restore"); + menuItem.icon = playerData["Desktop Icon Name"]; + menuItem.visible = Qt.binding(function() { + return !startNewInstanceItem.visible; + }); + menuItem.clicked.connect(function() { + mpris2Source.raise(sourceName); + }); + menu.addMenuItem(menuItem, startNewInstanceItem); + } + } + } + + // We allow mute/unmute whenever an application has a stream, regardless of whether it + // is actually playing sound. + // This way you can unmute, e.g. a telephony app, even after the conversation has ended, + // so you still have it ringing later on. + if (menu.visualParent.hasAudioStream) { + var muteItem = menu.newMenuItem(menu); + muteItem.checkable = true; + muteItem.checked = Qt.binding(function() { + return menu.visualParent && menu.visualParent.muted; + }); + muteItem.clicked.connect(function() { + menu.visualParent.toggleMuted(); + }); + muteItem.text = i18n("Mute"); + muteItem.icon = "audio-volume-muted"; + menu.addMenuItem(muteItem, startNewInstanceItem); + + menu.addMenuItem(newSeparator(menu), startNewInstanceItem); + } + } + + PlasmaComponents.MenuItem { + id: startNewInstanceItem + visible: get(atm.CanLaunchNewInstance) + text: i18n("Open New Window") + icon: "window-new" + + onClicked: tasksModel.requestNewInstance(modelIndex) + } + + PlasmaComponents.MenuItem { + id: virtualDesktopsMenuItem + + visible: virtualDesktopInfo.numberOfDesktops > 1 + && (visualParent && get(atm.IsLauncher) !== true + && get(atm.IsStartup) !== true + && get(atm.IsVirtualDesktopsChangeable) === true) + + enabled: visible + + text: i18n("Move to &Desktop") + icon: "virtual-desktops" + + Connections { + target: virtualDesktopInfo + + function onNumberOfDesktopsChanged() {Qt.callLater(virtualDesktopsMenu.refresh)} + function onDesktopIdsChanged() {Qt.callLater(virtualDesktopsMenu.refresh)} + function onDesktopNamesChanged() {Qt.callLater(virtualDesktopsMenu.refresh)} + } + + PlasmaComponents.ContextMenu { + id: virtualDesktopsMenu + + visualParent: virtualDesktopsMenuItem.action + + function refresh() { + clearMenuItems(); + + if (virtualDesktopInfo.numberOfDesktops <= 1) { + return; + } + + var menuItem = menu.newMenuItem(virtualDesktopsMenu); + menuItem.text = i18n("Move &To Current Desktop"); + menuItem.enabled = Qt.binding(function() { + return menu.visualParent && menu.get(atm.VirtualDesktops).indexOf(virtualDesktopInfo.currentDesktop) === -1; + }); + menuItem.clicked.connect(function() { + tasksModel.requestVirtualDesktops(menu.modelIndex, [virtualDesktopInfo.currentDesktop]); + }); + + menuItem = menu.newMenuItem(virtualDesktopsMenu); + menuItem.text = i18n("&All Desktops"); + menuItem.checkable = true; + menuItem.checked = Qt.binding(function() { + return menu.visualParent && menu.get(atm.IsOnAllVirtualDesktops) === true; + }); + menuItem.clicked.connect(function() { + tasksModel.requestVirtualDesktops(menu.modelIndex, []); + }); + backend.setActionGroup(menuItem.action); + + menu.newSeparator(virtualDesktopsMenu); + + for (var i = 0; i < virtualDesktopInfo.desktopNames.length; ++i) { + menuItem = menu.newMenuItem(virtualDesktopsMenu); + menuItem.text = i18nc("1 = number of desktop, 2 = desktop name", "&%1 %2", i + 1, virtualDesktopInfo.desktopNames[i]); + menuItem.checkable = true; + menuItem.checked = Qt.binding((function(i) { + return function() { return menu.visualParent && menu.get(atm.VirtualDesktops).indexOf(virtualDesktopInfo.desktopIds[i]) > -1 }; + })(i)); + menuItem.clicked.connect((function(i) { + return function() { return tasksModel.requestVirtualDesktops(menu.modelIndex, [virtualDesktopInfo.desktopIds[i]]); }; + })(i)); + backend.setActionGroup(menuItem.action); + } + + menu.newSeparator(virtualDesktopsMenu); + + menuItem = menu.newMenuItem(virtualDesktopsMenu); + menuItem.text = i18n("&New Desktop"); + menuItem.clicked.connect(function() { + tasksModel.requestNewVirtualDesktop(menu.modelIndex); + }); + } + + Component.onCompleted: refresh() + } + } + + PlasmaComponents.MenuItem { + id: activitiesDesktopsMenuItem + + visible: activityInfo.numberOfRunningActivities > 1 + && (visualParent && !get(atm.IsLauncher) + && !get(atm.IsStartup)) + + enabled: visible + + text: i18n("Show in &Activities") + icon: "activities" + + Connections { + target: activityInfo + + function onNumberOfRunningActivitiesChanged() { + activitiesDesktopsMenu.refresh() + } + } + + PlasmaComponents.ContextMenu { + id: activitiesDesktopsMenu + + visualParent: activitiesDesktopsMenuItem.action + + function refresh() { + clearMenuItems(); + + if (activityInfo.numberOfRunningActivities <= 1) { + return; + } + + var menuItem = menu.newMenuItem(activitiesDesktopsMenu); + menuItem.text = i18n("Add To Current Activity"); + menuItem.enabled = Qt.binding(function() { + return menu.visualParent && menu.get(atm.Activities).length > 0 && + menu.get(atm.Activities).indexOf(activityInfo.currentActivity) < 0; + }); + menuItem.clicked.connect(function() { + tasksModel.requestActivities(menu.modelIndex, menu.get(atm.Activities).concat(activityInfo.currentActivity)); + }); + + menuItem = menu.newMenuItem(activitiesDesktopsMenu); + menuItem.text = i18n("All Activities"); + menuItem.checkable = true; + menuItem.checked = Qt.binding(function() { + return menu.visualParent && menu.get(atm.Activities).length === 0; + }); + menuItem.toggled.connect(function(checked) { + let newActivities = []; // will cast to an empty QStringList i.e all activities + if (!checked) { + newActivities = new Array(activityInfo.currentActivity); + } + tasksModel.requestActivities(menu.modelIndex, newActivities); + }); + + menu.newSeparator(activitiesDesktopsMenu); + + var runningActivities = activityInfo.runningActivities(); + for (var i = 0; i < runningActivities.length; ++i) { + var activityId = runningActivities[i]; + + menuItem = menu.newMenuItem(activitiesDesktopsMenu); + menuItem.text = activityInfo.activityName(runningActivities[i]); + menuItem.checkable = true; + menuItem.checked = Qt.binding( (function(activityId) { + return function() { + return menu.visualParent && menu.get(atm.Activities).indexOf(activityId) >= 0; + }; + })(activityId)); + menuItem.toggled.connect((function(activityId) { + return function (checked) { + var newActivities = menu.get(atm.Activities); + if (checked) { + newActivities = newActivities.concat(activityId); + } else { + var index = newActivities.indexOf(activityId) + if (index < 0) { + return; + } + + newActivities.splice(index, 1); + } + return tasksModel.requestActivities(menu.modelIndex, newActivities); + }; + })(activityId)); + } + + menu.newSeparator(activitiesDesktopsMenu); + + for (var i = 0; i < runningActivities.length; ++i) { + var activityId = runningActivities[i]; + var onActivities = menu.get(atm.Activities); + + // if the task is on a single activity, don't insert a "move to" item for that activity + if(onActivities.length == 1 && onActivities[0] == activityId) { + continue; + } + + menuItem = menu.newMenuItem(activitiesDesktopsMenu); + menuItem.text = i18n("Move to %1", activityInfo.activityName(activityId)) + menuItem.clicked.connect((function(activityId) { + return function () { + return tasksModel.requestActivities(menu.modelIndex, [activityId]); + }; + })(activityId)); + } + + menu.newSeparator(activitiesDesktopsMenu); + } + + Component.onCompleted: refresh() + } + } + + PlasmaComponents.MenuItem { + id: launcherToggleAction + + visible: visualParent + && get(atm.IsLauncher) !== true + && get(atm.IsStartup) !== true + && plasmoid.immutability !== PlasmaCore.Types.SystemImmutable + && (activityInfo.numberOfRunningActivities < 2) + && !doesBelongToCurrentActivity() + + enabled: visualParent && get(atm.LauncherUrlWithoutIcon) != "" + + text: i18n("&Pin to Task Manager") + icon: "window-pin" + + function doesBelongToCurrentActivity() { + return tasksModel.launcherActivities(get(atm.LauncherUrlWithoutIcon)).some(function(activity) { + return activity === activityInfo.currentActivity || activity === activityInfo.nullUuid; + }); + } + + onClicked: { + tasksModel.requestAddLauncher(get(atm.LauncherUrl)); + } + } + + PlasmaComponents.MenuItem { + id: showLauncherInActivitiesItem + + text: i18n("&Pin to Task Manager") + icon: "window-pin" + + visible: visualParent + && get(atm.IsStartup) !== true + && plasmoid.immutability !== PlasmaCore.Types.SystemImmutable + && (activityInfo.numberOfRunningActivities >= 2) + + Connections { + target: activityInfo + function onNumberOfRunningActivitiesChanged() { + activitiesDesktopsMenu.refresh() + } + } + + PlasmaComponents.ContextMenu { + id: activitiesLaunchersMenu + visualParent: showLauncherInActivitiesItem.action + + function refresh() { + clearMenuItems(); + + if (menu.visualParent === null) return; + + var createNewItem = function(id, title, url, activities) { + var result = menu.newMenuItem(activitiesLaunchersMenu); + result.text = title; + + result.visible = true; + result.checkable = true; + + result.checked = activities.some(function(activity) { return activity === id }); + + result.clicked.connect( + function() { + if (result.checked) { + tasksModel.requestAddLauncherToActivity(url, id); + } else { + tasksModel.requestRemoveLauncherFromActivity(url, id); + } + } + ); + + return result; + } + + if (menu.visualParent === null) return; + + var url = menu.get(atm.LauncherUrlWithoutIcon); + + var activities = tasksModel.launcherActivities(url); + + createNewItem(activityInfo.nullUuid, i18n("On All Activities"), url, activities); + + if (activityInfo.numberOfRunningActivities <= 1) { + return; + } + + createNewItem(activityInfo.currentActivity, i18n("On The Current Activity"), url, activities); + + menu.newSeparator(activitiesLaunchersMenu); + + var runningActivities = activityInfo.runningActivities(); + + runningActivities.forEach(function(id) { + createNewItem(id, activityInfo.activityName(id), url, activities); + }); + } + + Component.onCompleted: { + menu.onVisualParentChanged.connect(refresh); + refresh(); + } + } + } + + PlasmaComponents.MenuItem { + visible: (visualParent + && plasmoid.immutability !== PlasmaCore.Types.SystemImmutable + && !launcherToggleAction.visible + && activityInfo.numberOfRunningActivities < 2) + + text: i18n("Unpin from Task Manager") + icon: "window-unpin" + + onClicked: { + tasksModel.requestRemoveLauncher(get(atm.LauncherUrlWithoutIcon)); + } + } + + PlasmaComponents.MenuItem { + id: moreActionsMenuItem + + visible: (visualParent && get(atm.IsLauncher) !== true && get(atm.IsStartup) !== true) + + enabled: visible + + text: i18n("More") + icon: "view-more-symbolic" + + PlasmaComponents.ContextMenu { + visualParent: moreActionsMenuItem.action + + PlasmaComponents.MenuItem { + enabled: menu.visualParent && menu.get(atm.IsMovable) === true + + text: i18n("&Move") + icon: "transform-move" + + onClicked: tasksModel.requestMove(menu.modelIndex) + } + + PlasmaComponents.MenuItem { + enabled: menu.visualParent && menu.get(atm.IsResizable) === true + + text: i18n("Re&size") + icon: "transform-scale" + + onClicked: tasksModel.requestResize(menu.modelIndex) + } + + PlasmaComponents.MenuItem { + visible: (menu.visualParent && get(atm.IsLauncher) !== true && get(atm.IsStartup) !== true) + + enabled: menu.visualParent && get(atm.IsMaximizable) === true + + checkable: true + checked: menu.visualParent && get(atm.IsMaximized) === true + + text: i18n("Ma&ximize") + icon: "window-maximize" + + onClicked: tasksModel.requestToggleMaximized(modelIndex) + } + + PlasmaComponents.MenuItem { + visible: (menu.visualParent && get(atm.IsLauncher) !== true && get(atm.IsStartup) !== true) + + enabled: menu.visualParent && get(atm.IsMinimizable) === true + + checkable: true + checked: menu.visualParent && get(atm.IsMinimized) === true + + text: i18n("Mi&nimize") + icon: "window-minimize" + + onClicked: tasksModel.requestToggleMinimized(modelIndex) + } + + PlasmaComponents.MenuItem { + checkable: true + checked: menu.visualParent && menu.get(atm.IsKeepAbove) === true + + text: i18n("Keep &Above Others") + icon: "window-keep-above" + + onClicked: tasksModel.requestToggleKeepAbove(menu.modelIndex) + } + + PlasmaComponents.MenuItem { + checkable: true + checked: menu.visualParent && menu.get(atm.IsKeepBelow) === true + + text: i18n("Keep &Below Others") + icon: "window-keep-below" + + onClicked: tasksModel.requestToggleKeepBelow(menu.modelIndex) + } + + PlasmaComponents.MenuItem { + enabled: menu.visualParent && menu.get(atm.IsFullScreenable) === true + + checkable: true + checked: menu.visualParent && menu.get(atm.IsFullScreen) === true + + text: i18n("&Fullscreen") + icon: "view-fullscreen" + + onClicked: tasksModel.requestToggleFullScreen(menu.modelIndex) + } + + PlasmaComponents.MenuItem { + enabled: menu.visualParent && menu.get(atm.IsShadeable) === true + + checkable: true + checked: menu.visualParent && menu.get(atm.IsShaded) === true + + text: i18n("&Shade") + icon: "window-shade" + + onClicked: tasksModel.requestToggleShaded(menu.modelIndex) + } + + PlasmaComponents.MenuItem { + separator: true + } + + PlasmaComponents.MenuItem { + visible: (plasmoid.configuration.groupingStrategy !== 0) && menu.get(atm.IsWindow) === true + + checkable: true + checked: menu.visualParent && menu.get(atm.IsGroupable) === true + + text: i18n("Allow this program to be grouped") + icon: "view-group" + + onClicked: tasksModel.requestToggleGrouping(menu.modelIndex) + } + + PlasmaComponents.MenuItem { + separator: true + } + + PlasmaComponents.MenuItem { + property QtObject configureAction: null + + enabled: configureAction && configureAction.enabled + visible: configureAction && configureAction.visible + + text: configureAction ? configureAction.text : "" + icon: configureAction ? configureAction.icon : "" + + onClicked: configureAction.trigger() + + Component.onCompleted: configureAction = plasmoid.action("configure") + } + + PlasmaComponents.MenuItem { + property QtObject alternativesAction: null + + enabled: alternativesAction && alternativesAction.enabled + visible: alternativesAction && alternativesAction.visible + + text: alternativesAction ? alternativesAction.text : "" + icon: alternativesAction ? alternativesAction.icon : "" + + onClicked: alternativesAction.trigger() + + Component.onCompleted: alternativesAction = plasmoid.action("alternatives") + } + } + } + + PlasmaComponents.MenuItem { separator: true } + + PlasmaComponents.MenuItem { + id: closeWindowItem + visible: (visualParent && get(atm.IsLauncher) !== true && get(atm.IsStartup) !== true) + + enabled: visualParent && get(atm.IsClosable) === true + + text: i18n("&Close") + icon: "window-close" + + onClicked: tasksModel.requestClose(modelIndex) + } +} diff --git a/contents/ui/GroupDialog.qml b/contents/ui/GroupDialog.qml new file mode 100644 index 00000000..539de70a --- /dev/null +++ b/contents/ui/GroupDialog.qml @@ -0,0 +1,147 @@ +/* + SPDX-FileCopyrightText: 2012-2013 Eike Hein + SPDX-FileCopyrightText: 2021 Fushan Wen + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 +// Deliberately imported after QtQuick to avoid missing restoreMode property in Binding. Fix in Qt 6. +import QtQml 2.15 +import QtQml.Models 2.15 +import QtQuick.Window 2.15 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 3.0 as PlasmaComponents3 +import org.kde.draganddrop 2.0 + +import "code/layout.js" as LayoutManager + +PlasmaCore.Dialog { + id: groupDialog + visible: true + + type: PlasmaCore.Dialog.PopupMenu + flags: Qt.WindowStaysOnTopHint + hideOnWindowDeactivate: true + location: plasmoid.location + + readonly property int preferredWidth: Screen.width / (3 * Screen.devicePixelRatio) + readonly property int preferredHeight: Screen.height / (2 * Screen.devicePixelRatio) + readonly property int contentWidth: mainItem.width // No padding here to avoid text elide. + + property alias overflowing: scrollView.overflowing + property var _oldAppletStatus: PlasmaCore.Types.UnknownStatus + + function findActiveTaskIndex() { + if (!tasksModel.activeTask) { + return; + } + for (let i = 0; i < groupListView.count; i++) { + if (tasksModel.makeModelIndex(visualParent.itemIndex, i) === tasksModel.activeTask) { + groupListView.positionViewAtIndex(i, ListView.Contain); // Prevent visual glitches + groupListView.currentIndex = i; + return; + } + } + } + + + mainItem: MouseHandler { + id: mouseHandler + width: Math.min(groupDialog.preferredWidth, Math.max(groupListView.maxWidth, groupDialog.visualParent.width)) + height: Math.min(groupDialog.preferredHeight, groupListView.maxHeight) + + target: groupListView + handleWheelEvents: !scrollView.overflowing + isGroupDialog: true + + Keys.onEscapePressed: groupDialog.visible = false + + PlasmaComponents3.ScrollView { + id: scrollView + anchors.fill: parent + readonly property bool overflowing: leftPadding > 0 || rightPadding > 0 // Scrollbar is visible + + PlasmaComponents3.ScrollBar.horizontal.policy: PlasmaComponents3.ScrollBar.AlwaysOff + + ListView { + id: groupListView + + readonly property int maxWidth: groupFilter.maxTextWidth + + LayoutManager.horizontalMargins() + + PlasmaCore.Units.iconSizes.medium + + 2 * (LayoutManager.labelMargin + LayoutManager.iconMargin) + + scrollView.leftPadding + scrollView.rightPadding + // Use groupFilter.count because sometimes count is not updated in time (BUG 446105) + readonly property int maxHeight: groupFilter.count * (LayoutManager.verticalMargins() + Math.max(theme.mSize(theme.defaultFont).height, PlasmaCore.Units.iconSizes.medium)) + + model: DelegateModel { + id: groupFilter + + readonly property TextMetrics textMetrics: TextMetrics {} + property int maxTextWidth: 0 + + model: tasksModel + rootIndex: tasksModel.makeModelIndex(groupDialog.visualParent.itemIndex) + delegate: Task { + width: groupListView.width + visible: true + inPopup: true + + ListView.onRemove: Qt.callLater(groupFilter.updateMaxTextWidth) + Connections { + enabled: index < 20 // 20 is based on performance considerations. + + function onLabelTextChanged() { // ListView.onAdd included + if (groupFilter.maxTextWidth === 0) { + // Update immediately to avoid shrinking + groupFilter.updateMaxTextWidth(); + } else { + Qt.callLater(groupFilter.updateMaxTextWidth); + } + } + } + } + + function updateMaxTextWidth() { + let tempMaxTextWidth = 0; + // 20 is based on performance considerations. + for (let i = 0; i < Math.min(count, 20); i++) { + textMetrics.text = items.get(i).model.display; + if (textMetrics.boundingRect.width > tempMaxTextWidth) { + tempMaxTextWidth = textMetrics.boundingRect.width; + } + } + maxTextWidth = tempMaxTextWidth; + } + } + + reuseItems: false + + onCountChanged: { + if (count > 0) { + backend.cancelHighlightWindows() + } else { + groupDialog.visible = false; + } + } + } + } + } + + onVisibleChanged: { + if (visible) { + _oldAppletStatus = plasmoid.status; + plasmoid.status = PlasmaCore.Types.RequiresAttentionStatus; + + groupDialog.requestActivate(); + groupListView.forceActiveFocus(); // Active focus on ListView so keyboard navigation can work. + Qt.callLater(findActiveTaskIndex); + } else { + plasmoid.status = _oldAppletStatus; + tasks.groupDialog = null; + destroy(); + } + } +} diff --git a/contents/ui/GroupExpanderOverlay.qml b/contents/ui/GroupExpanderOverlay.qml new file mode 100644 index 00000000..d90b0b03 --- /dev/null +++ b/contents/ui/GroupExpanderOverlay.qml @@ -0,0 +1,82 @@ +/* + SPDX-FileCopyrightText: 2012-2013 Eike Hein + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 + +import org.kde.plasma.core 2.0 as PlasmaCore + +PlasmaCore.SvgItem { + id: arrow + + anchors { + bottom: arrow.parent.bottom + horizontalCenter: iconBox.horizontalCenter + } + + visible: parent.m.IsGroupParent === true + + states: [ + State { + name: "top" + when: plasmoid.location === PlasmaCore.Types.TopEdge + AnchorChanges { + target: arrow + anchors.top: arrow.parent.top + anchors.left: undefined + anchors.right: undefined + anchors.bottom: undefined + anchors.horizontalCenter: iconBox.horizontalCenter + anchors.verticalCenter: undefined + } + }, + State { + name: "left" + when: plasmoid.location === PlasmaCore.Types.LeftEdge + AnchorChanges { + target: arrow + anchors.top: undefined + anchors.left: arrow.parent.left + anchors.right: undefined + anchors.bottom: undefined + anchors.horizontalCenter: undefined + anchors.verticalCenter: iconBox.verticalCenter + } + }, + State { + name: "right" + when: plasmoid.location === PlasmaCore.Types.RightEdge + AnchorChanges { + target: arrow + anchors.top: undefined + anchors.left: undefined + anchors.right: arrow.parent.right + anchors.bottom: undefined + anchors.horizontalCenter: undefined + anchors.verticalCenter: iconBox.verticalCenter + } + } + ] + + implicitWidth: Math.min(naturalSize.width, iconBox.width) + implicitHeight: Math.min(naturalSize.height, iconBox.width) + + svg: taskSvg + elementId: elementForLocation() + + function elementForLocation() { + switch (plasmoid.location) { + case PlasmaCore.Types.LeftEdge: + return "group-expander-left"; + case PlasmaCore.Types.TopEdge: + return "group-expander-top"; + case PlasmaCore.Types.RightEdge: + return "group-expander-right"; + case PlasmaCore.Types.BottomEdge: + default: + return "group-expander-bottom"; + } + } +} diff --git a/contents/ui/IndicatorOverlay.qml b/contents/ui/IndicatorOverlay.qml new file mode 100644 index 00000000..ef503dbc --- /dev/null +++ b/contents/ui/IndicatorOverlay.qml @@ -0,0 +1,137 @@ +import QtQuick 2.15 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents // for DialogStatus +import org.kde.plasma.components 3.0 as PlasmaComponents3 +import org.kde.draganddrop 2.0 +import org.kde.kirigami 2.20 as Kirigami + +import QtGraphicalEffects 1.0 + + +import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet + +import "code/layout.js" as LayoutManager +import "code/tools.js" as TaskTools + +Item{ + id: root + readonly property int thickness: isVertical ? width - screenEdgeMargin : height - screenEdgeMargin + readonly property int screenEdgeMargin: 0 + + readonly property bool isHorizontal: plasmoid.formFactor === PlasmaCore.Types.Horizontal + readonly property bool isVertical: plasmoid.formFactor === PlasmaCore.Types.Vertical + + readonly property bool isMetroStyle: plasmoid.configuration.indicatorStyle === 0 + readonly property bool isCilioraStyle: plasmoid.configuration.indicatorStyle === 1 + readonly property bool isDashesStyle: plasmoid.configuration.indicatorStyle === 2 + + Rectangle{ + anchors.fill: parent + color: white + height: 20 + width: 20 + } +} + + /*GridLayout { + id: boxesLayout + anchors.topMargin: plasmoid.location === PlasmaCore.Types.TopEdge ? root.screenEdgeMargin : 0 + anchors.bottomMargin: plasmoid.location === PlasmaCore.Types.BottomEdge ? root.screenEdgeMargin : 0 + anchors.leftMargin: plasmoid.location === PlasmaCore.Types.LeftEdge ? root.screenEdgeMargin : 0 + anchors.rightMargin: plasmoid.location === PlasmaCore.Types.RightEdge ? root.screenEdgeMargin : 0 + + width: isDashesStyle && isHorizontal ? undefined : (isHorizontal ? parent.width : undefined) + height: isDashesStyle && isVertical ? undefined: (isVertical ? parent.height : undefined) + + rows: isHorizontal ? 1 : -1 + columns: isVertical ? 1 : -1 + + rowSpacing: isVertical ? spacing : 0 + columnSpacing: isHorizontal ? spacing : 0 + + readonly property int spacing: PlasmaCore.Units.gridUnit + readonly property int thickness: plasmoid.configuration.indicatorSize + + readonly property int minLength: isCilioraStyle ? thickness : 2*thickness + + + } + + Repeater { + model: { + //console.log(model) + if (task.m.model.IsLauncher) { + return task.m.model.isActive ? 1 : 0 + } + + return Math.min(task.m.model.childCount, maxStates); + } + + readonly property int maxStates: isMetroStyle ? 2 : 4 + + Rectangle { + id: stateRect + + Kirigami.ImageColors { + id: imageColors + source: task.m.model.decoration + } + Layout.fillWidth: isHorizontal && isFirst && !isDashesStyle + Layout.fillHeight: isVertical && isFirst && !isDashesStyle + + Layout.minimumWidth: isHorizontal ? boxesLayout.minLength : boxesLayout.thickness + Layout.maximumWidth: isHorizontal && isFirst ? -1 : (isHorizontal ? boxesLayout.minLength : boxesLayout.thickness) + + Layout.minimumHeight: isHorizontal ? boxesLayout.thickness : boxesLayout.minLength + Layout.maximumHeight: isVertical && isFirst ? -1 : (isVertical ? boxesLayout.minLength : boxesLayout.thickness) + + color: white//!isFirst ? imagesColors.highlight : imageColors.dominant + + readonly property bool isFirst: index === 0 + } + } + + /*states:[ + State { + name: "bottom" + when: plasmoid.configuration.indicatorLocation === 0 + + AnchorChanges { + target: boxesLayout + anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:parent.right; + horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} + } + }, + State { + name: "left" + when: plasmoid.configuration.indicatorLocation === 1 + + AnchorChanges { + target: boxesLayout + anchors{ top:parent.top; bottom:parent.bottom; left:parent.left; right:undefined; + horizontalCenter:undefined; verticalCenter:parent.verticalCenter} + } + }, + State { + name: "right" + when: plasmoid.configuration.indicatorLocation === 2 + + AnchorChanges { + target: boxesLayout + anchors{ top:parent.top; bottom:parent.left; left:undefined; right:parent.right; + horizontalCenter:undefined; verticalCenter:parent.verticalCenter} + } + }, + State { + name: "top" + when: plasmoid.configuration.indicatorLocation === 3 + + AnchorChanges { + target: boxesLayout + anchors{ top:parent.top; bottom:undefined; left:parent.left; right:parent.right; + horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} + } + } + ]*/ +} \ No newline at end of file diff --git a/contents/ui/MouseHandler.qml b/contents/ui/MouseHandler.qml new file mode 100644 index 00000000..6bf40e0c --- /dev/null +++ b/contents/ui/MouseHandler.qml @@ -0,0 +1,186 @@ +/* + SPDX-FileCopyrightText: 2012-2016 Eike Hein + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 + +import org.kde.draganddrop 2.0 + +import org.kde.taskmanager 0.1 as TaskManager + +import "code/tools.js" as TaskTools + +Item { + signal urlsDropped(var urls) + + property Item target + property Item ignoredItem + property bool isGroupDialog: false + property bool moved: false + + property alias hoveredItem: dropHandler.hoveredItem + property alias handleWheelEvents: wheelHandler.active + + Timer { + id: ignoreItemTimer + + repeat: false + interval: 750 + + onTriggered: { + ignoredItem = null; + } + } + + Connections { + target: tasks + + function onDragSourceChanged() { + if (!dragSource) { + ignoredItem = null; + ignoreItemTimer.stop(); + } + } + } + + DropArea { + id: dropHandler + + anchors.fill: parent + + preventStealing: true; + + property Item hoveredItem + + //ignore anything that is neither internal to TaskManager or a URL list + onDragEnter: { + if (event.mimeData.formats.indexOf("text/x-plasmoidservicename") >= 0) { + event.ignore(); + } + } + + onDragMove: { + if (target.animating) { + return; + } + + let above; + if (isGroupDialog) { + above = target.itemAt(event.x, event.y); + } else { + above = target.childAt(event.x, event.y); + } + + if (!above) { + hoveredItem = null; + activationTimer.stop(); + + return; + } + + // If we're mixing launcher tasks with other tasks and are moving + // a (small) launcher task across a non-launcher task, don't allow + // the latter to be the move target twice in a row for a while, as + // it will naturally be moved underneath the cursor as result of the + // initial move, due to being far larger than the launcher delegate. + // TODO: This restriction (minus the timer, which improves things) + // has been proven out in the EITM fork, but could be improved later + // by tracking the cursor movement vector and allowing the drag if + // the movement direction has reversed, establishing user intent to + // move back. + if (!plasmoid.configuration.separateLaunchers && tasks.dragSource != null + && tasks.dragSource.m.IsLauncher === true && above.m.IsLauncher !== true + && above === ignoredItem) { + return; + } else { + ignoredItem = null; + } + + if (tasksModel.sortMode === TaskManager.TasksModel.SortManual && tasks.dragSource) { + // Reject drags between different TaskList instances. + if (tasks.dragSource.parent !== above.parent) { + return; + } + + var insertAt = TaskTools.insertIndexAt(above, event.x, event.y); + + if (tasks.dragSource !== above && tasks.dragSource.itemIndex !== insertAt) { + if (!!tasks.groupDialog) { + tasksModel.move(tasks.dragSource.itemIndex, insertAt, + tasksModel.makeModelIndex(tasks.groupDialog.visualParent.itemIndex)); + } else { + tasksModel.move(tasks.dragSource.itemIndex, insertAt); + } + + ignoredItem = above; + ignoreItemTimer.restart(); + } + } else if (!tasks.dragSource && hoveredItem !== above) { + hoveredItem = above; + activationTimer.restart(); + } + } + + onDragLeave: { + hoveredItem = null; + activationTimer.stop(); + } + + onDrop: { + // Reject internal drops. + if (event.mimeData.formats.indexOf("application/x-orgkdeplasmataskmanager_taskbuttonitem") >= 0) { + event.ignore(); + return; + } + + // Reject plasmoid drops. + if (event.mimeData.formats.indexOf("text/x-plasmoidservicename") >= 0) { + event.ignore(); + return; + } + + if (event.mimeData.hasUrls) { + parent.urlsDropped(event.mimeData.urls); + return; + } + } + + Timer { + id: activationTimer + + interval: 250 + repeat: false + + onTriggered: { + if (parent.hoveredItem.m.IsGroupParent === true) { + TaskTools.createGroupDialog(parent.hoveredItem); + } else if (parent.hoveredItem.m.IsLauncher !== true) { + tasksModel.requestActivate(parent.hoveredItem.modelIndex()); + } + } + } + } + + MouseArea { + id: wheelHandler + + anchors.fill: parent + + enabled: active && plasmoid.configuration.wheelEnabled + + property bool active: true + property int wheelDelta: 0; + + + onWheel: { + if (!active) { + wheel.accepted = false; + return; + } + + wheelDelta = TaskTools.wheelActivateNextPrevTask(null, wheelDelta, wheel.angleDelta.y); + } + } +} diff --git a/contents/ui/PipeWireThumbnail.qml b/contents/ui/PipeWireThumbnail.qml new file mode 100644 index 00000000..fbc94236 --- /dev/null +++ b/contents/ui/PipeWireThumbnail.qml @@ -0,0 +1,40 @@ +/* + SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +import QtQuick 2.15 +import QtQuick.Window 2.15 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.taskmanager 0.1 as TaskManager + +// opacity doesn't work in the root item +Item { + anchors.fill: parent + + TaskManager.PipeWireSourceItem { + id: pipeWireSourceItem + + enabled: false // Must be set in pipewiresourceitem.cpp so opacity animation can work + visible: waylandItem.nodeId > 0 + nodeId: waylandItem.nodeId + + anchors.fill: parent + + opacity: enabled ? 1 : 0 + + TaskManager.ScreencastingRequest { + id: waylandItem + uuid: toolTipDelegate.Window.visibility === Window.Hidden ? "" : thumbnailSourceItem.winId + } + + Behavior on opacity { + OpacityAnimator { + duration: PlasmaCore.Units.longDuration + easing.type: Easing.OutCubic + } + } + } +} diff --git a/contents/ui/PlayerController.qml b/contents/ui/PlayerController.qml new file mode 100644 index 00000000..61dc8688 --- /dev/null +++ b/contents/ui/PlayerController.qml @@ -0,0 +1,121 @@ +/* + SPDX-FileCopyrightText: 2013 Sebastian Kügler + SPDX-FileCopyrightText: 2014 Martin Gräßlin + SPDX-FileCopyrightText: 2016 Kai Uwe Broulik + SPDX-FileCopyrightText: 2017 Roman Gilg + SPDX-FileCopyrightText: 2020 Nate Graham + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +import QtQuick 2.15 +import QtQuick.Layouts 1.15 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 3.0 as PlasmaComponents3 +import org.kde.plasma.extras 2.0 as PlasmaExtras + +RowLayout { + enabled: !!playerData.CanControl + + readonly property string mprisSourceName: mpris2Source.sourceNameForLauncherUrl(launcherUrl, appPid) + readonly property var playerData: mprisSourceName != "" ? mpris2Source.data[mprisSourceName] : 0 + readonly property bool playing: !!(playerData.PlaybackStatus === "Playing") + + readonly property var currentMetadata: !!playerData ? playerData.Metadata : "" + + readonly property string track: { + const xesamTitle = currentMetadata["xesam:title"] + if (xesamTitle) { + return xesamTitle; + } + // if no track title is given, print out the file name + const xesamUrl = currentMetadata["xesam:url"] ? currentMetadata["xesam:url"].toString() : "" + if (!xesamUrl) { + return ""; + } + const lastSlashPos = xesamUrl.lastIndexOf('/') + if (lastSlashPos < 0) { + return ""; + } + const lastUrlPart = xesamUrl.substring(lastSlashPos + 1) + return decodeURIComponent(lastUrlPart) || ""; + } + readonly property string artist: currentMetadata["xesam:artist"] || "" + readonly property string albumArt: currentMetadata["mpris:artUrl"] || "" + + ColumnLayout { + Layout.fillWidth: true + Layout.topMargin: PlasmaCore.Units.smallSpacing + Layout.bottomMargin: PlasmaCore.Units.smallSpacing + Layout.rightMargin: isWin ? PlasmaCore.Units.smallSpacing : PlasmaCore.Units.largeSpacing + spacing: 0 + + ScrollableTextWrapper { + id: songTextWrapper + + Layout.fillWidth: true + Layout.preferredHeight: songText.height + implicitWidth: songText.implicitWidth + + PlasmaComponents3.Label { + id: songText + parent: songTextWrapper + width: parent.width + height: undefined + lineHeight: 1 + maximumLineCount: artistText.visible? 1 : 2 + wrapMode: Text.NoWrap + elide: parent.state ? Text.ElideNone : Text.ElideRight + text: track + textFormat: Text.PlainText + } + } + + ScrollableTextWrapper { + id: artistTextWrapper + + Layout.fillWidth: true + Layout.preferredHeight: artistText.height + implicitWidth: artistText.implicitWidth + visible: artistText.text !== "" + + PlasmaExtras.DescriptiveLabel { + id: artistText + parent: artistTextWrapper + width: parent.width + height: undefined + wrapMode: Text.NoWrap + lineHeight: 1 + elide: parent.state ? Text.ElideNone : Text.ElideRight + text: artist + font: PlasmaCore.Theme.smallestFont + textFormat: Text.PlainText + } + } + } + + PlasmaComponents3.ToolButton { + enabled: !!playerData.CanGoPrevious + icon.name: LayoutMirroring.enabled ? "media-skip-forward" : "media-skip-backward" + onClicked: mpris2Source.goPrevious(mprisSourceName) + } + + PlasmaComponents3.ToolButton { + enabled: playing ? !!playerData.CanPause : !!playerData.CanPlay + icon.name: playing ? "media-playback-pause" : "media-playback-start" + onClicked: { + if (!playing) { + mpris2Source.play(mprisSourceName); + } else { + mpris2Source.pause(mprisSourceName); + } + } + } + + PlasmaComponents3.ToolButton { + enabled: !!playerData.CanGoNext + icon.name: LayoutMirroring.enabled ? "media-skip-backward" : "media-skip-forward" + onClicked: mpris2Source.goNext(mprisSourceName) + } +} diff --git a/contents/ui/PulseAudio.qml b/contents/ui/PulseAudio.qml new file mode 100644 index 00000000..83ebe070 --- /dev/null +++ b/contents/ui/PulseAudio.qml @@ -0,0 +1,104 @@ +/* + SPDX-FileCopyrightText: 2017 Kai Uwe Broulik + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 + +import org.kde.plasma.private.volume 0.1 + +QtObject { + id: pulseAudio + + signal streamsChanged + + // It's a JS object so we can do key lookup and don't need to take care of filtering duplicates. + property var pidMatches: ({}) + + // TODO Evict cache at some point, preferably if all instances of an application closed. + function registerPidMatch(appName) { + if (!hasPidMatch(appName)) { + pidMatches[appName] = true; + + // In case this match is new, notify that streams might have changed. + // This way we also catch the case when the non-playing instance + // shows up first. + // Only notify if we changed to avoid infinite recursion. + streamsChanged(); + } + } + + function hasPidMatch(appName) { + return pidMatches[appName] === true; + } + + function findStreams(key, value) { + var streams = [] + for (var i = 0, length = instantiator.count; i < length; ++i) { + var stream = instantiator.objectAt(i); + if (stream[key] === value) { + streams.push(stream); + } + } + return streams + } + + function streamsForAppName(appName) { + return findStreams("appName", appName); + } + + function streamsForPid(pid) { + var streams = findStreams("pid", pid); + + if (streams.length === 0) { + for (var i = 0, length = instantiator.count; i < length; ++i) { + var stream = instantiator.objectAt(i); + + if (stream.parentPid === -1) { + stream.parentPid = backend.parentPid(stream.pid); + } + + if (stream.parentPid === pid) { + streams.push(stream); + } + } + } + + return streams; + } + + // QtObject has no default property, hence adding the Instantiator to one explicitly. + property var instantiator: Instantiator { + model: PulseObjectFilterModel { + filters: [ { role: "VirtualStream", value: false } ] + sourceModel: SinkInputModel {} + } + + delegate: QtObject { + id: delegate + required property var model + readonly property int pid: model.Client ? model.Client.properties["application.process.id"] : 0 + // Determined on demand. + property int parentPid: -1 + readonly property string appName: model.Client ? model.Client.properties["application.name"] : "" + readonly property bool muted: model.Muted + // whether there is nothing actually going on on that stream + readonly property bool corked: model.Corked + readonly property int volume: model.Volume + + function mute() { + model.Muted = true + } + function unmute() { + model.Muted = false + } + } + + onObjectAdded: pulseAudio.streamsChanged() + onObjectRemoved: pulseAudio.streamsChanged() + } + + readonly property int minimalVolume: PulseAudio.MinimalVolume + readonly property int normalVolume: PulseAudio.NormalVolume +} diff --git a/contents/ui/ScrollableTextWrapper.qml b/contents/ui/ScrollableTextWrapper.qml new file mode 100644 index 00000000..356a1d84 --- /dev/null +++ b/contents/ui/ScrollableTextWrapper.qml @@ -0,0 +1,53 @@ +/* + SPDX-FileCopyrightText: 2020 Tranter Madi + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +import QtQuick 2.15 + +MouseArea { + id: textWrapper + + default property Text textItem + + clip: textItem.elide === Text.ElideNone + hoverEnabled: true + + onContainsMouseChanged: { + if (!containsMouse) { + state = "" + } + } + + Timer { + id: timer + interval: 500 + running: textWrapper.containsMouse + onTriggered: { + if (textWrapper.width < textItem.implicitWidth) { + textWrapper.state = "ShowRight" + } + } + } + + states: [ + State { + name: "" + PropertyChanges { target: textItem; x: 0 } + }, + State { + name: "ShowRight" + PropertyChanges { target: textItem; x: textWrapper.width - textItem.implicitWidth } + } + ] + + transitions: Transition { + to: "ShowRight" + NumberAnimation { + target: textItem; properties: "x"; + easing.type: Easing.Linear; + duration: Math.abs(textItem.implicitWidth - textWrapper.width)*25 + } + } +} diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml new file mode 100644 index 00000000..60737868 --- /dev/null +++ b/contents/ui/Task.qml @@ -0,0 +1,843 @@ +/* + SPDX-FileCopyrightText: 2012-2013 Eike Hein + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents // for DialogStatus +import org.kde.plasma.components 3.0 as PlasmaComponents3 +import org.kde.draganddrop 2.0 +import org.kde.kirigami 2.20 as Kirigami + +import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet + +import QtQuick.Layouts 1.3 + + +import QtGraphicalEffects 1.15 + +import "code/layout.js" as LayoutManager +import "code/tools.js" as TaskTools + +MouseArea { + id: task + + activeFocusOnTab: true + + height: Math.max(theme.mSize(theme.defaultFont).height, PlasmaCore.Units.iconSizes.medium) + LayoutManager.verticalMargins() + + visible: false + + LayoutMirroring.enabled: (Qt.application.layoutDirection == Qt.RightToLeft) + LayoutMirroring.childrenInherit: (Qt.application.layoutDirection == Qt.RightToLeft) + + readonly property var m: model + + readonly property int pid: model.AppPid !== undefined ? model.AppPid : 0 + readonly property string appName: model.AppName || "" + readonly property variant winIdList: model.WinIdList + property int itemIndex: index + property bool inPopup: false + property bool isWindow: model.IsWindow === true + property int childCount: model.ChildCount !== undefined ? model.ChildCount : 0 + property int previousChildCount: 0 + property alias labelText: label.text + property bool pressed: false + property int pressX: -1 + property int pressY: -1 + property QtObject contextMenu: null + property int wheelDelta: 0 + readonly property bool smartLauncherEnabled: !inPopup && model.IsStartup !== true + property QtObject smartLauncherItem: null + property alias toolTipAreaItem: toolTipArea + property alias audioStreamIconLoaderItem: audioStreamIconLoader + + readonly property bool isMetro: plasmoid.configuration.indicatorStyle === 0 + readonly property bool isCiliora: plasmoid.configuration.indicatorStyle === 1 + readonly property bool isDashes: plasmoid.configuration.indicatorStyle === 2 + + property Item audioStreamOverlay + property var audioStreams: [] + property bool delayAudioStreamIndicator: false + readonly property bool audioIndicatorsEnabled: plasmoid.configuration.indicateAudioStreams + readonly property bool hasAudioStream: audioStreams.length > 0 + readonly property bool playingAudio: hasAudioStream && audioStreams.some(function (item) { + return !item.corked + }) + readonly property bool muted: hasAudioStream && audioStreams.every(function (item) { + return item.muted + }) + + readonly property bool highlighted: (inPopup && activeFocus) || (!inPopup && containsMouse) + || (task.contextMenu && task.contextMenu.status === PlasmaComponents.DialogStatus.Open) + || (!!tasks.groupDialog && tasks.groupDialog.visualParent === task) + + Accessible.name: model.display + Accessible.description: model.display ? i18n("Activate %1", model.display) : "" + Accessible.role: Accessible.Button + + + onHighlightedChanged: { + // ensure it doesn't get stuck with a window highlighted + backend.cancelHighlightWindows(); + } + + function showToolTip() { + toolTipArea.showToolTip(); + } + function hideToolTipTemporarily() { + toolTipArea.hideToolTip(); + } + + acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MidButton | Qt.BackButton | Qt.ForwardButton + + onPidChanged: updateAudioStreams({delay: false}) + onAppNameChanged: updateAudioStreams({delay: false}) + + onIsWindowChanged: { + if (isWindow) { + taskInitComponent.createObject(task); + } + } + + onChildCountChanged: { + if (childCount > previousChildCount) { + tasksModel.requestPublishDelegateGeometry(modelIndex(), backend.globalRect(task), task); + } + + previousChildCount = childCount; + } + + onItemIndexChanged: { + hideToolTipTemporarily(); + + if (!inPopup && !tasks.vertical + && (LayoutManager.calculateStripes() > 1 || !plasmoid.configuration.separateLaunchers)) { + tasks.requestLayout(); + } + } + + onContainsMouseChanged: { + if (containsMouse) { + if (inPopup) { + forceActiveFocus(); + } + } else { + pressed = false; + } + } + + onPressed: { + if (mouse.button == Qt.LeftButton || mouse.button == Qt.MidButton || mouse.button === Qt.BackButton || mouse.button === Qt.ForwardButton) { + pressed = true; + pressX = mouse.x; + pressY = mouse.y; + } else if (mouse.button == Qt.RightButton) { + // When we're a launcher, there's no window controls, so we can show all + // places without the menu getting super huge. + if (model.IsLauncher === true) { + showContextMenu({showAllPlaces: true}) + } else { + showContextMenu(); + } + } + } + + onPressAndHold: if (mouse.button === Qt.LeftButton) { + /* TODO: make press and hold to open menu exclusive to touch. + * I (ndavis) tried `if (lastDeviceType & ~(PointerDevice.Mouse | PointerDevice.TouchPad))` + * with a TapHandler. lastDeviceType was gotten from the EventPoint argument of the + * grabChanged() signal. ngraham said it wouldn't work because it was preventing single + * taps on touch. I didn't have a touch screen to test it with. + */ + // When we're a launcher, there's no window controls, so we can show all + // places without the menu getting super huge. + if (model.IsLauncher === true) { + showContextMenu({showAllPlaces: true}) + } else { + showContextMenu(); + } + } + + onReleased: { + if (pressed) { + if (mouse.button == Qt.MidButton) { + if (plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.NewInstance) { + tasksModel.requestNewInstance(modelIndex()); + } else if (plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.Close) { + tasks.taskClosedWithMouseMiddleButton = winIdList.slice() + tasksModel.requestClose(modelIndex()); + } else if (plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.ToggleMinimized) { + tasksModel.requestToggleMinimized(modelIndex()); + } else if (plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.ToggleGrouping) { + tasksModel.requestToggleGrouping(modelIndex()); + } else if (plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.BringToCurrentDesktop) { + tasksModel.requestVirtualDesktops(modelIndex(), [virtualDesktopInfo.currentDesktop]); + } + } else if (mouse.button == Qt.LeftButton) { + if (plasmoid.configuration.showToolTips && toolTipArea.active) { + hideToolTipTemporarily(); + } + TaskTools.activateTask(modelIndex(), model, mouse.modifiers, task); + } else if (mouse.button === Qt.BackButton || mouse.button === Qt.ForwardButton) { + var sourceName = mpris2Source.sourceNameForLauncherUrl(model.LauncherUrlWithoutIcon, model.AppPid); + if (sourceName) { + if (mouse.button === Qt.BackButton) { + mpris2Source.goPrevious(sourceName); + } else { + mpris2Source.goNext(sourceName); + } + } else { + mouse.accepted = false; + } + } + + backend.cancelHighlightWindows(); + } + + pressed = false; + pressX = -1; + pressY = -1; + } + + onPositionChanged: { + // mouse.button is always 0 here, hence checking with mouse.buttons + if (pressX != -1 && mouse.buttons == Qt.LeftButton && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) { + tasks.dragSource = task; + dragHelper.startDrag(task, model.MimeType, model.MimeData, + model.LauncherUrlWithoutIcon, model.decoration); + pressX = -1; + pressY = -1; + + return; + } + } + + onWheel: { + if (plasmoid.configuration.wheelEnabled && (!inPopup || !groupDialog.overflowing)) { + wheelDelta = TaskTools.wheelActivateNextPrevTask(task, wheelDelta, wheel.angleDelta.y); + } else { + wheel.accepted = false; + } + } + + onSmartLauncherEnabledChanged: { + if (smartLauncherEnabled && !smartLauncherItem) { + const smartLauncher = Qt.createQmlObject(` + import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet; + + TaskManagerApplet.SmartLauncherItem { } + `, task); + + smartLauncher.launcherUrl = Qt.binding(() => model.LauncherUrlWithoutIcon); + + smartLauncherItem = smartLauncher; + } + } + + onHasAudioStreamChanged: { + audioStreamIconLoader.active = hasAudioStream && audioIndicatorsEnabled; + } + + onAudioIndicatorsEnabledChanged: { + audioStreamIconLoader.active = hasAudioStream && audioIndicatorsEnabled; + } + + function hexToHSL(hex) { + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + let r = parseInt(result[1], 16); + let g = parseInt(result[2], 16); + let b = parseInt(result[3], 16); + r /= 255, g /= 255, b /= 255; + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2; + if(max == min){ + h = s = 0; // achromatic + }else{ + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch(max){ + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + var HSL = new Object(); + HSL['h']=h; + HSL['s']=s; + HSL['l']=l; + return HSL; + } + + Keys.onReturnPressed: TaskTools.activateTask(modelIndex(), model, event.modifiers, task) + Keys.onEnterPressed: Keys.onReturnPressed(event); + Keys.onSpacePressed: Keys.onReturnPressed(event); + + function modelIndex() { + return (inPopup ? tasksModel.makeModelIndex(groupDialog.visualParent.itemIndex, index) + : tasksModel.makeModelIndex(index)); + } + + function showContextMenu(args) { + toolTipArea.hideImmediately(); + contextMenu = tasks.createContextMenu(task, modelIndex(), args); + contextMenu.show(); + } + + function updateAudioStreams(args) { + if (args) { + // When the task just appeared (e.g. virtual desktop switch), show the audio indicator + // right away. Only when audio streams change during the lifetime of this task, delay + // showing that to avoid distraction. + delayAudioStreamIndicator = !!args.delay; + } + + var pa = pulseAudio.item; + if (!pa) { + task.audioStreams = []; + return; + } + + var streams = pa.streamsForPid(task.pid); + if (streams.length) { + pa.registerPidMatch(task.appName); + } else { + // We only want to fall back to appName matching if we never managed to map + // a PID to an audio stream window. Otherwise if you have two instances of + // an application, one playing and the other not, it will look up appName + // for the non-playing instance and erroneously show an indicator on both. + if (!pa.hasPidMatch(task.appName)) { + streams = pa.streamsForAppName(task.appName); + } + } + + task.audioStreams = streams; + } + + function toggleMuted() { + if (muted) { + task.audioStreams.forEach(function (item) { item.unmute(); }); + } else { + task.audioStreams.forEach(function (item) { item.mute(); }); + } + } + + Connections { + target: pulseAudio.item + ignoreUnknownSignals: true // Plasma-PA might not be available + function onStreamsChanged() { + task.updateAudioStreams({delay: true}) + } + } + + Component { + id: taskInitComponent + + Timer { + id: timer + + interval: PlasmaCore.Units.longDuration + repeat: false + + onTriggered: { + parent.hoverEnabled = true; + + if (parent.isWindow) { + tasksModel.requestPublishDelegateGeometry(parent.modelIndex(), + backend.globalRect(parent), parent); + } + + timer.destroy(); + } + + Component.onCompleted: timer.start() + } + } + PlasmaCore.FrameSvgItem { + id: frame + property color dominantColor: imageColors.dominant + Kirigami.ImageColors { + id: imageColors + source: model.decoration + } + + anchors { + fill: parent + + topMargin: (!tasks.vertical && taskList.rows > 1) ? LayoutManager.iconMargin : 0 + bottomMargin: (!tasks.vertical && taskList.rows > 1) ? LayoutManager.iconMargin : 0 + leftMargin: ((inPopup || tasks.vertical) && taskList.columns > 1) ? LayoutManager.iconMargin : 0 + rightMargin: ((inPopup || tasks.vertical) && taskList.columns > 1) ? LayoutManager.iconMargin : 0 + } + + imagePath: "widgets/tasks" + enabledBorders: plasmoid.configuration.useBorders ? 1 | 2 | 4 | 8 : 0 + property bool isHovered: task.highlighted && plasmoid.configuration.taskHoverEffect + property string basePrefix: "normal" + prefix: isHovered ? TaskTools.taskPrefixHovered(basePrefix) : TaskTools.taskPrefix(basePrefix) + + property Colorize colorOverride: colorOverride + Colorize { + id: colorOverride + anchors.fill: frame + source: parent + hue: hexToHSL(plasmoid.configuration.buttonColorizeDominant ? imageColors.dominant : plasmoid.configuration.buttonColorizeCustom).h + lightness: frame.isHovered ? hexToHSL(plasmoid.configuration.buttonColorizeDominant ? imageColors.dominant : plasmoid.configuration.buttonColorizeCustom).l - 0.5 : hexToHSL(plasmoid.configuration.buttonColorizeDominant ? imageColors.dominant : plasmoid.configuration.buttonColorizeCustom).l - 0.6 + saturation: hexToHSL(plasmoid.configuration.buttonColorizeDominant ? imageColors.dominant : plasmoid.configuration.buttonColorizeCustom).s + visible: plasmoid.configuration.buttonColorize ? frame.isHovered ? true : false : false + } + + Flow { + id: indicator + flow: Flow.LeftToRight + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + spacing: PlasmaCore.Units.smallSpacing + Repeater { + + model: { + + if(!plasmoid.configuration.indicatorsEnabled) + return 0; + if(task.parent.toString().includes('QQuickItem'))//Target only the main task items. + return 0; + /*for(var key in task) { + console.log(key) + console.log(task[key]) + }*/ //Kept for debugging + if(task.state === 'launcher') { + return 0; + } + return Math.min(task.childCount + 1, maxStates); + } + readonly property int maxStates: isMetro ? 2 : 4 + + Rectangle{ + id: stateRect + readonly property color decoColor: frame.dominantColor + readonly property int maxStates: isMetro ? 2 : 4 + readonly property bool isFirst: index === 0 + readonly property int adjust: plasmoid.configuration.indicatorShrink + readonly property int indicatorLength: plasmoid.configuration.indicatorLength + readonly property int spacing: PlasmaCore.Units.smallSpacing /2 + readonly property bool isVertical: { + if(plasmoid.formFactor === PlasmaCore.Types.Vertical && !plasmoid.configuration.indicatorOverride) + return true; + if(plasmoid.configuration.indicatorLocation === 1 || plasmoid.configuration.indicatorLocation === 2) + return true; + else{ + return false; + } + } + readonly property var computedVar: { + var height; + var width; + var colorCalc; + var colorEval = '#FFFFFF'; + var parentSize = !isVertical ? frame.width : frame.height; + var indicatorComputedSize; + var adjustment = isFirst ? adjust : 0 + if(plasmoid.configuration.indicatorDominantColor){ + colorEval = decoColor + } + if(plasmoid.configuration.indicatorAccentColor){ + colorEval = PlasmaCore.Theme.highlightColor + } + else if(!plasmoid.configuration.indicatorDominantColor && !plasmoid.configuration.indicatorAccentColor){ + colorEval = plasmoid.configuration.indicatorCustomColor + } + if(isFirst){//compute the size + switch(plasmoid.configuration.indicatorStyle){ + case 0: + indicatorComputedSize = parentSize - (Math.min(task.childCount, maxStates) * ((spacing + indicatorLength) / 2) + adjust) + break + case 1: + indicatorComputedSize = parentSize - (Math.min(task.childCount, maxStates) * ((spacing + indicatorLength)) + adjust) + break + case 2: + indicatorComputedSize = indicatorLength + break + default: + break + } + } + else { + indicatorComputedSize = indicatorLength + } + if(!isVertical){ + width = indicatorComputedSize; + height = plasmoid.configuration.indicatorSize + } + else{ + width = plasmoid.configuration.indicatorSize + height = indicatorComputedSize + } + if(!isFirst && plasmoid.configuration.indicatorStyle === 0) {//Metro specific handling + colorCalc = Qt.darker(colorEval, 1.2) + } + else { + colorCalc = colorEval + } + return {height: height, width: width, colorCalc: colorCalc} + } + width: computedVar.width + height: computedVar.height + color: computedVar.colorCalc + radius: (Math.max(width, height) / Math.min(width, height)) * (plasmoid.configuration.indicatorRadius / 100) + } + } + } + + PlasmaCore.ToolTipArea { + id: toolTipArea + + anchors.fill: parent + location: plasmoid.location + + enabled: plasmoid.configuration.showToolTips && !inPopup && !tasks.groupDialog && (tasks.toolTipOpenedByClick === task || tasks.toolTipOpenedByClick === null) + interactive: model.IsWindow === true || mainItem.hasPlayer + + // when the mouse leaves the tooltip area, a timer to hide is set for (timeout / 20) ms + // see plasma-framework/src/declarativeimports/core/tooltipdialog.cpp function dismiss() + // to compensate for that we multiply by 20 here, to get an effective leave timeout of 2s. + timeout: (tasks.toolTipOpenedByClick === task) ? 2000*20 : 4000 + + mainItem: (model.IsWindow === true) ? openWindowToolTipDelegate : pinnedAppToolTipDelegate + + onToolTipVisibleChanged: { + if (!toolTipVisible) { + tasks.toolTipOpenedByClick = null; + } + } + + onContainsMouseChanged: if (containsMouse) { + updateMainItemBindings(); + } + + // Will also be called in activateTaskAtIndex(index) + function updateMainItemBindings() { + if (tasks.toolTipOpenedByClick !== null && tasks.toolTipOpenedByClick !== task) { + return; + } + + mainItem.parentTask = task; + mainItem.rootIndex = tasksModel.makeModelIndex(itemIndex, -1); + + mainItem.appName = Qt.binding(() => model.AppName); + mainItem.pidParent = Qt.binding(() => model.AppPid !== undefined ? model.AppPid : 0); + mainItem.windows = Qt.binding(() => model.WinIdList); + mainItem.isGroup = Qt.binding(() => model.IsGroupParent === true); + mainItem.icon = Qt.binding(() => model.decoration); + mainItem.launcherUrl = Qt.binding(() => model.LauncherUrlWithoutIcon); + mainItem.isLauncher = Qt.binding(() => model.IsLauncher === true); + mainItem.isMinimizedParent = Qt.binding(() => model.IsMinimized === true); + mainItem.displayParent = Qt.binding(() => model.display); + mainItem.genericName = Qt.binding(() => model.GenericName); + mainItem.virtualDesktopParent = Qt.binding(() => + (model.VirtualDesktops !== undefined && model.VirtualDesktops.length > 0) ? model.VirtualDesktops : [0]); + mainItem.isOnAllVirtualDesktopsParent = Qt.binding(() => model.IsOnAllVirtualDesktops === true); + mainItem.activitiesParent = Qt.binding(() => model.Activities); + + mainItem.smartLauncherCountVisible = Qt.binding(() => task.smartLauncherItem && task.smartLauncherItem.countVisible); + mainItem.smartLauncherCount = Qt.binding(() => mainItem.smartLauncherCountVisible ? task.smartLauncherItem.count : 0); + } + } + + states:[ + State { + name: "bottom" + when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 0) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.BottomEdge && !plasmoid.configuration.indicatorReverse) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.TopEdge && plasmoid.configuration.indicatorReverse) + + AnchorChanges { + target: indicator + anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; + horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} + } + PropertyChanges { + target: indicator + width: undefined + height: plasmoid.configuration.indicatorSize + } + }, + State { + name: "left" + when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 1) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.LeftEdge && !plasmoid.configuration.indicatorReverse) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.RightEdge && plasmoid.configuration.indicatorReverse) + + + AnchorChanges { + target: indicator + anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; + horizontalCenter:undefined; verticalCenter:parent.verticalCenter} + } + PropertyChanges { + target: indicator + height: undefined + width: plasmoid.configuration.indicatorSize + } + }, + State { + name: "right" + when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 2) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.RightEdge && !plasmoid.configuration.indicatorReverse) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.LeftEdge && plasmoid.configuration.indicatorReverse) + + AnchorChanges { + target: indicator + anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; + horizontalCenter:undefined; verticalCenter:parent.verticalCenter} + } + PropertyChanges { + target: indicator + height: undefined + width: plasmoid.configuration.indicatorSize + } + }, + State { + name: "top" + when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 3) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.TopEdge && !plasmoid.configuration.indicatorReverse) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.BottomEdge && plasmoid.configuration.indicatorReverse) + + AnchorChanges { + target: indicator + anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; + horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} + } + PropertyChanges { + target: indicator + width: undefined + height: plasmoid.configuration.indicatorSize + } + } + ] + + } + + + + Loader { + anchors.fill: frame + asynchronous: true + source: "TaskProgressOverlay.qml" + active: task.isWindow && task.smartLauncherItem && task.smartLauncherItem.progressVisible + } + + Item { + id: iconBox + + anchors { + left: parent.left + leftMargin: adjustMargin(true, parent.width, taskFrame.margins.left) + top: parent.top + topMargin: adjustMargin(false, parent.height, taskFrame.margins.top) + } + + width: height + height: (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) + - adjustMargin(false, parent.height, taskFrame.margins.bottom)) + + function adjustMargin(vert, size, margin) { + if (!size) { + return margin; + } + + var margins = vert ? LayoutManager.horizontalMargins() : LayoutManager.verticalMargins(); + + if ((size - margins) < PlasmaCore.Units.iconSizes.small) { + return Math.ceil((margin * (PlasmaCore.Units.iconSizes.small / size)) / 2); + } + + return margin; + } + + //width: inPopup ? PlasmaCore.Units.iconSizes.small : Math.min(height, parent.width - LayoutManager.horizontalMargins()) + + PlasmaCore.IconItem { + id: icon + + anchors.fill: parent + + active: task.highlighted + enabled: true + usesPlasmaTheme: false + + source: model.decoration + } + + Loader { + // QTBUG anchors.fill in conjunction with the Loader doesn't reliably work on creation: + // have a window with a badge, move it from one screen to another, the new task item on the + // other screen will now have a glitched out badge mask. + width: parent.width + height: parent.height + asynchronous: true + source: "TaskBadgeOverlay.qml" + active: height >= PlasmaCore.Units.iconSizes.small + && task.smartLauncherItem && task.smartLauncherItem.countVisible + } + + states: [ + // Using a state transition avoids a binding loop between label.visible and + // the text label margin, which derives from the icon width. + State { + name: "standalone" + when: !label.visible + + AnchorChanges { + target: iconBox + anchors.left: undefined + anchors.horizontalCenter: parent.horizontalCenter + } + + PropertyChanges { + target: iconBox + anchors.leftMargin: 0 + width: parent.width - adjustMargin(true, task.width, taskFrame.margins.left) + - adjustMargin(true, task.width, taskFrame.margins.right) + } + } + ] + + Loader { + anchors.centerIn: parent + width: Math.min(parent.width, parent.height) + height: width + active: model.IsStartup === true + sourceComponent: busyIndicator + } + + Component { + id: busyIndicator + PlasmaComponents3.BusyIndicator {} + } + } + + Loader { + id: audioStreamIconLoader + + readonly property bool shown: item && item.visible + readonly property var indicatorScale: 1.2 + + source: "AudioStream.qml" + width: Math.min(Math.min(iconBox.width, iconBox.height) * 0.4, PlasmaCore.Units.iconSizes.smallMedium) + height: width + + anchors { + right: frame.right + top: frame.top + rightMargin: taskFrame.margins.right + topMargin: Math.round(taskFrame.margins.top * indicatorScale) + } + } + + PlasmaComponents3.Label { + id: label + + visible: (inPopup || !iconsOnly && model.IsLauncher !== true + && (parent.width - iconBox.height - PlasmaCore.Units.smallSpacing) >= (theme.mSize(theme.defaultFont).width * LayoutManager.minimumMColumns())) + + anchors { + fill: parent + leftMargin: taskFrame.margins.left + iconBox.width + LayoutManager.labelMargin + topMargin: taskFrame.margins.top + rightMargin: taskFrame.margins.right + (audioStreamIconLoader.shown ? (audioStreamIconLoader.width + LayoutManager.labelMargin) : 0) + bottomMargin: taskFrame.margins.bottom + } + + wrapMode: (maximumLineCount == 1) ? Text.NoWrap : Text.Wrap + elide: Text.ElideRight + textFormat: Text.PlainText + verticalAlignment: Text.AlignVCenter + maximumLineCount: plasmoid.configuration.maxTextLines || undefined + + // use State to avoid unnecessary re-evaluation when the label is invisible + states: State { + name: "labelVisible" + when: label.visible + + PropertyChanges { + target: label + text: model.display || "" + } + } + } + + states: [ + State { + name: "launcher" + when: model.IsLauncher === true + + PropertyChanges { + target: frame + basePrefix: "" + } + PropertyChanges { + target: colorOverride + visible: false + } + }, + State { + name: "attention" + when: model.IsDemandingAttention === true || (task.smartLauncherItem && task.smartLauncherItem.urgent) + + PropertyChanges { + target: frame + basePrefix: "attention" + } + PropertyChanges { + target: colorOverride + visible: plasmoid.configuration.buttonColorize ? frame.isHovered ? true : false : false + } + }, + State { + name: "minimized" + when: model.IsMinimized === true + + PropertyChanges { + target: frame + basePrefix: "minimized" + } + PropertyChanges { + target: colorOverride + visible: plasmoid.configuration.buttonColorize ? frame.isHovered ? true : false : false + lightness: hexToHSL(plasmoid.configuration.buttonColorizeDominant ? imageColors.dominant : plasmoid.configuration.buttonColorizeCustom).l - 0.8 + } + }, + State { + name: "active" + when: model.IsActive === true + + PropertyChanges { + target: frame + basePrefix: "focus" + } + PropertyChanges { + target: colorOverride + visible: plasmoid.configuration.buttonColorize ? true : false + } + } + ] + + Component.onCompleted: { + if (!inPopup && model.IsWindow === true) { + if(plasmoid.configuration.groupIconEnabled){ + var component = Qt.createComponent("GroupExpanderOverlay.qml"); + component.createObject(task); + } + } + + if (!inPopup && model.IsWindow !== true) { + taskInitComponent.createObject(task); + } + + updateAudioStreams({delay: false}) + } +} diff --git a/contents/ui/TaskBadgeOverlay.qml b/contents/ui/TaskBadgeOverlay.qml new file mode 100644 index 00000000..ead630af --- /dev/null +++ b/contents/ui/TaskBadgeOverlay.qml @@ -0,0 +1,85 @@ +/* + SPDX-FileCopyrightText: 2016 Kai Uwe Broulik + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 + +import org.kde.plasma.core 2.0 as PlasmaCore + +Item { + readonly property int iconWidthDelta: (icon.width - icon.paintedWidth) / 2 + readonly property bool shiftBadgeDown: (plasmoid.configuration.iconOnly) && task.audioStreamIconLoaderItem.shown + + Item { + id: badgeMask + anchors.fill: parent + + Rectangle { + readonly property int offset: Math.round(Math.max(PlasmaCore.Units.smallSpacing / 2, badgeMask.width / 32)) + anchors.right: Qt.application.layoutDirection === Qt.RightToLeft ? undefined : parent.right + anchors.left: Qt.application.layoutDirection === Qt.RightToLeft ? parent.left : undefined + anchors.rightMargin: Qt.application.layoutDirection === Qt.RightToLeft ? 0 : -offset + anchors.leftMargin: Qt.application.layoutDirection === Qt.RightToLeft ? -offset : 0 + y: shiftBadgeDown ? (icon.height/2) : 0 + + visible: task.smartLauncherItem.countVisible + width: badgeRect.width + offset * 2 + height: badgeRect.height + offset * 2 + radius: badgeRect.radius + offset * 2 + + // Badge changes width based on number. + onWidthChanged: maskShaderSource.scheduleUpdate() + onVisibleChanged: maskShaderSource.scheduleUpdate() + onYChanged: maskShaderSource.scheduleUpdate() + } + } + + ShaderEffectSource { + id: iconShaderSource + sourceItem: icon + hideSource: GraphicsInfo.api !== GraphicsInfo.Software + } + + ShaderEffectSource { + id: maskShaderSource + sourceItem: badgeMask + hideSource: true + live: false + } + + ShaderEffect { + id: shader + + anchors.fill: parent + property var source: iconShaderSource + property var mask: maskShaderSource + + onWidthChanged: maskShaderSource.scheduleUpdate() + onHeightChanged: maskShaderSource.scheduleUpdate() + + supportsAtlasTextures: true + + fragmentShader: ` + varying highp vec2 qt_TexCoord0; + uniform highp float qt_Opacity; + uniform lowp sampler2D source; + uniform lowp sampler2D mask; + void main() { + gl_FragColor = texture2D(source, qt_TexCoord0.st) * (1.0 - (texture2D(mask, qt_TexCoord0.st).a)) * qt_Opacity; + } + ` + } + + Badge { + readonly property int offset: Math.round(Math.max(PlasmaCore.Units.smallSpacing / 2, badgeMask.width / 32)) + id: badgeRect + anchors.right: Qt.application.layoutDirection === Qt.RightToLeft ? undefined : parent.right + anchors.left: Qt.application.layoutDirection === Qt.RightToLeft ? parent.left : undefined + y: offset + (shiftBadgeDown ? (icon.height/2) : 0) + height: Math.round(parent.height * 0.4) + visible: task.smartLauncherItem.countVisible + number: task.smartLauncherItem.count + } +} diff --git a/contents/ui/TaskList.qml b/contents/ui/TaskList.qml new file mode 100644 index 00000000..ef36aeb9 --- /dev/null +++ b/contents/ui/TaskList.qml @@ -0,0 +1,38 @@ +/* + SPDX-FileCopyrightText: 2012-2013 Eike Hein + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 +import org.kde.plasma.core 2.0 as PlasmaCore + +Flow { + property bool animating: false + + readonly property bool tasksGrowInOppositeDirection: plasmoid.configuration.reverseMode + readonly property bool isHorizontalPanel: plasmoid.formFactor === PlasmaCore.Types.Horizontal + + layoutDirection: (tasksGrowInOppositeDirection && isHorizontalPanel) + ? (Qt.application.layoutDirection === Qt.LeftToRight) + ? Qt.RightToLeft + : Qt.LeftToRight + : Qt.application.layoutDirection + + property int rows: Math.floor(height / children[0].height) + property int columns: Math.floor(width / children[0].width) + + move: Transition { + SequentialAnimation { + PropertyAction { target: taskList; property: "animating"; value: true } + + NumberAnimation { + properties: "x, y" + easing.type: Easing.OutQuad + duration: PlasmaCore.Units.longDuration + } + + PropertyAction { target: taskList; property: "animating"; value: false } + } + } +} diff --git a/contents/ui/TaskProgressOverlay.qml b/contents/ui/TaskProgressOverlay.qml new file mode 100644 index 00000000..94fdbe4e --- /dev/null +++ b/contents/ui/TaskProgressOverlay.qml @@ -0,0 +1,36 @@ +/* + SPDX-FileCopyrightText: 2016 Kai Uwe Broulik + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 + +import org.kde.plasma.core 2.0 as PlasmaCore + +import "code/tools.js" as TaskTools + +Item { + id: background + + Item { + id: progress + anchors { + top: parent.top + left: parent.left + bottom: parent.bottom + } + + width: parent.width * (task.smartLauncherItem.progress / 100) + clip: true + + PlasmaCore.FrameSvgItem { + id: progressFrame + width: background.width + height: background.height + + imagePath: "widgets/tasks" + prefix: TaskTools.taskPrefix("progress").concat(TaskTools.taskPrefix("hover")) + } + } +} diff --git a/contents/ui/ToolTipDelegate.qml b/contents/ui/ToolTipDelegate.qml new file mode 100644 index 00000000..9f08af91 --- /dev/null +++ b/contents/ui/ToolTipDelegate.qml @@ -0,0 +1,124 @@ +/* + SPDX-FileCopyrightText: 2013 Sebastian Kügler + SPDX-FileCopyrightText: 2014 Martin Gräßlin + SPDX-FileCopyrightText: 2016 Kai Uwe Broulik + SPDX-FileCopyrightText: 2017 Roman Gilg + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQml.Models 2.15 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 3.0 as PlasmaComponents3 + +Loader { + id: toolTipDelegate + + property Item parentTask + property var rootIndex + + property string appName + property int pidParent + property bool isGroup + + property var windows + readonly property bool isWin: windows !== undefined + + property variant icon + property url launcherUrl + property bool isLauncher + property bool isMinimizedParent + + // Needed for generateSubtext() + property string displayParent + property string genericName + property var virtualDesktopParent + property bool isOnAllVirtualDesktopsParent + property var activitiesParent + // + property bool smartLauncherCountVisible + property int smartLauncherCount + + readonly property bool isVerticalPanel: plasmoid.formFactor === PlasmaCore.Types.Vertical + // This number controls the overall size of the window tooltips + readonly property int tooltipInstanceMaximumWidth: PlasmaCore.Units.gridUnit * 16 + + // These properties are required to make tooltip interactive when there is a player but no window is present. + readonly property string mprisSourceName: mpris2Source.sourceNameForLauncherUrl(launcherUrl, pidParent) + readonly property var playerData: mprisSourceName != "" ? mpris2Source.data[mprisSourceName] : 0 + readonly property bool hasPlayer: !!mprisSourceName && !!playerData + + Binding on Layout.minimumWidth { + value: implicitWidth + delayed: true // Prevent early hide of tooltip (BUG439522) + } + Layout.maximumWidth: Layout.minimumWidth + + Binding on Layout.minimumHeight { + value: implicitHeight + delayed: true // Prevent early hide of tooltip (BUG439522) + } + Layout.maximumHeight: Layout.minimumHeight + + LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft + LayoutMirroring.childrenInherit: true + + active: rootIndex !== undefined + asynchronous: true + + sourceComponent: isGroup ? groupToolTip : singleTooltip + + Component { + id: singleTooltip + + ToolTipInstance { + submodelIndex: toolTipDelegate.rootIndex + } + } + + Component { + id: groupToolTip + + PlasmaComponents3.ScrollView { + // 2 * PlasmaCore.Units.smallSpacing is for the margin of tooltipDialog + implicitWidth: leftPadding + rightPadding + Math.min(Screen.desktopAvailableWidth - 2 * PlasmaCore.Units.smallSpacing, Math.max(delegateModel.estimatedWidth, contentItem.contentItem.childrenRect.width)) + implicitHeight: bottomPadding + Math.min(Screen.desktopAvailableHeight - 2 * PlasmaCore.Units.smallSpacing, Math.max(delegateModel.estimatedHeight, contentItem.contentItem.childrenRect.height)) + + // HACK: workaround for https://bugreports.qt.io/browse/QTBUG-83890 + PlasmaComponents3.ScrollBar.horizontal.policy: isVerticalPanel ? PlasmaComponents3.ScrollBar.AlwaysOff : PlasmaComponents3.ScrollBar.AsNeeded + PlasmaComponents3.ScrollBar.vertical.policy: isVerticalPanel ? PlasmaComponents3.ScrollBar.AsNeeded : PlasmaComponents3.ScrollBar.AlwaysOff + + ListView { + id: groupToolTipListView + + // HACK: workaround for https://bugreports.qt.io/browse/QTBUG-102811 + model: delegateModel.count > 0 ? delegateModel : null + + orientation: isVerticalPanel ? ListView.Vertical : ListView.Horizontal + reuseItems: true + spacing: PlasmaCore.Units.largeSpacing + } + + DelegateModel { + id: delegateModel + + // On Wayland, a tooltip has a significant resizing process, so estimate the size first. + readonly property int estimatedWidth: (toolTipDelegate.isVerticalPanel ? 1 : count) * (toolTipDelegate.tooltipInstanceMaximumWidth + PlasmaCore.Units.largeSpacing) - PlasmaCore.Units.largeSpacing + readonly property int estimatedHeight: (toolTipDelegate.isVerticalPanel ? count : 1) * (toolTipDelegate.tooltipInstanceMaximumWidth / 2 + PlasmaCore.Units.largeSpacing) - PlasmaCore.Units.largeSpacing + + model: tasksModel + + rootIndex: toolTipDelegate.rootIndex + onRootIndexChanged: groupToolTipListView.positionViewAtBeginning() // Fix a visual glitch (when the mouse moves from a tooltip with a moved scrollbar to another tooltip without a scrollbar) + + delegate: ToolTipInstance { + submodelIndex: tasksModel.makeModelIndex(toolTipDelegate.rootIndex.row, index) + } + } + } + } +} diff --git a/contents/ui/ToolTipInstance.qml b/contents/ui/ToolTipInstance.qml new file mode 100644 index 00000000..48cb5f9e --- /dev/null +++ b/contents/ui/ToolTipInstance.qml @@ -0,0 +1,439 @@ +/* + SPDX-FileCopyrightText: 2013 Sebastian Kügler + SPDX-FileCopyrightText: 2014 Martin Gräßlin + SPDX-FileCopyrightText: 2016 Kai Uwe Broulik + SPDX-FileCopyrightText: 2017 Roman Gilg + SPDX-FileCopyrightText: 2020 Nate Graham + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtGraphicalEffects 1.15 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 3.0 as PlasmaComponents3 +import org.kde.plasma.extras 2.0 as PlasmaExtras + +ColumnLayout { + property var submodelIndex + property int flatIndex: isGroup && index != undefined ? index : 0 + readonly property int appPid: isGroup ? model.AppPid : pidParent + + // HACK: Avoid blank space in the tooltip after closing a window + ListView.onPooled: width = height = 0 + ListView.onReused: width = height = undefined + + readonly property string title: { + if (!isWin) { + return genericName || ""; + } + + let text; + if (isGroup) { + if (model.display === undefined) { + return ""; + } + text = model.display.toString(); + } else { + text = displayParent; + } + + // KWin appends increasing integers in between pointy brackets to otherwise equal window titles. + // In this case save <#number> as counter and delete it at the end of text. + text = `${(text.match(/.*(?=\s*(—|-))/) || [""])[0]}${(text.match(/<\d+>/) || [""]).pop()}`; + + // In case the window title had only redundant information (i.e. appName), text is now empty. + // Add a hyphen to indicate that and avoid empty space. + if (text === "") { + text = "—"; + } + return text; + } + readonly property bool titleIncludesTrack: playerController.item + && title.includes(playerController.item.track) + + spacing: PlasmaCore.Units.smallSpacing + + // text labels + close button + RowLayout { + id: header + // match spacing of DefaultToolTip.qml in plasma-framework + spacing: isWin ? PlasmaCore.Units.smallSpacing : PlasmaCore.Units.largeSpacing + + // This number controls the overall size of the window tooltips + Layout.maximumWidth: toolTipDelegate.tooltipInstanceMaximumWidth + Layout.minimumWidth: isWin ? Layout.maximumWidth : 0 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + // match margins of DefaultToolTip.qml in plasma-framework + Layout.margins: isWin ? 0 : PlasmaCore.Units.gridUnit / 2 + + // all textlabels + ColumnLayout { + spacing: 0 + // app name + PlasmaExtras.Heading { + id: appNameHeading + level: 3 + maximumLineCount: 1 + lineHeight: isWin ? 1 : appNameHeading.lineHeight + Layout.fillWidth: true + elide: Text.ElideRight + text: appName + opacity: flatIndex == 0 + visible: text.length !== 0 + textFormat: Text.PlainText + } + // window title + PlasmaComponents3.Label { + id: winTitle + maximumLineCount: 1 + Layout.fillWidth: true + elide: Text.ElideRight + text: titleIncludesTrack ? "" : title + opacity: 0.75 + visible: title.length !== 0 && title !== appNameHeading.text + textFormat: Text.PlainText + } + // subtext + PlasmaComponents3.Label { + id: subtext + maximumLineCount: 1 + Layout.fillWidth: true + elide: Text.ElideRight + text: isWin ? generateSubText() : "" + opacity: 0.6 + visible: text.length !== 0 && text !== appNameHeading.text + textFormat: Text.PlainText + } + } + + // Count badge. + // The badge itself is inside an item to better center the text in the bubble + Item { + Layout.alignment: Qt.AlignRight | Qt.AlignTop + Layout.preferredHeight: closeButton.height + Layout.preferredWidth: closeButton.width + visible: flatIndex === 0 && smartLauncherCountVisible + + Badge { + anchors.centerIn: parent + height: PlasmaCore.Units.iconSizes.smallMedium + number: smartLauncherCount + } + } + + // close button + PlasmaComponents3.ToolButton { + id: closeButton + Layout.alignment: Qt.AlignRight | Qt.AlignTop + visible: isWin + icon.name: "window-close" + onClicked: { + backend.cancelHighlightWindows(); + tasksModel.requestClose(submodelIndex); + } + } + } + + // thumbnail container + Item { + id: thumbnailSourceItem + + Layout.minimumWidth: header.width + Layout.preferredHeight: header.width / 2 + + clip: true + visible: toolTipDelegate.isWin + + readonly property bool isMinimized: isGroup ? IsMinimized == true : isMinimizedParent + // TODO: this causes XCB error message when being visible the first time + readonly property var winId: toolTipDelegate.isWin && toolTipDelegate.windows[flatIndex] !== undefined ? toolTipDelegate.windows[flatIndex] : 0 + + // There's no PlasmaComponents3 version + PlasmaExtras.Highlight { + anchors.fill: hoverHandler + visible: hoverHandler.item ? hoverHandler.item.containsMouse : false + pressed: hoverHandler.item ? hoverHandler.item.containsPress : false + hovered: true + } + + Loader { + id: thumbnailLoader + active: !albumArtImage.visible && Number.isInteger(thumbnailSourceItem.winId) && flatIndex !== -1 // Avoid loading when the instance is going to be destroyed + asynchronous: true + visible: active + anchors.fill: hoverHandler + // Indent a little bit so that neither the thumbnail nor the drop + // shadow can cover up the highlight + anchors.margins: PlasmaCore.Units.smallSpacing * 2 + + sourceComponent: thumbnailSourceItem.isMinimized ? iconItem : x11Thumbnail + + Component { + id: x11Thumbnail + + PlasmaCore.WindowThumbnail { + winId: thumbnailSourceItem.winId + } + } + + // when minimized, we don't have a preview on X11, so show the icon + Component { + id: iconItem + + PlasmaCore.IconItem { + source: icon + animated: false + usesPlasmaTheme: false + visible: valid + } + } + } + + Loader { + id: pipeWireLoader + anchors.fill: hoverHandler + // Indent a little bit so that neither the thumbnail nor the drop + // shadow can cover up the highlight + anchors.margins: thumbnailLoader.anchors.margins + + active: !albumArtImage.visible && !Number.isInteger(thumbnailSourceItem.winId) && flatIndex !== -1 + asynchronous: true + //In a loader since we might not have PipeWire available yet (WITH_PIPEWIRE could be undefined in plasma-workspace/libtaskmanager/declarative/taskmanagerplugin.cpp) + source: "PipeWireThumbnail.qml" + } + + Loader { + active: (pipeWireLoader.active && pipeWireLoader.item.visible) || (thumbnailLoader.status === Loader.Ready && !thumbnailSourceItem.isMinimized) + asynchronous: true + visible: active + anchors.fill: pipeWireLoader.active ? pipeWireLoader : thumbnailLoader + + sourceComponent: DropShadow { + horizontalOffset: 0 + verticalOffset: Math.round(3 * PlasmaCore.Units.devicePixelRatio) + radius: Math.round(8.0 * PlasmaCore.Units.devicePixelRatio) + samples: Math.round(radius * 1.5) + color: "Black" + source: pipeWireLoader.active ? pipeWireLoader.item : thumbnailLoader.item // source could be undefined when albumArt is available, so put it in a Loader. + } + } + + Loader { + active: albumArtImage.visible && albumArtImage.status === Image.Ready && flatIndex !== -1 // Avoid loading when the instance is going to be destroyed + asynchronous: true + visible: active + anchors.centerIn: hoverHandler + + sourceComponent: ShaderEffect { + id: albumArtBackground + readonly property Image source: albumArtImage + + // Manual implementation of Image.PreserveAspectCrop + readonly property real scaleFactor: Math.max(hoverHandler.width / source.paintedWidth, hoverHandler.height / source.paintedHeight) + width: Math.round(source.paintedWidth * scaleFactor) + height: Math.round(source.paintedHeight * scaleFactor) + layer.enabled: true + opacity: 0.25 + layer.effect: FastBlur { + source: albumArtBackground + anchors.fill: source + radius: 30 + } + } + } + + Image { + id: albumArtImage + // also Image.Loading to prevent loading thumbnails just because the album art takes a split second to load + // if this is a group tooltip, we check if window title and track match, to allow distinguishing the different windows + // if this app is a browser, we also check the title, so album art is not shown when the user is on some other tab + // in all other cases we can safely show the album art without checking the title + readonly property bool available: (status === Image.Ready || status === Image.Loading) + && (!(isGroup || backend.applicationCategories(launcherUrl).includes("WebBrowser")) || titleIncludesTrack) + + anchors.fill: hoverHandler + // Indent by one pixel to make sure we never cover up the entire highlight + anchors.margins: 1 + sourceSize: Qt.size(parent.width, parent.height) + + asynchronous: true + source: playerController.item ? playerController.item.albumArt : "" + fillMode: Image.PreserveAspectFit + visible: available + } + + // hoverHandler has to be unloaded after the instance is pooled in order to avoid getting the old containsMouse status when the same instance is reused, so put it in a Loader. + Loader { + id: hoverHandler + active: flatIndex !== -1 + anchors.fill: parent + sourceComponent: ToolTipWindowMouseArea { + rootTask: parentTask + modelIndex: submodelIndex + winId: thumbnailSourceItem.winId + } + } + } + + // Player controls row, load on demand so group tooltips could be loaded faster + Loader { + id: playerController + active: hasPlayer && flatIndex !== -1 // Avoid loading when the instance is going to be destroyed + asynchronous: true + visible: active + Layout.fillWidth: true + Layout.maximumWidth: header.Layout.maximumWidth + Layout.leftMargin: header.Layout.margins + Layout.rightMargin: header.Layout.margins + + source: "PlayerController.qml" + } + + // Volume controls + Loader { + active: parentTask + && pulseAudio.item + && parentTask.audioIndicatorsEnabled + && parentTask.hasAudioStream + && flatIndex !== -1 // Avoid loading when the instance is going to be destroyed + asynchronous: true + visible: active + Layout.fillWidth: true + Layout.maximumWidth: header.Layout.maximumWidth + Layout.leftMargin: header.Layout.margins + Layout.rightMargin: header.Layout.margins + sourceComponent: RowLayout { + PlasmaComponents3.ToolButton { // Mute button + icon.width: PlasmaCore.Units.iconSizes.small + icon.height: PlasmaCore.Units.iconSizes.small + icon.name: if (checked) { + "audio-volume-muted" + } else if (slider.displayValue <= 25) { + "audio-volume-low" + } else if (slider.displayValue <= 75) { + "audio-volume-medium" + } else { + "audio-volume-high" + } + onClicked: parentTask.toggleMuted() + checked: parentTask.muted + + PlasmaComponents3.ToolTip { + text: parent.checked ? + i18nc("button to unmute app", "Unmute %1", parentTask.appName) + : i18nc("button to mute app", "Mute %1", parentTask.appName) + } + } + + PlasmaComponents3.Slider { + id: slider + + readonly property int displayValue: Math.round(value / to * 100) + readonly property int loudestVolume: { + let v = 0 + parentTask.audioStreams.forEach((stream) => { + v = Math.max(v, stream.volume) + }) + return v + } + + Layout.fillWidth: true + from: pulseAudio.item.minimalVolume + to: pulseAudio.item.normalVolume + value: loudestVolume + stepSize: to / 100 + opacity: parentTask.muted ? 0.5 : 1 + + Accessible.name: i18nc("Accessibility data on volume slider", "Adjust volume for %1", parentTask.appName) + + onMoved: parentTask.audioStreams.forEach((stream) => { + let v = Math.max(from, value) + if (v > 0 && loudestVolume > 0) { // prevent divide by 0 + // adjust volume relative to the loudest stream + v = Math.min(Math.round(stream.volume / loudestVolume * v), to) + } + stream.model.Volume = v + stream.model.Muted = v === 0 + }) + } + PlasmaComponents3.Label { // percent label + Layout.alignment: Qt.AlignHCenter + Layout.minimumWidth: percentMetrics.advanceWidth + horizontalAlignment: Qt.AlignRight + text: i18nc("volume percentage", "%1%", slider.displayValue) + TextMetrics { + id: percentMetrics + text: i18nc("only used for sizing, should be widest possible string", "100%") + } + } + } + } + + function generateSubText() { + if (activitiesParent === undefined) { + return ""; + } + + let subTextEntries = []; + + const onAllDesktops = (isGroup ? IsOnAllVirtualDesktops : isOnAllVirtualDesktopsParent) === true; + if (!plasmoid.configuration.showOnlyCurrentDesktop && virtualDesktopInfo.numberOfDesktops > 1) { + const virtualDesktops = isGroup ? VirtualDesktops : virtualDesktopParent; + + if (!onAllDesktops && virtualDesktops !== undefined && virtualDesktops.length > 0) { + let virtualDesktopNameList = new Array(); + + for (let i = 0; i < virtualDesktops.length; ++i) { + virtualDesktopNameList.push(virtualDesktopInfo.desktopNames[virtualDesktopInfo.desktopIds.indexOf(virtualDesktops[i])]); + } + + subTextEntries.push(i18nc("Comma-separated list of desktops", "On %1", + virtualDesktopNameList.join(", "))); + } else if (onAllDesktops) { + subTextEntries.push(i18nc("Comma-separated list of desktops", "Pinned to all desktops")); + } + } + + const act = isGroup ? Activities : activitiesParent; + if (act === undefined) { + return subTextEntries.join("\n"); + } + + if (act.length === 0 && activityInfo.numberOfRunningActivities > 1) { + subTextEntries.push(i18nc("Which virtual desktop a window is currently on", + "Available on all activities")); + } else if (act.length > 0) { + let activityNames = []; + + for (let i = 0; i < act.length; i++) { + const activity = act[i]; + const activityName = activityInfo.activityName(act[i]); + if (activityName === "") { + continue; + } + if (plasmoid.configuration.showOnlyCurrentActivity) { + if (activity !== activityInfo.currentActivity) { + activityNames.push(activityName); + } + } else if (activity !== activityInfo.currentActivity) { + activityNames.push(activityName); + } + } + + if (plasmoid.configuration.showOnlyCurrentActivity) { + if (activityNames.length > 0) { + subTextEntries.push(i18nc("Activities a window is currently on (apart from the current one)", + "Also available on %1", activityNames.join(", "))); + } + } else if (activityNames.length > 0) { + subTextEntries.push(i18nc("Which activities a window is currently on", + "Available on %1", activityNames.join(", "))); + } + } + + return subTextEntries.join("\n"); + } +} diff --git a/contents/ui/ToolTipWindowMouseArea.qml b/contents/ui/ToolTipWindowMouseArea.qml new file mode 100644 index 00000000..590ee775 --- /dev/null +++ b/contents/ui/ToolTipWindowMouseArea.qml @@ -0,0 +1,37 @@ +/* + SPDX-FileCopyrightText: 2013 Sebastian Kügler + SPDX-FileCopyrightText: 2014 Martin Gräßlin + SPDX-FileCopyrightText: 2016 Kai Uwe Broulik + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +import QtQuick 2.15 + +MouseArea { + property var modelIndex + // winId won't be an int wayland + property var winId // FIXME Legacy + property Item rootTask + + acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton + hoverEnabled: true + enabled: winId !== 0 + + onClicked: { + if (mouse.button == Qt.LeftButton) { + tasksModel.requestActivate(modelIndex); + rootTask.toolTipAreaItem.hideImmediately(); + backend.cancelHighlightWindows(); + } else if (mouse.button == Qt.MiddleButton) { + backend.cancelHighlightWindows(); + tasksModel.requestClose(modelIndex); + } else /* right button */ { + tasks.createContextMenu(rootTask, modelIndex).show(); + } + } + + onContainsMouseChanged: { + tasks.windowsHovered([winId], containsMouse); + } +} diff --git a/contents/ui/code/layout.js b/contents/ui/code/layout.js new file mode 100644 index 00000000..bc8f5de7 --- /dev/null +++ b/contents/ui/code/layout.js @@ -0,0 +1,237 @@ +/* + SPDX-FileCopyrightText: 2012-2013 Eike Hein + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +.import org.kde.plasma.core 2.0 as PlasmaCore +.import org.kde.kirigami 2.19 as Kirigami + +const iconMargin = Math.round(PlasmaCore.Units.smallSpacing / 4); +const labelMargin = PlasmaCore.Units.smallSpacing; + +function horizontalMargins() { + const spacingAdjustment = (plasmoid.configuration.iconOnly) ? (Kirigami.Settings.tabletMode ? 3 : plasmoid.configuration.iconSpacing) : 1 + return (taskFrame.margins.left + taskFrame.margins.right) * spacingAdjustment; +} + +function verticalMargins() { + const spacingAdjustment = (plasmoid.configuration.iconOnly) ? (Kirigami.Settings.tabletMode ? 3 : plasmoid.configuration.iconSpacing) : 1 + return (taskFrame.margins.top + taskFrame.margins.bottom) * spacingAdjustment; +} + +function adjustMargin(height, margin) { + var available = height - verticalMargins(); + + if (available < PlasmaCore.Units.iconSizes.small) { + return Math.floor((margin * (PlasmaCore.Units.iconSizes.small / available)) / 3); + } + + return margin; +} + +function launcherLayoutTasks() { + return Math.round(tasksModel.logicalLauncherCount / Math.floor(preferredMinWidth() / launcherWidth())); +} + +function launcherLayoutWidthDiff() { + return (launcherLayoutTasks() * taskWidth()) - (tasksModel.logicalLauncherCount * launcherWidth()); +} + +function logicalTaskCount() { + var count = (tasksModel.count - tasksModel.logicalLauncherCount) + launcherLayoutTasks(); + + return Math.max(tasksModel.count ? 1 : 0, count); +} + +function maxStripes() { + var length = tasks.vertical ? taskList.width : taskList.height; + var minimum = tasks.vertical ? preferredMinWidth() : preferredMinHeight(); + + return Math.min(plasmoid.configuration.maxStripes, Math.max(1, Math.floor(length / minimum))); +} + +function tasksPerStripe() { + if (plasmoid.configuration.forceStripes) { + return Math.ceil(logicalTaskCount() / maxStripes()); + } else { + var length = tasks.vertical ? taskList.height : taskList.width; + var minimum = tasks.vertical ? preferredMinHeight() : preferredMinWidth(); + + return Math.floor(length / minimum); + } +} + +function calculateStripes() { + var stripes = plasmoid.configuration.forceStripes ? plasmoid.configuration.maxStripes : Math.min(plasmoid.configuration.maxStripes, Math.ceil(logicalTaskCount() / tasksPerStripe())); + + return Math.min(stripes, maxStripes()); +} + +function full() { + return (maxStripes() == calculateStripes()); +} + +function optimumCapacity(width, height) { + var length = tasks.vertical ? height : width; + var maximum = tasks.vertical ? preferredMaxHeight() : preferredMaxWidth(); + + if (!tasks.vertical) { + // Fit more tasks in this case, that is possible to cut text, before combining tasks. + return Math.ceil(length / maximum) * maxStripes() + 1; + } + + return Math.floor(length / maximum) * maxStripes(); +} + +function layoutWidth() { + if (plasmoid.configuration.forceStripes && !tasks.vertical) { + return Math.min(tasks.width - (tasksPerStripe() * plasmoid.configuration.taskSpacingSize), Math.max(preferredMaxWidth(), tasksPerStripe() * preferredMaxWidth())); + } else { + return tasks.width; + } +} + +function layoutHeight() { + if (plasmoid.configuration.forceStripes && tasks.vertical) { + return Math.min(tasks.height - (tasksPerStripe() * plasmoid.configuration.taskSpacingSize), Math.max(preferredMaxHeight(), tasksPerStripe() * preferredMaxHeight())); + } else { + return tasks.height; + } +} + +function preferredMinWidth() { + var width = launcherWidth(); + + if (!tasks.vertical && !tasks.iconsOnly) { + width += + (PlasmaCore.Units.smallSpacing * 2) + + (plasmoid.configuration.maxLength /*PlasmaCore.Theme.mSize(PlasmaCore.Theme.defaultFont).width * 12*/); + } + + return width; +} + +function preferredMaxWidth() { + if (tasks.iconsOnly) { + if (tasks.vertical) { + return tasks.width + verticalMargins(); + } else { + return tasks.height + horizontalMargins(); + } + } + + if (plasmoid.configuration.groupingStrategy != 0 && !plasmoid.configuration.groupPopups) { + return preferredMinWidth(); + } + + return Math.floor(preferredMinWidth()); +} + +function preferredMinHeight() { + // TODO FIXME UPSTREAM: Port to proper font metrics for descenders once we have access to them. + return PlasmaCore.Theme.mSize(PlasmaCore.Theme.defaultFont).height + 4; +} + +function preferredMaxHeight() { + if (tasks.vertical) { + return verticalMargins() + + Math.min( + // Do not allow the preferred icon size to exceed the width of + // the vertical task manager. + tasks.width, + tasks.iconsOnly ? tasks.width : + Math.max( + PlasmaCore.Theme.mSize(PlasmaCore.Theme.defaultFont).height, + PlasmaCore.Units.iconSizes.medium + ) + ); + } else { + return verticalMargins() + + Math.min( + PlasmaCore.Units.iconSizes.small * 3, + PlasmaCore.Theme.mSize(PlasmaCore.Theme.defaultFont).height * + 3); + } +} + +// Returns the number of 'm' characters whose joint width must be available in the task button label +// so that the button text is rendered at all. +function minimumMColumns() { + return tasks.vertical ? 4 : 5; +} + +function taskWidth() { + if (tasks.vertical) { + return Math.floor(taskList.width / calculateStripes()); + } else { + if (full() && Math.max(1, logicalTaskCount()) > tasksPerStripe()) { + return Math.floor(taskList.width / Math.ceil(logicalTaskCount() / maxStripes())); + } else { + return Math.min(preferredMaxWidth(), Math.floor(taskList.width / Math.min(logicalTaskCount(), tasksPerStripe()))); + } + } +} + +function taskHeight() { + if (tasks.vertical) { + if (full() && Math.max(1, logicalTaskCount()) > tasksPerStripe()) { + return Math.floor(taskList.height / Math.ceil(logicalTaskCount() / maxStripes())); + } else { + return Math.min(preferredMaxHeight(), Math.floor(taskList.height / Math.min(logicalTaskCount(), tasksPerStripe()))); + } + } else { + return Math.floor(taskList.height / calculateStripes()); + } +} + +function launcherWidth() { + var baseWidth = tasks.vertical ? preferredMinHeight() : Math.min(tasks.height, PlasmaCore.Units.iconSizes.small * 3); + + return (baseWidth + horizontalMargins()) + - (adjustMargin(baseWidth, taskFrame.margins.top) + adjustMargin(baseWidth, taskFrame.margins.bottom)); +} + +function maximumContextMenuTextWidth() { + return (PlasmaCore.Theme.mSize(PlasmaCore.Theme.defaultFont).width * 28); +} + +function layout(container) { + var item; + var stripes = calculateStripes(); + var taskCount = tasksModel.count - tasksModel.logicalLauncherCount; + var width = taskWidth(); + var adjustedWidth = width; + var height = taskHeight(); + + if (!tasks.vertical && stripes == 1 && taskCount) + { + var shrink = ((tasksModel.count - tasksModel.logicalLauncherCount) * preferredMaxWidth()) + + (tasksModel.logicalLauncherCount * launcherWidth()) > taskList.width; + width = Math.min(shrink ? width + Math.floor(launcherLayoutWidthDiff() / taskCount) : width, + preferredMaxWidth()); + } + + for (var i = 0; i < container.count; ++i) { + item = container.itemAt(i); + + if (!item) { + continue; + } + + adjustedWidth = width; + + if (!tasks.vertical && !tasks.iconsOnly && (plasmoid.configuration.separateLaunchers || stripes == 1)) { + if (item.m.IsLauncher === true + || (!plasmoid.configuration.separateLaunchers && item.m.IsStartup === true && item.m.HasLauncher === true)) { + adjustedWidth = launcherWidth(); + } else if (stripes > 1 && i == tasksModel.logicalLauncherCount) { + adjustedWidth += launcherLayoutWidthDiff(); + } + } + + item.width = adjustedWidth; + item.height = height; + item.visible = true; + } +} diff --git a/contents/ui/code/tools.js b/contents/ui/code/tools.js new file mode 100644 index 00000000..ecebacc2 --- /dev/null +++ b/contents/ui/code/tools.js @@ -0,0 +1,288 @@ +/* + SPDX-FileCopyrightText: 2012-2016 Eike Hein + SPDX-FileCopyrightText: 2020 Nate Graham + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +.import QtQml 2.15 as QtQml +.import org.kde.taskmanager 0.1 as TaskManager +.import org.kde.plasma.core 2.0 as PlasmaCore // Needed by TaskManager + +function wheelActivateNextPrevTask(anchor, wheelDelta, eventDelta) { + // magic number 120 for common "one click" + // See: http://qt-project.org/doc/qt-5/qml-qtquick-wheelevent.html#angleDelta-prop + wheelDelta += eventDelta; + var increment = 0; + while (wheelDelta >= 120) { + wheelDelta -= 120; + increment++; + } + while (wheelDelta <= -120) { + wheelDelta += 120; + increment--; + } + while (increment != 0) { + activateNextPrevTask(anchor, increment < 0) + increment += (increment < 0) ? 1 : -1; + } + + return wheelDelta; +} + +function activateNextPrevTask(anchor, next) { + // FIXME TODO: Unnecessarily convoluted and costly; optimize. + + var taskIndexList = []; + var activeTaskIndex = tasksModel.activeTask; + + for (var i = 0; i < taskList.children.length - 1; ++i) { + var task = taskList.children[i]; + var modelIndex = task.modelIndex(i); + + if (task.m.IsLauncher !== true && task.m.IsStartup !== true) { + if (task.m.IsGroupParent === true) { + if (task == anchor) { // If the anchor is a group parent, collect only windows within the group. + taskIndexList = []; + } + + for (var j = 0; j < tasksModel.rowCount(modelIndex); ++j) { + const childModelIndex = tasksModel.makeModelIndex(i, j); + const childHidden = tasksModel.data(childModelIndex, TaskManager.AbstractTasksModel.IsHidden); + if (!plasmoid.configuration.wheelSkipMinimized || !childHidden) { + taskIndexList.push(childModelIndex); + } + } + + if (task == anchor) { // See above. + break; + } + } else { + if (!plasmoid.configuration.wheelSkipMinimized || !task.m.IsHidden) { + taskIndexList.push(modelIndex); + } + } + } + } + + if (!taskIndexList.length) { + return; + } + + var target = taskIndexList[0]; + + for (var i = 0; i < taskIndexList.length; ++i) { + if (taskIndexList[i] === activeTaskIndex) + { + if (next && i < (taskIndexList.length - 1)) { + target = taskIndexList[i + 1]; + } else if (!next) { + if (i) { + target = taskIndexList[i - 1]; + } else { + target = taskIndexList[taskIndexList.length - 1]; + } + } + + break; + } + } + + tasksModel.requestActivate(target); +} + +function activateTask(index, model, modifiers, task) { + if (modifiers & Qt.ShiftModifier) { + tasksModel.requestNewInstance(index); + } else if (model.IsGroupParent === true) { + + // Option 1 (default): Cycle through this group's tasks + // ==================================================== + // If the grouped task does not include the currently active task, bring + // forward the most recently used task in the group according to the + // Stacking order. + // Otherwise cycle through all tasks in the group without paying attention + // to the stacking order, which otherwise would change with every click + if (plasmoid.configuration.groupedTaskVisualization === 0) { + let childTaskList = []; + let highestStacking = -1; + let lastUsedTask = undefined; + + // Build list of child tasks and get stacking order data for them + for (let i = 0; i < tasksModel.rowCount(task.modelIndex(index)); ++i) { + const childTaskModelIndex = tasksModel.makeModelIndex(task.itemIndex, i); + childTaskList.push(childTaskModelIndex); + const stacking = tasksModel.data(childTaskModelIndex, TaskManager.AbstractTasksModel.StackingOrder); + if (stacking > highestStacking) { + highestStacking = stacking; + lastUsedTask = childTaskModelIndex; + } + } + + // If the active task is from a different app from the group that + // was clicked on switch to the last-used task from that app. + if (!childTaskList.some(index => tasksModel.data(index, TaskManager.AbstractTasksModel.IsActive))) { + tasksModel.requestActivate(lastUsedTask); + } else { + // If the active task is already among in the group that was + // activated, cycle through all tasks according to the order of + // the immutable model index so the order doesn't change with + // every click. + for (let j = 0; j < childTaskList.length; ++j) { + const childTask = childTaskList[j]; + if (tasksModel.data(childTask, TaskManager.AbstractTasksModel.IsActive)) { + // Found the current task. Activate the next one + let nextTask = j + 1; + if (nextTask >= childTaskList.length) { + nextTask = 0; + } + tasksModel.requestActivate(childTaskList[nextTask]); + break; + } + } + } + } + + // Option 2: show tooltips for all child tasks + // =========================================== + // Make sure tooltips are actually enabled though; if not, fall through + // to the next option. + else if (plasmoid.configuration.showToolTips + && plasmoid.configuration.groupedTaskVisualization === 1 + ) { + if (tasks.toolTipOpenedByClick) { + task.toolTipAreaItem.hideImmediately(); + } else { + tasks.toolTipOpenedByClick = task; + task.showToolTip(); + task.toolTipAreaItem.onContainsMouseChanged(); + } + } + + // Option 3: show Window View for all child tasks + // ================================================== + // Make sure the Window View effect is are actually enabled though; + // if not, fall through to the next option. + else if (backend.windowViewAvailable + && (plasmoid.configuration.groupedTaskVisualization === 2 + || plasmoid.configuration.groupedTaskVisualization === 1) + ) { + task.hideToolTipTemporarily(); + tasks.activateWindowView(model.WinIdList); + } + + // Option 4: show group dialog/textual list + // ======================================== + // This is also the final fallback option if Tooltips or Present windows + // are chosen but not actually available + else { + if (!!groupDialog) { + task.hideToolTipTemporarily(); + groupDialog.visible = false; + } else { + createGroupDialog(task); + } + } + } else { + if (model.IsMinimized === true) { + tasksModel.requestToggleMinimized(index); + tasksModel.requestActivate(index); + } else if (model.IsActive === true && plasmoid.configuration.minimizeActiveTaskOnClick) { + tasksModel.requestToggleMinimized(index); + } else { + tasksModel.requestActivate(index); + } + } +} + +function insertIndexAt(above, x, y) { + if (above) { + return above.itemIndex; + } else { + var distance = tasks.vertical ? x : y; + var step = tasks.vertical ? LayoutManager.taskWidth() : LayoutManager.taskHeight(); + var stripe = Math.ceil(distance / step); + + if (stripe === LayoutManager.calculateStripes()) { + return tasksModel.count - 1; + } else { + return stripe * LayoutManager.tasksPerStripe(); + } + } +} + +function publishIconGeometries(taskItems) { + for (var i = 0; i < taskItems.length - 1; ++i) { + var task = taskItems[i]; + + if (task.IsLauncher !== true && task.m.IsStartup !== true) { + tasksModel.requestPublishDelegateGeometry(tasksModel.makeModelIndex(task.itemIndex), + backend.globalRect(task), task); + } + } +} + +function taskPrefix(prefix) { + var effectivePrefix; + switch (plasmoid.location) { + case PlasmaCore.Types.LeftEdge: + effectivePrefix = "west-" + prefix; + break; + case PlasmaCore.Types.TopEdge: + effectivePrefix = "north-" + prefix; + break; + case PlasmaCore.Types.RightEdge: + effectivePrefix = "east-" + prefix; + break; + default: + effectivePrefix = "south-" + prefix; + } + if(plasmoid.configuration.overridePlasmaButtonDirection){ + switch (plasmoid.configuration.plasmaButtonDirection) { + case 2: + effectivePrefix = "west-" + prefix; + break; + case 1: + effectivePrefix = "north-" + prefix; + break; + case 4: + effectivePrefix = "east-" + prefix; + break; + default: + effectivePrefix = "south-" + prefix; + } + } + return [effectivePrefix, prefix]; +} + +function taskPrefixHovered(prefix) { + var effectivePrefix = taskPrefix(prefix); + + if ("" !== prefix) + effectivePrefix = [ + ...taskPrefix(prefix + "-hover"), + ...taskPrefix("hover"), + ...effectivePrefix + ]; + + return effectivePrefix; +} + +function createGroupDialog(visualParent) { + if (!visualParent) { + return; + } + + if (!!tasks.groupDialog) { + tasks.groupDialog.visualParent = visualParent; + return; + } + + if (groupDialogComponent.status === QtQml.Component.Ready) { + tasks.groupDialog = groupDialogComponent.createObject(tasks, + { + visualParent: visualParent, + } + ); + } +} diff --git a/contents/ui/main.qml b/contents/ui/main.qml new file mode 100644 index 00000000..ff699a39 --- /dev/null +++ b/contents/ui/main.qml @@ -0,0 +1,538 @@ +/* + SPDX-FileCopyrightText: 2012-2016 Eike Hein + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQml 2.15 + +import org.kde.plasma.plasmoid 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore + +import org.kde.taskmanager 0.1 as TaskManager +import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet + +import "code/layout.js" as LayoutManager +import "code/tools.js" as TaskTools + +MouseArea { + id: tasks + + anchors.fill: parent + hoverEnabled: true + + property bool vertical: plasmoid.formFactor === PlasmaCore.Types.Vertical + property bool iconsOnly: plasmoid.configuration.iconOnly + + property var toolTipOpenedByClick: null + + property QtObject contextMenuComponent: Qt.createComponent("ContextMenu.qml") + property QtObject pulseAudioComponent: Qt.createComponent("PulseAudio.qml") + + property bool needLayoutRefresh: false; + property variant taskClosedWithMouseMiddleButton: [] + + Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation + + Plasmoid.constraintHints: PlasmaCore.Types.CanFillArea + + Plasmoid.onUserConfiguringChanged: { + if (plasmoid.userConfiguring) { + groupDialog.visible = false; + } + } + + Layout.fillWidth: true + Layout.fillHeight: true + Layout.minimumWidth: tasks.vertical ? 0 : LayoutManager.preferredMinWidth() + Layout.minimumHeight: !tasks.vertical ? 0 : LayoutManager.preferredMinHeight() + +//BEGIN TODO: this is not precise enough: launchers are smaller than full tasks + + Layout.preferredWidth: tasks.vertical ? PlasmaCore.Units.gridUnit * 10 : + (LayoutManager.logicalTaskCount() === 0 ? 0.01 : //Return a small non-zero value to make the panel account for the change in size + (LayoutManager.logicalTaskCount() * LayoutManager.preferredMaxWidth()) / LayoutManager.calculateStripes()) + + + Layout.preferredHeight: !tasks.vertical ? PlasmaCore.Units.gridUnit * 2 : + (LayoutManager.logicalTaskCount() === 0 ? 0.01 : //Same as above + (LayoutManager.logicalTaskCount() * LayoutManager.preferredMaxHeight()) / LayoutManager.calculateStripes()) + +//END TODO + + property Item dragSource: null + + signal requestLayout + signal windowsHovered(variant winIds, bool hovered) + signal activateWindowView(variant winIds) + + onWidthChanged: { + taskList.width = LayoutManager.layoutWidth(); + + if (plasmoid.configuration.forceStripes) { + taskList.height = LayoutManager.layoutHeight(); + } + } + + onHeightChanged: { + if (plasmoid.configuration.forceStripes) { + taskList.width = LayoutManager.layoutWidth(); + } + + taskList.height = LayoutManager.layoutHeight(); + } + + onDragSourceChanged: { + if (dragSource == null) { + tasksModel.syncLaunchers(); + } + } + + onExited: { + if (needLayoutRefresh) { + LayoutManager.layout(taskRepeater) + needLayoutRefresh = false; + } + } + + TaskManager.TasksModel { + id: tasksModel + + readonly property int logicalLauncherCount: { + if (plasmoid.configuration.separateLaunchers) { + return launcherCount; + } + + var startupsWithLaunchers = 0; + + for (var i = 0; i < taskRepeater.count; ++i) { + var item = taskRepeater.itemAt(i); + + if (item && item.m.IsStartup === true && item.m.HasLauncher === true) { + ++startupsWithLaunchers; + } + } + + return launcherCount + startupsWithLaunchers; + } + + virtualDesktop: virtualDesktopInfo.currentDesktop + screenGeometry: plasmoid.screenGeometry + activity: activityInfo.currentActivity + + filterByVirtualDesktop: plasmoid.configuration.showOnlyCurrentDesktop + filterByScreen: plasmoid.configuration.showOnlyCurrentScreen + filterByActivity: plasmoid.configuration.showOnlyCurrentActivity + filterNotMinimized: plasmoid.configuration.showOnlyMinimized + + sortMode: sortModeEnumValue(plasmoid.configuration.sortingStrategy) + launchInPlace: iconsOnly && plasmoid.configuration.sortingStrategy === 1 + separateLaunchers: { + if (!iconsOnly && !plasmoid.configuration.separateLaunchers + && plasmoid.configuration.sortingStrategy === 1) { + return false; + } + + return true; + } + + groupMode: groupModeEnumValue(plasmoid.configuration.groupingStrategy) + groupInline: !plasmoid.configuration.groupPopups + groupingWindowTasksThreshold: (plasmoid.configuration.onlyGroupWhenFull && !iconsOnly + ? LayoutManager.optimumCapacity(width, height) + 1 : -1) + + onLauncherListChanged: { + layoutTimer.restart(); + plasmoid.configuration.launchers = launcherList; + } + + onGroupingAppIdBlacklistChanged: { + plasmoid.configuration.groupingAppIdBlacklist = groupingAppIdBlacklist; + } + + onGroupingLauncherUrlBlacklistChanged: { + plasmoid.configuration.groupingLauncherUrlBlacklist = groupingLauncherUrlBlacklist; + } + + function sortModeEnumValue(index) { + switch (index) { + case 0: + return TaskManager.TasksModel.SortDisabled; + case 1: + return TaskManager.TasksModel.SortManual; + case 2: + return TaskManager.TasksModel.SortAlpha; + case 3: + return TaskManager.TasksModel.SortVirtualDesktop; + case 4: + return TaskManager.TasksModel.SortActivity; + default: + return TaskManager.TasksModel.SortDisabled; + } + } + + function groupModeEnumValue(index) { + switch (index) { + case 0: + return TaskManager.TasksModel.GroupDisabled; + case 1: + return TaskManager.TasksModel.GroupApplications; + } + } + + Component.onCompleted: { + launcherList = plasmoid.configuration.launchers; + groupingAppIdBlacklist = plasmoid.configuration.groupingAppIdBlacklist; + groupingLauncherUrlBlacklist = plasmoid.configuration.groupingLauncherUrlBlacklist; + + // Only hook up view only after the above churn is done. + taskRepeater.model = tasksModel; + } + } + + TaskManager.VirtualDesktopInfo { + id: virtualDesktopInfo + } + + TaskManager.ActivityInfo { + id: activityInfo + readonly property string nullUuid: "00000000-0000-0000-0000-000000000000" + } + + TaskManagerApplet.Backend { + id: backend + + taskManagerItem: tasks + highlightWindows: plasmoid.configuration.highlightWindows + + onAddLauncher: { + tasks.addLauncher(url); + } + } + + PlasmaCore.DataSource { + id: mpris2Source + engine: "mpris2" + connectedSources: sources + onSourceAdded: { + connectSource(source); + } + onSourceRemoved: { + disconnectSource(source); + } + function sourceNameForLauncherUrl(launcherUrl, pid) { + if (!launcherUrl || launcherUrl === "") { + return ""; + } + + // MPRIS spec explicitly mentions that "DesktopEntry" is with .desktop extension trimmed + // Moreover, remove URL parameters, like wmClass (part after the question mark) + var desktopFileName = launcherUrl.toString().split('/').pop().split('?')[0].replace(".desktop", "") + if (desktopFileName.indexOf("applications:") === 0) { + desktopFileName = desktopFileName.substr(13) + } + + let fallbackSource = ""; + + for (var i = 0, length = connectedSources.length; i < length; ++i) { + var source = connectedSources[i]; + // we intend to connect directly, otherwise the multiplexer steals the connection away + if (source === "@multiplex") { + continue; + } + + var sourceData = data[source]; + if (!sourceData) { + continue; + } + + /** + * If the task is in a group, we can't use desktopFileName to match the task. + * but in case PID match fails, use the match result from desktopFileName. + */ + if (pid && sourceData.InstancePid === pid) { + return source; + } + if (sourceData.DesktopEntry === desktopFileName) { + fallbackSource = source; + } + + var metadata = sourceData.Metadata; + if (metadata) { + var kdePid = metadata["kde:pid"]; + if (kdePid && pid === kdePid) { + return source; + } + } + } + + // If PID match fails, return fallbackSource. + return fallbackSource; + } + + function startOperation(source, op) { + var service = serviceForSource(source) + var operation = service.operationDescription(op) + return service.startOperationCall(operation) + } + + function goPrevious(source) { + startOperation(source, "Previous"); + } + function goNext(source) { + startOperation(source, "Next"); + } + function play(source) { + startOperation(source, "Play"); + } + function pause(source) { + startOperation(source, "Pause"); + } + function playPause(source) { + startOperation(source, "PlayPause"); + } + function stop(source) { + startOperation(source, "Stop"); + } + function raise(source) { + startOperation(source, "Raise"); + } + function quit(source) { + startOperation(source, "Quit"); + } + } + + Loader { + id: pulseAudio + sourceComponent: pulseAudioComponent + active: pulseAudioComponent.status === Component.Ready + } + + Timer { + id: iconGeometryTimer + + interval: 500 + repeat: false + + onTriggered: { + TaskTools.publishIconGeometries(taskList.children); + } + } + + Binding { + target: plasmoid + property: "status" + value: (tasksModel.anyTaskDemandsAttention && plasmoid.configuration.unhideOnAttention + ? PlasmaCore.Types.NeedsAttentionStatus : PlasmaCore.Types.PassiveStatus) + restoreMode: Binding.RestoreBinding + } + + Connections { + target: plasmoid + + function onLocationChanged() { + // This is on a timer because the panel may not have + // settled into position yet when the location prop- + // erty updates. + iconGeometryTimer.start(); + } + } + + Connections { + target: plasmoid.configuration + + function onLaunchersChanged() { + tasksModel.launcherList = plasmoid.configuration.launchers + } + function onGroupingAppIdBlacklistChanged() { + tasksModel.groupingAppIdBlacklist = plasmoid.configuration.groupingAppIdBlacklist; + } + function onGroupingLauncherUrlBlacklistChanged() { + tasksModel.groupingLauncherUrlBlacklist = plasmoid.configuration.groupingLauncherUrlBlacklist; + } + function onIconSpacingChanged() { + taskList.layout(); + } + } + + TaskManagerApplet.DragHelper { + id: dragHelper + + dragIconSize: PlasmaCore.Units.iconSizes.medium + } + + PlasmaCore.FrameSvgItem { + id: taskFrame + + visible: false; + + imagePath: "widgets/tasks"; + prefix: "normal" + } + + PlasmaCore.Svg { + id: taskSvg + + imagePath: "widgets/tasks" + } + + MouseHandler { + id: mouseHandler + + anchors.fill: parent + + target: taskList + + onUrlsDropped: { + // If all dropped URLs point to application desktop files, we'll add a launcher for each of them. + var createLaunchers = urls.every(function (item) { + return backend.isApplication(item) + }); + + if (createLaunchers) { + urls.forEach(function (item) { + addLauncher(item); + }); + return; + } + + if (!hoveredItem) { + return; + } + + // DeclarativeMimeData urls is a QJsonArray but requestOpenUrls expects a proper QList. + var urlsList = backend.jsonArrayToUrlList(urls); + + // Otherwise we'll just start a new instance of the application with the URLs as argument, + // as you probably don't expect some of your files to open in the app and others to spawn launchers. + tasksModel.requestOpenUrls(hoveredItem.modelIndex(), urlsList); + } + } + + ToolTipDelegate { + id: openWindowToolTipDelegate + visible: false + } + + ToolTipDelegate { + id: pinnedAppToolTipDelegate + visible: false + } + + TaskList { + id: taskList + spacing: plasmoid.configuration.taskSpacingSize + + anchors { + left: parent.left + top: parent.top + } + + onWidthChanged: LayoutManager.layout(taskRepeater) + onHeightChanged: LayoutManager.layout(taskRepeater) + + flow: { + if (tasks.vertical) { + return plasmoid.configuration.forceStripes ? Flow.LeftToRight : Flow.TopToBottom + } + return plasmoid.configuration.forceStripes ? Flow.TopToBottom : Flow.LeftToRight + } + + onAnimatingChanged: { + if (!animating) { + TaskTools.publishIconGeometries(children); + } + } + + function layout() { + taskList.width = LayoutManager.layoutWidth(); + taskList.height = LayoutManager.layoutHeight(); + LayoutManager.layout(taskRepeater); + } + + Timer { + id: layoutTimer + + interval: 0 + repeat: false + + onTriggered: taskList.layout() + } + + Repeater { + id: taskRepeater + + delegate: Task {} + onItemAdded: taskList.layout() + onItemRemoved: { + if (tasks.containsMouse && index != taskRepeater.count && + item.winIdList && item.winIdList.length > 0 && + taskClosedWithMouseMiddleButton.indexOf(item.winIdList[0]) > -1) { + needLayoutRefresh = true; + } else { + taskList.layout(); + } + taskClosedWithMouseMiddleButton = []; + } + } + } + + readonly property Component groupDialogComponent: Qt.createComponent("GroupDialog.qml") + property GroupDialog groupDialog: null + + function hasLauncher(url) { + return tasksModel.launcherPosition(url) != -1; + } + + function addLauncher(url) { + if (plasmoid.immutability !== PlasmaCore.Types.SystemImmutable) { + tasksModel.requestAddLauncher(url); + } + } + + // This is called by plasmashell in response to a Meta+number shortcut. + function activateTaskAtIndex(index) { + if (typeof index !== "number") { + return; + } + + var task = taskRepeater.itemAt(index); + if (task) { + /** + * BUG 452187: when activating a task from keyboard, there is no + * containsMouse changed signal, so we need to update the tooltip + * properties here. + */ + if (plasmoid.configuration.showToolTips + && plasmoid.configuration.groupedTaskVisualization === 1) { + task.toolTipAreaItem.updateMainItemBindings(); + } + + TaskTools.activateTask(task.modelIndex(), task.m, null, task); + } + } + + function resetDragSource() { + dragSource = null; + } + + function createContextMenu(rootTask, modelIndex, args = {}) { + const initialArgs = Object.assign(args, { + visualParent: rootTask, + modelIndex, + mpris2Source, + backend, + }); + return contextMenuComponent.createObject(rootTask, initialArgs); + } + + Component.onCompleted: { + tasks.requestLayout.connect(layoutTimer.restart); + tasks.requestLayout.connect(iconGeometryTimer.restart); + tasks.windowsHovered.connect(backend.windowsHovered); + tasks.activateWindowView.connect(backend.activateWindowView); + dragHelper.dropped.connect(resetDragSource); + } +} diff --git a/metadata.json b/metadata.json new file mode 100644 index 00000000..f4361387 --- /dev/null +++ b/metadata.json @@ -0,0 +1,181 @@ +{ + "KPlugin": { + "Authors": [ + { + "Email": "Hein@kde.org, ideas@alexankitty.com", + "Name": "Eike Hein, Alexandra Stone, Alexandra Stone", + "Name[ar]": "Eike Hein, Alexandra Stone, Alexandra Stone", + "Name[az]": "Eike Hein, Alexandra Stone, Alexandra Stone", + "Name[bg]": "Eike Hein, Alexandra Stone, Alexandra Stone", + "Name[ca@valencia]": "Eike Hein, Alexandra Stone, Alexandra Stone", + "Name[ca]": "Eike Hein, Alexandra Stone", + "Name[cs]": "Eike Hein, Alexandra Stone", + "Name[da]": "Eike Hein, Alexandra Stone", + "Name[de]": "Eike Hein, Alexandra Stone", + "Name[en_GB]": "Eike Hein, Alexandra Stone", + "Name[es]": "Eike Hein, Alexandra Stone", + "Name[eu]": "Eike Hein, Alexandra Stone", + "Name[fi]": "Eike Hein, Alexandra Stone", + "Name[fr]": "Eike Hein, Alexandra Stone", + "Name[hu]": "Eike Hein, Alexandra Stone", + "Name[ia]": "Eike Hein, Alexandra Stone", + "Name[id]": "Eike Hein, Alexandra Stone", + "Name[it]": "Eike Hein, Alexandra Stone", + "Name[ja]": "Eike Hein, Alexandra Stone", + "Name[ka]": "აიკე ჰაინი", + "Name[ko]": "Eike Hein, Alexandra Stone", + "Name[lt]": "Eike Hein, Alexandra Stone", + "Name[nl]": "Eike Hein, Alexandra Stone", + "Name[nn]": "Eike Hein, Alexandra Stone", + "Name[pa]": "ਇਕੀ ਹੀਇਨ", + "Name[pl]": "Eike Hein, Alexandra Stone", + "Name[pt]": "Eike Hein, Alexandra Stone", + "Name[pt_BR]": "Eike Hein, Alexandra Stone", + "Name[ro]": "Eike Hein, Alexandra Stone", + "Name[ru]": "Eike Hein, Alexandra Stone", + "Name[sk]": "Eike Hein, Alexandra Stone", + "Name[sl]": "Eike Hein, Alexandra Stone", + "Name[sv]": "Eike Hein, Alexandra Stone", + "Name[ta]": "எய்கே ஹைன்", + "Name[tr]": "Eike Hein, Alexandra Stone", + "Name[uk]": "Eike Hein, Alexandra Stone", + "Name[vi]": "Eike Hein, Alexandra Stone", + "Name[x-test]": "xxEike Hein, Alexandra Stonexx", + "Name[zh_CN]": "Eike Hein, Alexandra Stone" + } + ], + "Category": "Windows and Tasks", + "Description": "More modern style taskbar-style window switcher displaying icons and text, with some improvments", + "Description[ar]": "مبدل نوافذ تقليدي بنمط شريط المهام يعرض الأيقونات والنص", + "Description[az]": "Nişanlar və mətn göstərən klassik tapşırıq paneli üslubunda pəncərə dəyişdirici", + "Description[bg]": "Класически превключвател на прозорци в стил лента на задачите, показващ икони и текст", + "Description[ca@valencia]": "Commutador de finestres clàssic d'estil barra de tasques que mostra les icones i text", + "Description[ca]": "Commutador de finestres clàssic d'estil barra de tasques que mostra les icones i text", + "Description[da]": "Klassisk opgavelinje-agtig vinduesskifter som viser ikoner og tekst", + "Description[en_GB]": "Classic taskbar-style window switcher displaying icons and text", + "Description[es]": "Selector de ventanas al estilo de la barra de tareas clásica que muestra iconos y texto", + "Description[eu]": "Ataza-barra tankerako leiho aldatzaile klasikoa ikonoak eta testua azaltzen dituena", + "Description[fi]": "Perinteinen tehtäväpalkkimainen ikkunavaihto kuvakkein ja tekstein", + "Description[fr]": "Sélecteur classique de fenêtres en barre des tâches, affichant des icônes et du texte", + "Description[ia]": "Moderne Commutator de fenestra de stilo a barra de carga monstrante icones e texto", + "Description[id]": "Pengalih window gaya taskbar klasik yang menampilkan ikon dan teks", + "Description[it]": "Scambiatore di finestre classico in stile barra delle applicazioni che mostra icone e testo", + "Description[ja]": "アイコンとテキストを表示するタスクバースタイルのウィンドウスイッチャー", + "Description[ka]": "ფანჯრების კლასიკური გადამრთველი, ხატულებსა და ტექსტის ჩვენებით", + "Description[ko]": "아이콘과 텍스트를 표시하는 고전 작업 표시줄 스타일 창 전환기", + "Description[nl]": "Klassieke taakbalkstijl vensterschakelaar met tonen van pictogrammen en tekst", + "Description[nn]": "Klassisk vindaugsbytar med oppgåvelinje med ikon og tekst", + "Description[pl]": "Klasyczny przełącznik okien, wyświetlający ikony i tekst na pasku zadań", + "Description[pt]": "Selector de janelas clássico em tarefas que mostra ícones e texto", + "Description[pt_BR]": "Seletor de janelas estilo barra de tarefas clássico mostrando ícones e texto", + "Description[ro]": "Comutator de ferestre clasic cu bară de sarcini, afișând pictograme și text", + "Description[ru]": "Классический вариант панели задач, использующий значки и текст", + "Description[sk]": "Klasický prepínač okien v štýle panela úloh zobrazujúci ikony a text", + "Description[sl]": "Klasični preklopnik oken z vrstico opravil, ki prikazuje ikone in besedilo", + "Description[sv]": "Klassiskt fönsterbytare med aktivitetsliknande fönster som visar ikoner och text", + "Description[ta]": "சின்னங்களையும் பெயர்களையும் காட்டும் சாளர மாற்றி", + "Description[tr]": "Klasik görev çubuğu tarzı, simgeler ve metin görüntüleyen pencere değiştiricisi", + "Description[uk]": "Класичний перемикач вікон у стилі панелі задач з показом піктограм і тексту", + "Description[vi]": "Trình chuyển cửa sổ phong cách thanh tác vụ cổ điển, hiển thị biểu tượng và chữ", + "Description[x-test]": "xxClassic taskbar-style window switcher displaying icons and textxx", + "Description[zh_CN]": "经典风格的同时显示图标和文本的任务栏式窗口切换器", + "EnabledByDefault": true, + "Icon": "FancyTasks", + "Id": "alexankitty.fancytasks", + "License": "GPL-2.0+", + "Name": "Fancy Tasks", + "Name[af]": "Taakbestuurder", + "Name[ar]": "مدير المهام", + "Name[ast]": "Xestor de xeres", + "Name[az]": "Tapşırıq Meneceri", + "Name[be@latin]": "Kiraŭnik zadańniaŭ", + "Name[be]": "Кіраванне заданнямі", + "Name[bg]": "Управление на задачи", + "Name[bn]": "টাস্ক ম্যানেজার", + "Name[bs]": "Menadžer zadataka", + "Name[ca@valencia]": "Gestor de tasques", + "Name[ca]": "Gestor de tasques", + "Name[cs]": "Správce úloh", + "Name[csb]": "Menedżer dzejaniów", + "Name[da]": "Opgavelinje", + "Name[de]": "Fensterleiste", + "Name[el]": "Διαχειριστής εργασιών", + "Name[en_GB]": "Task Manager", + "Name[eo]": "Taskadministrilo", + "Name[es]": "Gestor de tareas", + "Name[et]": "Tegumihaldur", + "Name[eu]": "Ataza-kudeatzailea", + "Name[fi]": "Tehtävienhallinta", + "Name[fr]": "Gestionnaire de tâches", + "Name[fy]": "Taakbehearder", + "Name[ga]": "Bainisteoir na dTascanna", + "Name[gl]": "Xestor de tarefas", + "Name[gu]": "ટાસ્ક વ્યવસ્થાપક", + "Name[he]": "מנהל משימות", + "Name[hi]": "कार्य प्रबंधक", + "Name[hne]": "काम प्रबंधक", + "Name[hr]": "Upravljanje zadacima", + "Name[hsb]": "Rjadowar nadawkow", + "Name[hu]": "Feladatkezelő", + "Name[ia]": "Gerente de carga", + "Name[id]": "Task Manager", + "Name[is]": "Verkefnastjóri", + "Name[it]": "Gestore dei processi", + "Name[ja]": "タスクマネージャ", + "Name[ka]": "ამოცანების მმართველი", + "Name[kk]": "Тапсырмалар менеджері", + "Name[km]": "កម្មវិធី​គ្រប់គ្រង​ភារកិច្ច", + "Name[kn]": "ಕಾರ್ಯ ವ್ಯವಸ್ಥಾಪಕ (ಟಾಸ್ಕ್ ಮ್ಯಾನೇಜರ್)", + "Name[ko]": "작업 관리자", + "Name[lt]": "Užduočių tvarkytuvė", + "Name[lv]": "Uzdevumu pārvaldnieks", + "Name[mk]": "Менаџер на апликации", + "Name[ml]": "ടാസ്ക് മാനേജര്‍", + "Name[mr]": "कार्य व्यवस्थापक", + "Name[nb]": "Oppgavebehandler", + "Name[nds]": "Opgavenpleger", + "Name[ne]": "कार्य प्रबन्धक", + "Name[nl]": "Takenbeheer", + "Name[nn]": "Oppgåve­handsamar", + "Name[or]": "କାର୍ଯ୍ୟ ପରିଚାଳକ", + "Name[pa]": "ਟਾਸਕ ਮੈਨੇਜਰ", + "Name[pl]": "Paskowy przełącznik zadań", + "Name[pt]": "Gestor de Tarefas", + "Name[pt_BR]": "Gerenciador de tarefas", + "Name[ro]": "Gestionar de sarcini", + "Name[ru]": "Панель задач", + "Name[se]": "Bargogieđahalli", + "Name[si]": "කාර්‍යය කළමණාකරු", + "Name[sk]": "Správca úloh", + "Name[sl]": "Upravljalnik opravil", + "Name[sr@ijekavian]": "менаџер задатака", + "Name[sr@ijekavianlatin]": "menadžer zadataka", + "Name[sr@latin]": "menadžer zadataka", + "Name[sr]": "менаџер задатака", + "Name[sv]": "Aktivitetshanterare", + "Name[ta]": "பணி மேலாளர்", + "Name[te]": "కర్తవ్య నిర్వాహకి", + "Name[tg]": "Мудири вазифаҳо", + "Name[th]": "จัดการงาน", + "Name[tr]": "Görev Yöneticisi", + "Name[ug]": "ۋەزىپە باشقۇرغۇچ", + "Name[uk]": "Менеджер задач", + "Name[uz@cyrillic]": "Вазифа бошқарувчиси", + "Name[uz]": "Vazifa boshqaruvchisi", + "Name[vi]": "Trình quản lí tác vụ", + "Name[wa]": "Manaedjeu des bouyes", + "Name[x-test]": "xxTask Managerxx", + "Name[zh_CN]": "任务管理器", + "Name[zh_TW]": "含描述文字的工作管理員", + "ServiceTypes": [ + "Plasma/Applet" + ], + "Version": "4.0", + "Website": "https://userbase.kde.org/Plasma/Tasks" + }, + "X-Plasma-API": "declarativeappletscript", + "X-Plasma-MainScript": "ui/main.qml", + "X-Plasma-Provides": [ + "org.kde.plasma.multitasking" + ] +} From d947d9d8e84f2e39c5b8f1e92f39b260f197ec66 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 27 Oct 2022 03:26:55 -0600 Subject: [PATCH 004/141] Add pictures --- docs/Ciliora Full.png | Bin 0 -> 1931 bytes docs/Ciliora Short.png | Bin 0 -> 3581 bytes docs/ColoredTasks.png | Bin 0 -> 8754 bytes docs/Dashes Full.png | Bin 0 -> 1688 bytes docs/Dashes Short.png | Bin 0 -> 4087 bytes docs/Metro Full.png | Bin 0 -> 2304 bytes docs/Metro Short.png | Bin 0 -> 3622 bytes 7 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/Ciliora Full.png create mode 100644 docs/Ciliora Short.png create mode 100644 docs/ColoredTasks.png create mode 100644 docs/Dashes Full.png create mode 100644 docs/Dashes Short.png create mode 100644 docs/Metro Full.png create mode 100644 docs/Metro Short.png diff --git a/docs/Ciliora Full.png b/docs/Ciliora Full.png new file mode 100644 index 0000000000000000000000000000000000000000..867e0918d68d614ea9bd73f454562ff78cd6e84d GIT binary patch literal 1931 zcmV;62Xy#}P)iECki4zU-whYmYQdU|(S~`kifil`s zDQ#~{UvBU7`|gj^m+RrS*82iXpU*!%=XcIM=Qj7-=XuU^&#A)tDi}rrSnh&h#EHq4 zktilxMxvN(8Hr+pbk__c9&Es5%SZ^*ZW)PUvSlQS4QhAIFyg^RsLx$9jCfFAFJ9oT zg*kh+0YF~fH1`I>_^5c8`7I++Oty?fG1)Q_#bnD!6q79@QB1asM6un4F)OT75$E)i zbJJ@xI)gA%vY%f4BFLQ_|8~pMr;AdjyQ{{hiP+xzA72}NyET%YKzDvx`r@>C?hRqy zXgb=5kh^MpQcy%OhCXp5qIK=QN_RDkg3<+m$6Yr*F@&tW&>mB^o~-yoT2}hdDkBZQ zTskhaZusgC5uef6_^l16Xo(?~q%3biphQc>jJzExt z{4yg})N;Hzwrp8GySKL&fKtk-T)E&{PR&a9Ci{S%p~^68%C|Q@|NZHTfCK|g?;Uyb z)xT^z+!F7;ldV;+Z>~SrWrCG3BBW+a+0t5j!g|#}UE{fb)V#a*2t^SfpoN+sDWnKV z32FIkYF;hh3q>Ap1in_C8hm zz&8sHZao>Yb8r6cqu;yz^Aqi!3)MR}|NfQgjFIVy-Ok@V_sX#VvhOW<@r%2cmh2A}Ec@*WZm*eo&z*(YNtaLU z-Mn#2#RsFmHDe4YLd_`WAUt9V%WB^*ukF6nNm`;vf}#MB zBo&>XnwnZ`J+^!F?K7tNz7ROO`BO{l|{m*RH%fd$^wk09ZM< z-Qs&~{jwzwuHF{BYxP54PE!Ej$-DV;XG$M?_&dvg`F85U6~*pJ7rWr@+k$^x_t4S@ z)@<*;W5uFEbBPfLB7#s1^YTf`o2+aFr2q&-LBS$HMG++e0wRh~LJ<*aaTY{KS1?A> z)!BuVaVhqsn~J8L*tM;;LnG9B_|;wKX3oE9qU#u;x_!G&b_s%w`*s`%-Z*!L4FJ+n zvFGjcL87;z@_1`jPPXe8X0UqCj#FKNU}M$cb7?s_z7KCVq7hTO1pq>?W&4x|fGA6e zqJU5o=g}cLU8R#I(V{6@M6?KX=p*{X0m`55M`uST{pl0>+Sw1kEJ|{ zid0a_=>g%aQi*8oB+F^Bw08Q$u|?XRdTY_t#+sT-(%v3OnmBQs^RX*`R)*Eq-tLO0 z@@M#+9juJ3jNU+JKLEfP3yxw86DP*UBqG@<9t%h=T=dw=;{1<2swXKFz@kS{!J-fl z3kotgxRSwcP;;PPq-Z_rz=bBP38Z3|AucYp5^zz&YZKT zc653_HWzhLGBkMd2rW5F%fJBLn=b`~SSSe(&jLnY@F%%0O#=Ea$avjQWb zP?JI>q_Qk%IHPvaPOwDlfj&^^tb~MGD5JI%zFXJ)dB>00-`(19;?V0)ZrXh!K!E3W zKJ$F)qd$1=PoMDxTWWS~eBtjc?t^q6JJxgW(=Y!l+uL6I#&5P9>`KI!4#t=e7@zEm z@>vWoJ&)i^niMD@wTKpIIxUqGED_Nm5us=&X4E1f5gno~&-=i2z}TqVg}*ADv3<#} z%Lm3z##J#=JerzYG7D!%|EE3BXhF0fELhN_6D&<3DbAS7i62EMlBg#l%_#hOq5Jz< zsw-m1mXM&6DreeV2u;zV#pwr~Kxs{CinAs{ttCO(GOibynVE?C-avs=UVN7n5eOhc zg2I6dLc$rj502kS!O%ug9suLrM~n%ZU;F8O?xJzcq>LMfsI#RNkL0$wtC1-{0an!K zGX77EX`;z6qF}ORB#Qlb`g~XEqVB2+Hk|0Y;Ho=j`KHYC=1=kr-x6qCLoE_G7_2`Y z{O?d@amw5o-rTTV0N`YQ^WS=g|Ji%I_6b*LXV3Ob&h?}XRU))oS)SC{-YM?tpd#ON z6Rhh;wl!g%H$S{`WgxCB#%rH&bM2|&!9v7r0kBo%I)D(z^fj|_)r|6CT}@X8Bf{Hi z4h5=$4esio%KkGg5^z_IYot-P9}L!qS5EdvxTn@tjMqNl-qGhT%H{CN{{VyjP)8J` Ri~;}v002ovPDHLkV1jYX!EXQn literal 0 HcmV?d00001 diff --git a/docs/Ciliora Short.png b/docs/Ciliora Short.png new file mode 100644 index 0000000000000000000000000000000000000000..3973389293ca33bed23d182070c2a8efb1584abc GIT binary patch literal 3581 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 literal 0 HcmV?d00001 diff --git a/docs/Dashes Full.png b/docs/Dashes Full.png new file mode 100644 index 0000000000000000000000000000000000000000..d5d8697ccc41780816b84e0e51e69d51f4bdb9c9 GIT binary patch literal 1688 zcmV;J250$+P)hcF*_v z;}j@ETXwsp26~=9-T7vAW;gThIp0int1xXdEUT>?Z^5!+;ezzmEGud*U;|{eogIO! zxYz($adAQItyxyoTttp|YnBx?b^Ea4-WsrH&t3poS-rd~EbGL0*!w_MTx@`>xYz($ zaj^li;$j12#l;55ii_(loJw}FYWC)Jm&}x+)ao$oZOP81-9{ka5j`-ex3_AY?P4B* zT2dFPy*N2#RPxo{6-|7zf7=m6yjAN=)@}h3t&3J~@>ZKrP`VG`^VY31T3Z72`i75^ z(^8HtvbmPXBY2=<#?4QneLAFbZhPf}q1&FGw(L;z2X^~US~#}i)hUa1H9efl9RBKz z?C&SdS{rKqX;xdbB|uJsTVG!fKq+M^CqM8!PD)GhcS!*1j#Z9xE_z`0+(&vV0um1G z|8wj2Uw*b^%fa@Z>R7S)>jkA{H8wr%sx1N1TKk$jF;u*-?7PB0R&Avy0tB>B6C{Nc zAt@0p7bImB@y|%}Jy1A*)}uLV!fsMV_D%Oc^?c67xi8FI)4~ALRt@Fb*Oq&WR-9rB zkk4_(JwC2<{tpy_1OZTl`-{sI6`%wV3JFD!fHcNP5kjF7?;cOUNKJX+irne`H*&|^ z)o1;pl8Bpm-9r-}zV)*1Zry=`cCIZbU01Mc-EX_{3rp7){gq!-d#IXpM3DqV0U${#n!lQw zT5BEM*RSQkrp>$4F7KD7oL=`#eddbN_a==VJ$~}X!CRky=8p8^(;@)C$++eEgs-NJ z8~y0yCE=lyAG`2}MMx#XJxpJ!iiqHPtof+O4a5 z;k5&M?Z{hF6x4`RZ22;;tlyw(yLfOTfJ;u_^JVYT>y~ahLu159VY7c zZu+evEhF9YJ{c}pxol^RAiQt$ma^oGjD!={ThWR+KoI&JH$nLTh;o!D3J66pzwe-# z*-T_ai>7E1(IV85Q%qrvR3IgQ>R>ekDd!%ktgJQT7DE-45(osmuekQ`VY7i$9SSBU zC%FK?P}R|EEoyO^_VcD#8>|YOhav){oG7zxd3aC9DUk%}gU?YuMMWwoWhN|`MJf@k zO?=GQqqUjB7}e3-o;M8axv#MBkW^KL61#WrX3nh&q@_BQRaKr0sz7SMY~ZA(rPhb4 z8vp>NKWjx4_a3Y$II(rnfa!__aOhK1a3}=Cfr1=uc;x7;rP(-*QM7LLCJ+I@NleKa zaNp#YM|S;T(aJp{`}2SP>(V<%T@moXJ+J@0!+QSy(?-)HALm{=Xn4PKeJbI?!Nae2 ze%)Bo+EJ`_=laq7g>_3P)TB@esT>Cyrd<|o(j!_oPFX^;5D{vjwECG(xM9kt%bsIH zZN=Ul8^3;i{)!zT0{naV%(+PupP2K>`3d2Jg?Y2*eS6TmliKau>qbof@TGKrRna$Z zFI->47_Tg?xWx9QdOv+n;TlZ}l#p6P3pCA`W6~ocIwB$zZL&ly5)si6>in#KJUfh! z${hJ-Zr`P&-^y?7XRHpW1gqbVfC^g$+L6rsrJ`T?44fB#Rh z2S`ZJM917{7D7|BXfe~4NsZQ|rkEuWYAvTJK-T{$wg3ra)4zX^A_4(KNKn{#xkZ?k z`Do)z3XZK5IR!eMv zthjWR`DIks0e$_Mo?=Nu`4@G^|3zd+ZgbY?EF;j#XY}M^M{aZ0=qv%UPLs|Oppu4W izKrN8cH}l^jsF0fz~q3x%s9~i0000^B?{v>)XJ=P?(TbIX5I2LcFu{co5F;)| zRD`L7s>BZQj~J)o3Q0MsN~qwJLpf!aEB=vk{-lyha2yB94kj48C@vPn*y0XCvMzvb z2z1+JC9PK4+w5HXd~bf7p4r*fu6A~2Bm*^1t#(g;XXbSG>Gyp7p3^NkFp_U;kBx45 z_mj^~p+$?2ERy`juc4aPXhn+_A1(ZRV56}XEk1(yAfvGsEk1&@q}<|Tf)BO~MvIRF zK7v9t)}qBn5V?KBozd8796me%;KBXE+WxTGdOg}?R`Zh za+Y>9D>a_`S;C$Bw=VcxwBnrb&4HgsL#I(K7r(09VouJbd|T8=B<-1*o4-kBP01}< z)X0ZO$}L*d&gp5dCFK?$6Fw|bZn=vVwKJ<$7BKB2`JtWt^!4>E?LSXRRe~gyBwdk8 zfJzO6E()cR7#kbQX0y@eTGYl*ueq3p5JE^p7*GfS3?ZZ|7`k9sRmJLq!Bu-t&ImQY z0;D`IpT2HQx}(F%ha^JH5K5PJtCZxbF`1d%w`*^-p(yi@A5}d*Jgin#ttzcrwMuHZ zt+c9Yt&(c3Ri&y`Rn=6g&G%!`<`&2mdu7&#rpf-UUEPyKoW+MwB~|n<7Xd^da6b|j z$`QDTL^?95rf^_DWR@eZk?j}s(uvh0j8pS;nVy~=bYF~F{N-b#D+lX&J~!9l`h|Ru zNH#~%14BcZ%v303mjc5)=%h<()iz0GdwVL{N?qh~xnv@tYMnsUIt4quT2;=XV{4Tp zu&A?9DbIyhus5VHelfE@TG2ezkKO$@_s4uQFqM66WJG*{5Ah@{_!22QM|neA&-Ht! zdiRZgbMSlFQYPAH?Wl-=geVBOG86zI5S5uhH^8{^Xz8mznTQwW&rl1(Z|}LkIQd=U zdC{7MlgUg?i+84ID}9~*X=L7xQF7PuG1{nJA*hs{Nfk)<@yz=FdM7m;INLF@duYDq=OfI@EGJzN zf{Mp){p=T>+xUU%9m`fcaOKs1{N}IT&y6Pn{`JpJ^dB>B?{#qIqxAvwuY6#1=*zy} zsLiNSZKz<7=PzG=WMH6@hAZ`9dY<=M)dtB>$1`&AOa)U(_`aXd=WEn)?R;zV!ySve zDx0;O*ZA?1-?`~tH0Gpf^_^p5;!o=pduP|KFjOsf(tSAE(85ur7296)mS;OqbuUmQ z%I3!N{jWXrom6kx_@tD^ei$6a+eC5u;RhhVLTRh;8Xka}AMiijZD`*4a0-%D>T409F zFursw((L5@FTH4PzInsa^Z(_xJ6`?eVp;S%y z2*uhZy?t%|(?dsTVkX_`k52?Yc!^*CV!X3$>1Qt8|LEqplsqXB#?s>%tW}xX^%3@d zXZKCnQ?*K&b0p?an+&fNNs!rG?#ZW~xqba@#bR;)d+(9eiJ5HDU7n;>yQh8h)#7{E z%#=HScL1y$*n8acx2KjZTl%9%eq1ON;_-ynjLEKN%spSZ=fH!ToNEH%2KCXs1402r z5w2kiK>`{ITHM;UG}HrBr6mAC=rNpO@dLYPJU8^>?#uu1GsgFhJofyemAyWTdBAxL zx*x4YPIDqE6js}eFRi+0RaeJT?;ny>V)fDNUmZ_e|G@8)Jowa>gO5Iwr1ecw;S+Gj z5NR+%?K(z9%JKN}1wAL=Y-+B$v6Jp{k)Y;s*=L`7Zrx4mN~PeyfdgS(Q?oKawX~|8 z9gD2hd^StC19E?1p+F7 z8%dzzYcK6g*etTSFKqwd+Cy^rH-67c#*RGs(xD$b8HcBc1*8!W;?z8|xfv|9W9pyk z@iaA0>sZ5o)0%FCj4z78wXYg$jg5NeWd(6$Dg;fICdOxu~it>s^%!aalPOu`o7zEWQ6A?z(Xx zW7J=P({aZQf?$IpSG@?3#?bfeJ>9znaC{i^GE;r-=}U_ zd-$1G1wLVn2w)Ua9#qXFlyb2!Ff(2goT=tewGk1Mu~=;F4cBeov3=;s00}=93)QU3 zrb*eYQiQ7)sZ{E^wQE;@@`@k+=zqq>#!uIArPvfHLm4wZ$P%rJ5rq;Ip@x3L`3@&u zwQ8y5#T6SgW-ye51%+N=GBvQxKRHN-3)IB;wzlh0my)n$cu4ovPJ>|6Kg?2%y` zXeeR|fU*MXr)pg}v>BZfqhH;z_nP)#*|+~dVipQgg*3S42!|EEcD6dmsJZ#{f)=w_F?^86F)Si?mZ8Btd%ctU#4YK%Bb~IDbs2 z2I2Cy%g5F_gTcmL=u*`sZQkVjTjR&~Ky3gFkBt1;efJehB@sy`67an1v}fHz8!dec zAMh$3Bh}ZTgAENNsGIPGHly#v`~8Evp74uu`EOmcVrf@AcKD$ueQM0aNoTi=({W`i zMcQkGP{8@jE9v%`H8tbpSdnH$#3Vi6yXM+8Z|{8j=+Flw;I1yT6sTuBfiz3X&R)FF zley9qNeOVpj@=hsb@`iHwwyRI0>N}PE*Gb!vQ5hhB$WyndO{1Mssc5TaCBSeE1ZTI znhdJ7jV&qz0C-3D=ud~<4#M6iNmVt*K%``?Si7lsZF-!$OLflXk7*#7`&@3qf*6NrEP9!s#$q8%qDdMxeAxZT$2Jv?t?tu3!Jb z(W7r}-|qT8kw_Ga#UKcbF#;5d#UPjaS+D8r==_5deF>E%Yc6SD)*J6gYJ&%$0zqnO zWZA%LesRhIB&}-6+F!o@^6Q=5cPHB}EI8ppAc`;<6KGla z?%o82%f|={O~#)bd%Z3GUPIH^GG%K)r|HULKR*^DX#)#D3_t*7H{$M34MWme>wZHd z+16Ib=ja4`CLK3J%Rrctp;loPmUM!)q)W$^N>Wv=RizEpP1S~_Y)ggVw>C$kvoTpN z9L4tPIM6e5a{*jAwmFeMj*gD<)g*x+2#g2-XL1Hh#sBQ^zB08W!I*_n_!gehD11Vu zMr(S;TnqlxsefwLOP-}-!Sj7G%+BGdkyQ0Ok0e#0aB10nC@9tcpsN~}l^rCFF^Obb zu}}bT1|7RUjboJrorslmGe7Iz3Q?DXY28fE*=D-9wc4nZdwYAMAppSb8#eU!_g6NL z9Xs}a8#h+fH-~TE`^9(n?YsDrOFZ`ikFzT>Jp~ek3C$SOgG5pdA%H0P#*VF5ulm$0 zU;qAebB*CQOUD4RQ<-9+NCIVtf$}eaZcVj(TL}|)JQ1&Mp>Bep6a?YS$3;XW7LS*T zMGz3U^*Dz1hT*zP)#vL*p<71YCDn~nRT5N&OBHl8Qs*dWNh&IpDjtA(r`rI4w$zLl zzK!v2yyaE^Jv}|*PxtNOCH)(I_bvdhys$|d9zPWbEb8idVbiAD)~~Phqr30AE_MYc zf^n~uHGX&C6R^rBe(`kw;`6FoYmgdsT+{XL>*W-~*zE(=0S&q)Jb?1HniV*Zx|0A=h694n`t<~`+s`;Me znjVt^a7wce=eI_y&oX`8-C_&?s-76F(SS8X6CMyaoGz;i^~IZu({Xj7SvdVw7n%~E zD`D4x({Xj-T;gk+zRHcMM%hS;lS$)W+5R%hJ16z zOuw~nUoC*Lvav^<4+#M?q01*iMA4xV2C-4)2q$k|*u=~u^obexY?GBy@ z`NE)1xGs7G4jbH!y+O0o+bm_r?Z|q$3 z(4sq9AA5N5p48h(Z02K6mB0JYGi%}lzbxc*q0t?U?cyA<3WEOjZDUJ~5SC;CiAAeN zR5Ye5oE3F?dwb!_3k=u@v~!B{Bbia4r$0G@bu5((_70wuA zr_|s0uKK!nDnDMig(?IH7^NXdDyd3RJ)>vmlvQ!JH}D+Jt$60n`Kw(gXH@yL@7({$ z{Ba9@{`BhO3}B~9qH)`r#$XsSh>(OqY5^^ZL>62zWqosNEIYH%aVBi2lkAd`OG^tU zjqcuAeRAP!%bIiVoSK*3qZ0JHr79bC)d>X<1(Zrc2olhwc0wqXqQM@If?ii+WVZ zNyed1RxW&Y(fZF${HKMa0aa-TK#;7e{v68jOkPJ%{RcbG`|jnIW7qz3WnNj4L-*tx zzqVSn>#ILmv%O~R_C0HN?5U`%SyT0CMOF8~PSR2#390}fNecbnhK9x%gS3V$ZQ8hL zZ}FGUFBWU;x92@Lx#q=(X3xHB?q55udgQ_DN{*Ci0Dv{>%FCj!KRRdjopYDC*Ur8B zid+EzyX?|)_b&L!z2Cd*H}B`nx@X3izCa$^X=JIeYGYF_E zJkXGaFn|F)0w}9*$?)9V=poCo0c4Mj^|f^Za&qASWJn}a9DxV`g$e`~2?|w36$Dg; z5T&Xrjrt8$GGNQ`=<4i3R(6&%`jV+*tCuaQ>M-zHH@~*5?)sP#gz$JQXH|}UH9#s-}Z*;e>So%qq!mZ!5xh{9qsOZt>Lr#U{ z24x`;6Xdqj5o*6Qxs#(4Ffth0-VH22|@5z7IYpi!|zp#(*!$qMUN zT3<0WYN$q4jVg_Il9HN4^78Z0+0n_o{E>ZaZQcI3$arg;=H=yC=soJ{?n8(C3$*=U zN5-Ta$G^D!@LH5ct zuCczWxBE*MOzhiH)46;9S<}ASUE6FtO-neEAZ^%2ph_hm@aJjp=WT?lXMElKvCSC2 zq%y5B)G57uYH9t3%7dC{k7tw@W((p3B(J!@YO8J!I4gMtd4gsFRzYz=Z@e=B0Lf|V z2}olvC**%bRZFt$&QCW*o2sG41Dab}?wdQ;O(aAlGb01GeTf!MdwIE`W8kEvgTD$; zz@jY_SX2UPL7;~xY+$LY4l3r!-1E z;g}M={NY!Y{)~z4*4pX~Z#@3e^6EGN9(eod=W`yo@43I76?K~{mp%K!znX)cbZ^_% zbJLSA|FR^~UiH@R7p?2!={+$CIduq($c)}Fefoihh7DV{k|ddtk>R?o=XsW83DD=d zUQf@GB5P#s$dmsQO@#LS_?jUVqNGtZ3PXQP^KDaAwrL{p>VL)*RxlvpD#j*Lr9ju5)9*b50 literal 0 HcmV?d00001 diff --git a/docs/Metro Short.png b/docs/Metro Short.png new file mode 100644 index 0000000000000000000000000000000000000000..0a7dbcf79468348647e5ccf053a5a7ea62dc67bd GIT binary patch literal 3622 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 literal 0 HcmV?d00001 From 5fb0d03b41ec7c0b98a44ba6dfc6ad064fe12b01 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Thu, 27 Oct 2022 03:38:08 -0600 Subject: [PATCH 005/141] Update README.MD --- README.MD | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/README.MD b/README.MD index 79401c4e..d42445df 100644 --- a/README.MD +++ b/README.MD @@ -1,8 +1,40 @@ # Customized KDE Task Manager -Features improvements tweaks and options to the original task manager plasmoid made by Eike Hein. + +![Fancy Tasks Icon](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/FancyTasks.png?raw=true) + +Features improvements tweaks and options to the original task manager plasmoid made by Eike Hein, licensed under GPL V2.0. + * Implemented adjustable task width. + * Implemented switching between taskbar types. -### Todo -* Implement marker changes and task designs -* Allow coloring based on icon dominant color \ No newline at end of file +* Indicators based on dash to dock styles from gnome, using [latte-indicator-dashtopanel](https://github.com/psifidotos/latte-indicator-dashtopanel) as the reference implementation. +* Customizable indicator locations and colorizing of plasma. Note: not every plasma theme will color in a pleasant way as it depends on how the SVGs are made. General rule of thumb is bright white does not colorize well. + +## Pictures +Colorful Tasks + +![Colorful tasks](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/ColoredTasks.png?raw=true) + +Metro Full Sized + +![Metro Full Sized](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/Metro%20Full.png?raw=true) + +Ciliora Full Sized + +![Ciliora Full Sized](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/Ciliora%20Full.png?raw=true) +Dashes Full Sized + +![Dashes Full Sized](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/Dashes%20Full.png?raw=true) + +Metro Icon Only + +![Metro Icon Only](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/Metro%20Short.png?raw=true) + +Ciliora Icon Only + +![Ciliora Icon Only](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/Ciliora%20Short.png?raw=true) + +Dashes Icon Only + +![Dashes Icon Only](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/Dashes%20Short.png?raw=true) From aa5c9b2b0a700a0aa9c6ec2af4e6a4f27776fcee Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Thu, 27 Oct 2022 03:38:37 -0600 Subject: [PATCH 006/141] Update README.MD --- README.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.MD b/README.MD index d42445df..ce734d6d 100644 --- a/README.MD +++ b/README.MD @@ -1,4 +1,4 @@ -# Customized KDE Task Manager +# FancyTasks ![Fancy Tasks Icon](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/FancyTasks.png?raw=true) From ddb263f5aa06ccee6ce04df59a04903a403ffa32 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 27 Oct 2022 03:53:08 -0600 Subject: [PATCH 007/141] Create installer --- README.MD | 9 +++++++++ install.sh | 3 +++ 2 files changed, 12 insertions(+) create mode 100755 install.sh diff --git a/README.MD b/README.MD index ce734d6d..467dfe48 100644 --- a/README.MD +++ b/README.MD @@ -2,6 +2,15 @@ ![Fancy Tasks Icon](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/FancyTasks.png?raw=true) +## Installing + +1. Clone this repository with the following command `git clone https://github.com/alexankitty/FancyTasks` +2. CD into the foloder and run the script `install.sh`, you may need to chmod +x or run append your shell in front of the script to run it +3. Right click your panel, click add widges and search for fancy tasks. +4. Right click the new task panel and click Configure Fancy Tasks... - everything you will want to configure to enable the new features will be in there. Default features are based on the KDE's team existing vision. + +## Features + Features improvements tweaks and options to the original task manager plasmoid made by Eike Hein, licensed under GPL V2.0. * Implemented adjustable task width. diff --git a/install.sh b/install.sh new file mode 100755 index 00000000..c38baea5 --- /dev/null +++ b/install.sh @@ -0,0 +1,3 @@ +#!/bin/sh +kpackagetool5 -i . +cp ./FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png \ No newline at end of file From c33a6f48f8ec130dab58328fa4958e6619fe0a2a Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Thu, 27 Oct 2022 04:10:02 -0600 Subject: [PATCH 008/141] Update README.MD --- README.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.MD b/README.MD index 467dfe48..dffdbd08 100644 --- a/README.MD +++ b/README.MD @@ -11,7 +11,7 @@ ## Features -Features improvements tweaks and options to the original task manager plasmoid made by Eike Hein, licensed under GPL V2.0. +Features improvements tweaks and options to the original task manager plasmoid made by Eike Hein, licensed under GPL V2.0: [link](https://github.com/KDE/plasma-desktop/tree/master/applets/taskmanager). * Implemented adjustable task width. From d0767aa0b5675dddfbb3a683a950725b27acb921 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Thu, 27 Oct 2022 04:58:26 -0600 Subject: [PATCH 009/141] Update README.MD --- README.MD | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.MD b/README.MD index dffdbd08..de60c8bb 100644 --- a/README.MD +++ b/README.MD @@ -9,6 +9,8 @@ 3. Right click your panel, click add widges and search for fancy tasks. 4. Right click the new task panel and click Configure Fancy Tasks... - everything you will want to configure to enable the new features will be in there. Default features are based on the KDE's team existing vision. +(This package is also on the AUR and can be installed from there) + ## Features Features improvements tweaks and options to the original task manager plasmoid made by Eike Hein, licensed under GPL V2.0: [link](https://github.com/KDE/plasma-desktop/tree/master/applets/taskmanager). From 95683972fd7bab7353a362de070b0266087f3964 Mon Sep 17 00:00:00 2001 From: Luis Bocanegra Date: Thu, 27 Oct 2022 08:02:47 -0500 Subject: [PATCH 010/141] Fix child tasks indicator count fixes #1 --- contents/ui/Task.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml index 60737868..31b1a48a 100644 --- a/contents/ui/Task.qml +++ b/contents/ui/Task.qml @@ -412,7 +412,7 @@ MouseArea { if(task.state === 'launcher') { return 0; } - return Math.min(task.childCount + 1, maxStates); + return Math.min((task.childCount === 0) ? 1 : task.childCount, maxStates); } readonly property int maxStates: isMetro ? 2 : 4 From f7ba3dd21a80c42ab598dd32a7275f225dcd20b6 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Thu, 27 Oct 2022 09:47:20 -0600 Subject: [PATCH 011/141] Typo fixes in readme --- README.MD | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.MD b/README.MD index de60c8bb..302bc549 100644 --- a/README.MD +++ b/README.MD @@ -6,7 +6,7 @@ 1. Clone this repository with the following command `git clone https://github.com/alexankitty/FancyTasks` 2. CD into the foloder and run the script `install.sh`, you may need to chmod +x or run append your shell in front of the script to run it -3. Right click your panel, click add widges and search for fancy tasks. +3. Right click your panel, click add widgets and search for fancy tasks. 4. Right click the new task panel and click Configure Fancy Tasks... - everything you will want to configure to enable the new features will be in there. Default features are based on the KDE's team existing vision. (This package is also on the AUR and can be installed from there) @@ -34,6 +34,7 @@ Metro Full Sized Ciliora Full Sized ![Ciliora Full Sized](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/Ciliora%20Full.png?raw=true) + Dashes Full Sized ![Dashes Full Sized](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/Dashes%20Full.png?raw=true) From d5272cbf96ceff86e63563fb646e0c5750c538e0 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Thu, 27 Oct 2022 09:56:03 -0600 Subject: [PATCH 012/141] Unused qml, removing --- contents/ui/IndicatorOverlay.qml | 137 ------------------------------- 1 file changed, 137 deletions(-) delete mode 100644 contents/ui/IndicatorOverlay.qml diff --git a/contents/ui/IndicatorOverlay.qml b/contents/ui/IndicatorOverlay.qml deleted file mode 100644 index ef503dbc..00000000 --- a/contents/ui/IndicatorOverlay.qml +++ /dev/null @@ -1,137 +0,0 @@ -import QtQuick 2.15 - -import org.kde.plasma.core 2.0 as PlasmaCore -import org.kde.plasma.components 2.0 as PlasmaComponents // for DialogStatus -import org.kde.plasma.components 3.0 as PlasmaComponents3 -import org.kde.draganddrop 2.0 -import org.kde.kirigami 2.20 as Kirigami - -import QtGraphicalEffects 1.0 - - -import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet - -import "code/layout.js" as LayoutManager -import "code/tools.js" as TaskTools - -Item{ - id: root - readonly property int thickness: isVertical ? width - screenEdgeMargin : height - screenEdgeMargin - readonly property int screenEdgeMargin: 0 - - readonly property bool isHorizontal: plasmoid.formFactor === PlasmaCore.Types.Horizontal - readonly property bool isVertical: plasmoid.formFactor === PlasmaCore.Types.Vertical - - readonly property bool isMetroStyle: plasmoid.configuration.indicatorStyle === 0 - readonly property bool isCilioraStyle: plasmoid.configuration.indicatorStyle === 1 - readonly property bool isDashesStyle: plasmoid.configuration.indicatorStyle === 2 - - Rectangle{ - anchors.fill: parent - color: white - height: 20 - width: 20 - } -} - - /*GridLayout { - id: boxesLayout - anchors.topMargin: plasmoid.location === PlasmaCore.Types.TopEdge ? root.screenEdgeMargin : 0 - anchors.bottomMargin: plasmoid.location === PlasmaCore.Types.BottomEdge ? root.screenEdgeMargin : 0 - anchors.leftMargin: plasmoid.location === PlasmaCore.Types.LeftEdge ? root.screenEdgeMargin : 0 - anchors.rightMargin: plasmoid.location === PlasmaCore.Types.RightEdge ? root.screenEdgeMargin : 0 - - width: isDashesStyle && isHorizontal ? undefined : (isHorizontal ? parent.width : undefined) - height: isDashesStyle && isVertical ? undefined: (isVertical ? parent.height : undefined) - - rows: isHorizontal ? 1 : -1 - columns: isVertical ? 1 : -1 - - rowSpacing: isVertical ? spacing : 0 - columnSpacing: isHorizontal ? spacing : 0 - - readonly property int spacing: PlasmaCore.Units.gridUnit - readonly property int thickness: plasmoid.configuration.indicatorSize - - readonly property int minLength: isCilioraStyle ? thickness : 2*thickness - - - } - - Repeater { - model: { - //console.log(model) - if (task.m.model.IsLauncher) { - return task.m.model.isActive ? 1 : 0 - } - - return Math.min(task.m.model.childCount, maxStates); - } - - readonly property int maxStates: isMetroStyle ? 2 : 4 - - Rectangle { - id: stateRect - - Kirigami.ImageColors { - id: imageColors - source: task.m.model.decoration - } - Layout.fillWidth: isHorizontal && isFirst && !isDashesStyle - Layout.fillHeight: isVertical && isFirst && !isDashesStyle - - Layout.minimumWidth: isHorizontal ? boxesLayout.minLength : boxesLayout.thickness - Layout.maximumWidth: isHorizontal && isFirst ? -1 : (isHorizontal ? boxesLayout.minLength : boxesLayout.thickness) - - Layout.minimumHeight: isHorizontal ? boxesLayout.thickness : boxesLayout.minLength - Layout.maximumHeight: isVertical && isFirst ? -1 : (isVertical ? boxesLayout.minLength : boxesLayout.thickness) - - color: white//!isFirst ? imagesColors.highlight : imageColors.dominant - - readonly property bool isFirst: index === 0 - } - } - - /*states:[ - State { - name: "bottom" - when: plasmoid.configuration.indicatorLocation === 0 - - AnchorChanges { - target: boxesLayout - anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:parent.right; - horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} - } - }, - State { - name: "left" - when: plasmoid.configuration.indicatorLocation === 1 - - AnchorChanges { - target: boxesLayout - anchors{ top:parent.top; bottom:parent.bottom; left:parent.left; right:undefined; - horizontalCenter:undefined; verticalCenter:parent.verticalCenter} - } - }, - State { - name: "right" - when: plasmoid.configuration.indicatorLocation === 2 - - AnchorChanges { - target: boxesLayout - anchors{ top:parent.top; bottom:parent.left; left:undefined; right:parent.right; - horizontalCenter:undefined; verticalCenter:parent.verticalCenter} - } - }, - State { - name: "top" - when: plasmoid.configuration.indicatorLocation === 3 - - AnchorChanges { - target: boxesLayout - anchors{ top:parent.top; bottom:undefined; left:parent.left; right:parent.right; - horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} - } - } - ]*/ -} \ No newline at end of file From 936e5f298de60838ba85a0e6e90b462ea3536093 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Thu, 27 Oct 2022 15:41:57 -0600 Subject: [PATCH 013/141] Corrected a mistake --- README.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.MD b/README.MD index 302bc549..22e26e5d 100644 --- a/README.MD +++ b/README.MD @@ -19,7 +19,7 @@ Features improvements tweaks and options to the original task manager plasmoid m * Implemented switching between taskbar types. -* Indicators based on dash to dock styles from gnome, using [latte-indicator-dashtopanel](https://github.com/psifidotos/latte-indicator-dashtopanel) as the reference implementation. +* Indicators based on dash to panel styles from gnome, using [latte-indicator-dashtopanel](https://github.com/psifidotos/latte-indicator-dashtopanel) as the reference implementation. * Customizable indicator locations and colorizing of plasma. Note: not every plasma theme will color in a pleasant way as it depends on how the SVGs are made. General rule of thumb is bright white does not colorize well. ## Pictures From 7c9fc01bb910541c95fea572d9219411a2e82048 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Fri, 28 Oct 2022 23:04:33 -0600 Subject: [PATCH 014/141] fix #7 - Crash due to no state handling for float --- contents/ui/ConfigAppearance.qml | 7 ++- contents/ui/ConfigIndicators.qml | 5 +++ contents/ui/Task.qml | 77 ++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) diff --git a/contents/ui/ConfigAppearance.qml b/contents/ui/ConfigAppearance.qml index 6fc81996..e30aa115 100644 --- a/contents/ui/ConfigAppearance.qml +++ b/contents/ui/ConfigAppearance.qml @@ -103,9 +103,14 @@ Kirigami.FormLayout { text: i18n("Override") } + Label { + text: i18n("Be sure to use this when using as a floating widget") + font: Kirigami.Theme.smallFont + } + ComboBox { id: plasmaButtonDirection - enabled: overridePlasmaButtonDirection.checked + visible: overridePlasmaButtonDirection.checked //Kirigami.FormData.label: i18n("Indicator Location:") model: [ i18n("North"), diff --git a/contents/ui/ConfigIndicators.qml b/contents/ui/ConfigIndicators.qml index 6efbc81f..483007db 100644 --- a/contents/ui/ConfigIndicators.qml +++ b/contents/ui/ConfigIndicators.qml @@ -59,6 +59,11 @@ Kirigami.FormLayout { text: i18n("Override location") } + Label { + text: i18n("Be sure to use this when using as a floating widget") + font: Kirigami.Theme.smallFont + } + ComboBox { enabled: indicatorsEnabled.currentIndex visible: indicatorOverride.checked diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml index 31b1a48a..15024452 100644 --- a/contents/ui/Task.qml +++ b/contents/ui/Task.qml @@ -427,6 +427,8 @@ MouseArea { readonly property bool isVertical: { if(plasmoid.formFactor === PlasmaCore.Types.Vertical && !plasmoid.configuration.indicatorOverride) return true; + if(plasmoid.formFactor == PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 1 || plasmoid.configuration.indicatorLocation === 2) + return true; if(plasmoid.configuration.indicatorLocation === 1 || plasmoid.configuration.indicatorLocation === 2) return true; else{ @@ -548,6 +550,81 @@ MouseArea { } states:[ + State {//safety case - use bottom when not overriding + name: "floating-fallback" + when: (PlasmaCore.Types.Floating && !plasmoid.configuration.indicatorOverride) + + AnchorChanges { + target: indicator + anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; + horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} + } + PropertyChanges { + target: indicator + width: undefined + height: plasmoid.configuration.indicatorSize + } + } + State { + name: "floating-bottom" + when: (PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) + + AnchorChanges { + target: indicator + anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; + horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} + } + PropertyChanges { + target: indicator + width: undefined + height: plasmoid.configuration.indicatorSize + } + }, + State { + name: "floating-left" + when: (PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) + + AnchorChanges { + target: indicator + anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; + horizontalCenter:undefined; verticalCenter:parent.verticalCenter} + } + PropertyChanges { + target: indicator + height: undefined + width: plasmoid.configuration.indicatorSize + } + }, + State { + name: "floating-right" + when: (PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) + + AnchorChanges { + target: indicator + anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; + horizontalCenter:undefined; verticalCenter:parent.verticalCenter} + } + PropertyChanges { + target: indicator + height: undefined + width: plasmoid.configuration.indicatorSize + } + }, + State { + name: "floating-top" + when: (PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) + + AnchorChanges { + target: indicator + anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; + horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} + } + PropertyChanges { + target: indicator + width: undefined + height: plasmoid.configuration.indicatorSize + } + }, State { name: "bottom" when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 0) From b914780e35b01a1f833fd01146ab9fed45263beb Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sat, 29 Oct 2022 00:20:36 -0600 Subject: [PATCH 015/141] Fix indicator layout to bottom when unspecified --- contents/ui/Task.qml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml index 15024452..cce87786 100644 --- a/contents/ui/Task.qml +++ b/contents/ui/Task.qml @@ -394,8 +394,6 @@ MouseArea { Flow { id: indicator flow: Flow.LeftToRight - anchors.top: parent.top - anchors.horizontalCenter: parent.horizontalCenter spacing: PlasmaCore.Units.smallSpacing Repeater { @@ -550,9 +548,9 @@ MouseArea { } states:[ - State {//safety case - use bottom when not overriding + State {//safety case - use bottom when not override name: "floating-fallback" - when: (PlasmaCore.Types.Floating && !plasmoid.configuration.indicatorOverride) + when: (plasmoid.location === PlasmaCore.Types.Floating && !plasmoid.configuration.indicatorOverride) AnchorChanges { target: indicator @@ -564,10 +562,10 @@ MouseArea { width: undefined height: plasmoid.configuration.indicatorSize } - } + }, State { name: "floating-bottom" - when: (PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) + when: (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) AnchorChanges { target: indicator @@ -582,7 +580,7 @@ MouseArea { }, State { name: "floating-left" - when: (PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) + when: (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) AnchorChanges { target: indicator @@ -597,7 +595,7 @@ MouseArea { }, State { name: "floating-right" - when: (PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) + when: (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) AnchorChanges { target: indicator @@ -612,7 +610,7 @@ MouseArea { }, State { name: "floating-top" - when: (PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) + when: (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) AnchorChanges { target: indicator From e4c58c688d0fc160341b76b3ceef4025b394b08a Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sat, 29 Oct 2022 00:30:36 -0600 Subject: [PATCH 016/141] Update script added, use script path --- install.sh | 3 ++- update.sh | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100755 update.sh diff --git a/install.sh b/install.sh index c38baea5..d8bbc858 100755 --- a/install.sh +++ b/install.sh @@ -1,3 +1,4 @@ #!/bin/sh -kpackagetool5 -i . +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +kpackagetool5 -i $SCRIPT_DIR cp ./FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png \ No newline at end of file diff --git a/update.sh b/update.sh new file mode 100755 index 00000000..5d6dfeb5 --- /dev/null +++ b/update.sh @@ -0,0 +1,6 @@ +#!/bin/sh +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +kpackagetool5 -u $SCRIPT_DIR +kquitapp5 plasmashell +kstart5 plasmashell +cp ./FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png \ No newline at end of file From e5f675f5d437d4817adba9efd3a68f3e7d3cfa4f Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sat, 29 Oct 2022 03:29:48 -0600 Subject: [PATCH 017/141] Desaturate, growth, and animation. Fixes #8 --- contents/config/main.xml | 20 +++++++++--- contents/ui/ConfigIndicators.qml | 55 ++++++++++++++++++++++++++++++++ contents/ui/Task.qml | 28 ++++++++++++---- 3 files changed, 93 insertions(+), 10 deletions(-) diff --git a/contents/config/main.xml b/contents/config/main.xml index cdb6a0b9..9cc41291 100644 --- a/contents/config/main.xml +++ b/contents/config/main.xml @@ -144,14 +144,26 @@ 0 - - - 0 - 0 + + + 4 + + + + false + + + + false + + + + 100 + 4 diff --git a/contents/ui/ConfigIndicators.qml b/contents/ui/ConfigIndicators.qml index 483007db..ce2b3cc3 100644 --- a/contents/ui/ConfigIndicators.qml +++ b/contents/ui/ConfigIndicators.qml @@ -18,6 +18,10 @@ Kirigami.FormLayout { property alias cfg_indicatorReverse: indicatorReverse.checked property alias cfg_indicatorOverride: indicatorOverride.checked property alias cfg_indicatorStyle: indicatorStyle.currentIndex + property alias cfg_indicatorLimit: indicatorLimit.value + property alias cfg_indicatorDesaturate: indicatorDesaturate.checked + property alias cfg_indicatorGrow: indicatorGrow.checked + property alias cfg_indicatorGrowFactor: indicatorGrowFactor.value property alias cfg_indicatorSize: indicatorSize.value property alias cfg_indicatorLength: indicatorLength.value property alias cfg_indicatorRadius: indicatorRadius.value @@ -93,6 +97,57 @@ Kirigami.FormLayout { ] } + SpinBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorLimit + Kirigami.FormData.label: i18n("Indicator Limit:") + from: 1 + to: 10 + } + + CheckBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorDesaturate + Kirigami.FormData.label: i18n("Minimize Options:") + text: i18n("Desaturate") + } + + CheckBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorGrow + text: i18n("Shrink when minimized") + } + + SpinBox { + id: indicatorGrowFactor + enabled: indicatorsEnabled.currentIndex + visible: indicatorGrow.checked + from: 100 + to: 10 * 100 + stepSize: 25 + Kirigami.FormData.label: i18n("Growth/Shrink factor:") + + property int decimals: 2 + property real realValue: value / 100 + + validator: DoubleValidator { + bottom: Math.min(indicatorGrowFactor.from, indicatorGrowFactor.to) + top: Math.max(indicatorGrowFactor.from, indicatorGrowFactor.to) + } + + textFromValue: function(value, locale) { + return Number(value / 100).toLocaleString(locale, 'f', indicatorGrowFactor.decimals) + } + + valueFromText: function(text, locale) { + return Number.fromLocaleString(locale, text) * 100 + } + } + + Item { + Kirigami.FormData.isSection: true + } + SpinBox { enabled: indicatorsEnabled.currentIndex id: indicatorSize diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml index cce87786..6aacead6 100644 --- a/contents/ui/Task.qml +++ b/contents/ui/Task.qml @@ -412,16 +412,20 @@ MouseArea { } return Math.min((task.childCount === 0) ? 1 : task.childCount, maxStates); } - readonly property int maxStates: isMetro ? 2 : 4 + readonly property int maxStates: plasmoid.configuration.indicatorLimit Rectangle{ id: stateRect + Behavior on height { PropertyAnimation {} } + Behavior on width { PropertyAnimation {} } + Behavior on color { PropertyAnimation {} } + Behavior on radius { PropertyAnimation {} } readonly property color decoColor: frame.dominantColor - readonly property int maxStates: isMetro ? 2 : 4 + readonly property int maxStates: plasmoid.configuration.indicatorLimit readonly property bool isFirst: index === 0 readonly property int adjust: plasmoid.configuration.indicatorShrink readonly property int indicatorLength: plasmoid.configuration.indicatorLength - readonly property int spacing: PlasmaCore.Units.smallSpacing /2 + readonly property int spacing: PlasmaCore.Units.smallSpacing readonly property bool isVertical: { if(plasmoid.formFactor === PlasmaCore.Types.Vertical && !plasmoid.configuration.indicatorOverride) return true; @@ -441,6 +445,7 @@ MouseArea { var parentSize = !isVertical ? frame.width : frame.height; var indicatorComputedSize; var adjustment = isFirst ? adjust : 0 + var parentSpacingAdjust = task.childCount >= 1 && maxStates >= 2 ? spacing * 3 : 0 //Spacing fix for multiple items if(plasmoid.configuration.indicatorDominantColor){ colorEval = decoColor } @@ -451,15 +456,22 @@ MouseArea { colorEval = plasmoid.configuration.indicatorCustomColor } if(isFirst){//compute the size + var growFactor = plasmoid.configuration.indicatorGrowFactor / 100 + if(plasmoid.configuration.indicatorGrow && task.state === "minimized") { + var mainSize = indicatorLength * growFactor; + } + else{ + var mainSize = (parentSize + parentSpacingAdjust); + } switch(plasmoid.configuration.indicatorStyle){ case 0: - indicatorComputedSize = parentSize - (Math.min(task.childCount, maxStates) * ((spacing + indicatorLength) / 2) + adjust) + indicatorComputedSize = mainSize - (Math.min(task.childCount, maxStates === 1 ? 0 : maxStates) * (spacing + indicatorLength)) - adjust break case 1: - indicatorComputedSize = parentSize - (Math.min(task.childCount, maxStates) * ((spacing + indicatorLength)) + adjust) + indicatorComputedSize = mainSize - (Math.min(task.childCount, maxStates === 1 ? 0 : maxStates) * (spacing + indicatorLength)) - adjust break case 2: - indicatorComputedSize = indicatorLength + indicatorComputedSize = plasmoid.configuration.indicatorGrow && task.state !== "minimized" ? indicatorLength * growFactor : indicatorLength break default: break @@ -476,6 +488,10 @@ MouseArea { width = plasmoid.configuration.indicatorSize height = indicatorComputedSize } + if(plasmoid.configuration.indicatorDesaturate && task.state === "minimized") { + var colorHSL = hexToHSL(colorEval) + colorCalc = Qt.hsla(colorHSL.h, 0.2, 0.6, 1) + } if(!isFirst && plasmoid.configuration.indicatorStyle === 0) {//Metro specific handling colorCalc = Qt.darker(colorEval, 1.2) } From b2cb43af111433856ab0588b4a0281abdac37a4f Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Sat, 29 Oct 2022 03:37:22 -0600 Subject: [PATCH 018/141] Update readme with new features Todo: Get new screenies --- README.MD | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/README.MD b/README.MD index 22e26e5d..dbb57ed2 100644 --- a/README.MD +++ b/README.MD @@ -9,18 +9,26 @@ 3. Right click your panel, click add widgets and search for fancy tasks. 4. Right click the new task panel and click Configure Fancy Tasks... - everything you will want to configure to enable the new features will be in there. Default features are based on the KDE's team existing vision. +(Alternatively you should be able to double click the shell script to run it) + (This package is also on the AUR and can be installed from there) +## Updating + +1. Run the update.sh script, it will automatically stop and restart plasma to make sure the new changes get loaded in. + ## Features Features improvements tweaks and options to the original task manager plasmoid made by Eike Hein, licensed under GPL V2.0: [link](https://github.com/KDE/plasma-desktop/tree/master/applets/taskmanager). * Implemented adjustable task width. - * Implemented switching between taskbar types. - * Indicators based on dash to panel styles from gnome, using [latte-indicator-dashtopanel](https://github.com/psifidotos/latte-indicator-dashtopanel) as the reference implementation. * Customizable indicator locations and colorizing of plasma. Note: not every plasma theme will color in a pleasant way as it depends on how the SVGs are made. General rule of thumb is bright white does not colorize well. +* Animations (Thanks ziomek64!) +* Growing/Shrinking and desaturation of indicators on minimize (Thanks ziomek64!) +* Customization of number of indicators displayed - limit 10. + ## Pictures Colorful Tasks From c401cd3630aeda0547fa52ff1f7e2fca77a463ed Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sat, 29 Oct 2022 04:01:54 -0600 Subject: [PATCH 019/141] Bugfix: color and size --- contents/ui/Task.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml index 6aacead6..985bd03a 100644 --- a/contents/ui/Task.qml +++ b/contents/ui/Task.qml @@ -445,7 +445,7 @@ MouseArea { var parentSize = !isVertical ? frame.width : frame.height; var indicatorComputedSize; var adjustment = isFirst ? adjust : 0 - var parentSpacingAdjust = task.childCount >= 1 && maxStates >= 2 ? spacing * 3 : 0 //Spacing fix for multiple items + var parentSpacingAdjust = task.childCount >= 1 && maxStates >= 2 ? (spacing * 2.5) : 0 //Spacing fix for multiple items if(plasmoid.configuration.indicatorDominantColor){ colorEval = decoColor } @@ -492,7 +492,7 @@ MouseArea { var colorHSL = hexToHSL(colorEval) colorCalc = Qt.hsla(colorHSL.h, 0.2, 0.6, 1) } - if(!isFirst && plasmoid.configuration.indicatorStyle === 0) {//Metro specific handling + else if(!isFirst && plasmoid.configuration.indicatorStyle === 0 && task.state !== "minimized") {//Metro specific handling colorCalc = Qt.darker(colorEval, 1.2) } else { From 4fbf99d7436311ddff71cc43b66f09222e76a8c3 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sat, 29 Oct 2022 04:38:14 -0600 Subject: [PATCH 020/141] update pictures --- docs/Ciliora Full.png | Bin 1931 -> 0 bytes docs/Ciliora Short.png | Bin 3581 -> 0 bytes docs/ColoredTasks.png | Bin 8754 -> 0 bytes docs/Dashes Full.png | Bin 1688 -> 0 bytes docs/Dashes Short.png | Bin 4087 -> 0 bytes docs/Metro Full.png | Bin 2304 -> 0 bytes docs/Metro Short.png | Bin 3622 -> 0 bytes docs/ciliora.png | Bin 0 -> 59237 bytes docs/dashes.png | Bin 0 -> 59854 bytes docs/desaturate crop.png | Bin 0 -> 27995 bytes docs/dots.png | Bin 0 -> 58809 bytes docs/metro.png | Bin 0 -> 58884 bytes docs/shrink crop.png | Bin 0 -> 28036 bytes 13 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/Ciliora Full.png delete mode 100644 docs/Ciliora Short.png delete mode 100644 docs/ColoredTasks.png delete mode 100644 docs/Dashes Full.png delete mode 100644 docs/Dashes Short.png delete mode 100644 docs/Metro Full.png delete mode 100644 docs/Metro Short.png create mode 100644 docs/ciliora.png create mode 100644 docs/dashes.png create mode 100644 docs/desaturate crop.png create mode 100644 docs/dots.png create mode 100644 docs/metro.png create mode 100644 docs/shrink crop.png diff --git a/docs/Ciliora Full.png b/docs/Ciliora Full.png deleted file mode 100644 index 867e0918d68d614ea9bd73f454562ff78cd6e84d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1931 zcmV;62Xy#}P)iECki4zU-whYmYQdU|(S~`kifil`s zDQ#~{UvBU7`|gj^m+RrS*82iXpU*!%=XcIM=Qj7-=XuU^&#A)tDi}rrSnh&h#EHq4 zktilxMxvN(8Hr+pbk__c9&Es5%SZ^*ZW)PUvSlQS4QhAIFyg^RsLx$9jCfFAFJ9oT zg*kh+0YF~fH1`I>_^5c8`7I++Oty?fG1)Q_#bnD!6q79@QB1asM6un4F)OT75$E)i zbJJ@xI)gA%vY%f4BFLQ_|8~pMr;AdjyQ{{hiP+xzA72}NyET%YKzDvx`r@>C?hRqy zXgb=5kh^MpQcy%OhCXp5qIK=QN_RDkg3<+m$6Yr*F@&tW&>mB^o~-yoT2}hdDkBZQ zTskhaZusgC5uef6_^l16Xo(?~q%3biphQc>jJzExt z{4yg})N;Hzwrp8GySKL&fKtk-T)E&{PR&a9Ci{S%p~^68%C|Q@|NZHTfCK|g?;Uyb z)xT^z+!F7;ldV;+Z>~SrWrCG3BBW+a+0t5j!g|#}UE{fb)V#a*2t^SfpoN+sDWnKV z32FIkYF;hh3q>Ap1in_C8hm zz&8sHZao>Yb8r6cqu;yz^Aqi!3)MR}|NfQgjFIVy-Ok@V_sX#VvhOW<@r%2cmh2A}Ec@*WZm*eo&z*(YNtaLU z-Mn#2#RsFmHDe4YLd_`WAUt9V%WB^*ukF6nNm`;vf}#MB zBo&>XnwnZ`J+^!F?K7tNz7ROO`BO{l|{m*RH%fd$^wk09ZM< z-Qs&~{jwzwuHF{BYxP54PE!Ej$-DV;XG$M?_&dvg`F85U6~*pJ7rWr@+k$^x_t4S@ z)@<*;W5uFEbBPfLB7#s1^YTf`o2+aFr2q&-LBS$HMG++e0wRh~LJ<*aaTY{KS1?A> z)!BuVaVhqsn~J8L*tM;;LnG9B_|;wKX3oE9qU#u;x_!G&b_s%w`*s`%-Z*!L4FJ+n zvFGjcL87;z@_1`jPPXe8X0UqCj#FKNU}M$cb7?s_z7KCVq7hTO1pq>?W&4x|fGA6e zqJU5o=g}cLU8R#I(V{6@M6?KX=p*{X0m`55M`uST{pl0>+Sw1kEJ|{ zid0a_=>g%aQi*8oB+F^Bw08Q$u|?XRdTY_t#+sT-(%v3OnmBQs^RX*`R)*Eq-tLO0 z@@M#+9juJ3jNU+JKLEfP3yxw86DP*UBqG@<9t%h=T=dw=;{1<2swXKFz@kS{!J-fl z3kotgxRSwcP;;PPq-Z_rz=bBP38Z3|AucYp5^zz&YZKT zc653_HWzhLGBkMd2rW5F%fJBLn=b`~SSSe(&jLnY@F%%0O#=Ea$avjQWb zP?JI>q_Qk%IHPvaPOwDlfj&^^tb~MGD5JI%zFXJ)dB>00-`(19;?V0)ZrXh!K!E3W zKJ$F)qd$1=PoMDxTWWS~eBtjc?t^q6JJxgW(=Y!l+uL6I#&5P9>`KI!4#t=e7@zEm z@>vWoJ&)i^niMD@wTKpIIxUqGED_Nm5us=&X4E1f5gno~&-=i2z}TqVg}*ADv3<#} z%Lm3z##J#=JerzYG7D!%|EE3BXhF0fELhN_6D&<3DbAS7i62EMlBg#l%_#hOq5Jz< zsw-m1mXM&6DreeV2u;zV#pwr~Kxs{CinAs{ttCO(GOibynVE?C-avs=UVN7n5eOhc zg2I6dLc$rj502kS!O%ug9suLrM~n%ZU;F8O?xJzcq>LMfsI#RNkL0$wtC1-{0an!K zGX77EX`;z6qF}ORB#Qlb`g~XEqVB2+Hk|0Y;Ho=j`KHYC=1=kr-x6qCLoE_G7_2`Y z{O?d@amw5o-rTTV0N`YQ^WS=g|Ji%I_6b*LXV3Ob&h?}XRU))oS)SC{-YM?tpd#ON z6Rhh;wl!g%H$S{`WgxCB#%rH&bM2|&!9v7r0kBo%I)D(z^fj|_)r|6CT}@X8Bf{Hi z4h5=$4esio%KkGg5^z_IYot-P9}L!qS5EdvxTn@tjMqNl-qGhT%H{CN{{VyjP)8J` Ri~;}v002ovPDHLkV1jYX!EXQn diff --git a/docs/Ciliora Short.png b/docs/Ciliora Short.png deleted file mode 100644 index 3973389293ca33bed23d182070c2a8efb1584abc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3581 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 diff --git a/docs/Dashes Full.png b/docs/Dashes Full.png deleted file mode 100644 index d5d8697ccc41780816b84e0e51e69d51f4bdb9c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1688 zcmV;J250$+P)hcF*_v z;}j@ETXwsp26~=9-T7vAW;gThIp0int1xXdEUT>?Z^5!+;ezzmEGud*U;|{eogIO! zxYz($adAQItyxyoTttp|YnBx?b^Ea4-WsrH&t3poS-rd~EbGL0*!w_MTx@`>xYz($ zaj^li;$j12#l;55ii_(loJw}FYWC)Jm&}x+)ao$oZOP81-9{ka5j`-ex3_AY?P4B* zT2dFPy*N2#RPxo{6-|7zf7=m6yjAN=)@}h3t&3J~@>ZKrP`VG`^VY31T3Z72`i75^ z(^8HtvbmPXBY2=<#?4QneLAFbZhPf}q1&FGw(L;z2X^~US~#}i)hUa1H9efl9RBKz z?C&SdS{rKqX;xdbB|uJsTVG!fKq+M^CqM8!PD)GhcS!*1j#Z9xE_z`0+(&vV0um1G z|8wj2Uw*b^%fa@Z>R7S)>jkA{H8wr%sx1N1TKk$jF;u*-?7PB0R&Avy0tB>B6C{Nc zAt@0p7bImB@y|%}Jy1A*)}uLV!fsMV_D%Oc^?c67xi8FI)4~ALRt@Fb*Oq&WR-9rB zkk4_(JwC2<{tpy_1OZTl`-{sI6`%wV3JFD!fHcNP5kjF7?;cOUNKJX+irne`H*&|^ z)o1;pl8Bpm-9r-}zV)*1Zry=`cCIZbU01Mc-EX_{3rp7){gq!-d#IXpM3DqV0U${#n!lQw zT5BEM*RSQkrp>$4F7KD7oL=`#eddbN_a==VJ$~}X!CRky=8p8^(;@)C$++eEgs-NJ z8~y0yCE=lyAG`2}MMx#XJxpJ!iiqHPtof+O4a5 z;k5&M?Z{hF6x4`RZ22;;tlyw(yLfOTfJ;u_^JVYT>y~ahLu159VY7c zZu+evEhF9YJ{c}pxol^RAiQt$ma^oGjD!={ThWR+KoI&JH$nLTh;o!D3J66pzwe-# z*-T_ai>7E1(IV85Q%qrvR3IgQ>R>ekDd!%ktgJQT7DE-45(osmuekQ`VY7i$9SSBU zC%FK?P}R|EEoyO^_VcD#8>|YOhav){oG7zxd3aC9DUk%}gU?YuMMWwoWhN|`MJf@k zO?=GQqqUjB7}e3-o;M8axv#MBkW^KL61#WrX3nh&q@_BQRaKr0sz7SMY~ZA(rPhb4 z8vp>NKWjx4_a3Y$II(rnfa!__aOhK1a3}=Cfr1=uc;x7;rP(-*QM7LLCJ+I@NleKa zaNp#YM|S;T(aJp{`}2SP>(V<%T@moXJ+J@0!+QSy(?-)HALm{=Xn4PKeJbI?!Nae2 ze%)Bo+EJ`_=laq7g>_3P)TB@esT>Cyrd<|o(j!_oPFX^;5D{vjwECG(xM9kt%bsIH zZN=Ul8^3;i{)!zT0{naV%(+PupP2K>`3d2Jg?Y2*eS6TmliKau>qbof@TGKrRna$Z zFI->47_Tg?xWx9QdOv+n;TlZ}l#p6P3pCA`W6~ocIwB$zZL&ly5)si6>in#KJUfh! z${hJ-Zr`P&-^y?7XRHpW1gqbVfC^g$+L6rsrJ`T?44fB#Rh z2S`ZJM917{7D7|BXfe~4NsZQ|rkEuWYAvTJK-T{$wg3ra)4zX^A_4(KNKn{#xkZ?k z`Do)z3XZK5IR!eMv zthjWR`DIks0e$_Mo?=Nu`4@G^|3zd+ZgbY?EF;j#XY}M^M{aZ0=qv%UPLs|Oppu4W izKrN8cH}l^jsF0fz~q3x%s9~i0000^B?{v>)XJ=P?(TbIX5I2LcFu{co5F;)| zRD`L7s>BZQj~J)o3Q0MsN~qwJLpf!aEB=vk{-lyha2yB94kj48C@vPn*y0XCvMzvb z2z1+JC9PK4+w5HXd~bf7p4r*fu6A~2Bm*^1t#(g;XXbSG>Gyp7p3^NkFp_U;kBx45 z_mj^~p+$?2ERy`juc4aPXhn+_A1(ZRV56}XEk1(yAfvGsEk1&@q}<|Tf)BO~MvIRF zK7v9t)}qBn5V?KBozd8796me%;KBXE+WxTGdOg}?R`Zh za+Y>9D>a_`S;C$Bw=VcxwBnrb&4HgsL#I(K7r(09VouJbd|T8=B<-1*o4-kBP01}< z)X0ZO$}L*d&gp5dCFK?$6Fw|bZn=vVwKJ<$7BKB2`JtWt^!4>E?LSXRRe~gyBwdk8 zfJzO6E()cR7#kbQX0y@eTGYl*ueq3p5JE^p7*GfS3?ZZ|7`k9sRmJLq!Bu-t&ImQY z0;D`IpT2HQx}(F%ha^JH5K5PJtCZxbF`1d%w`*^-p(yi@A5}d*Jgin#ttzcrwMuHZ zt+c9Yt&(c3Ri&y`Rn=6g&G%!`<`&2mdu7&#rpf-UUEPyKoW+MwB~|n<7Xd^da6b|j z$`QDTL^?95rf^_DWR@eZk?j}s(uvh0j8pS;nVy~=bYF~F{N-b#D+lX&J~!9l`h|Ru zNH#~%14BcZ%v303mjc5)=%h<()iz0GdwVL{N?qh~xnv@tYMnsUIt4quT2;=XV{4Tp zu&A?9DbIyhus5VHelfE@TG2ezkKO$@_s4uQFqM66WJG*{5Ah@{_!22QM|neA&-Ht! zdiRZgbMSlFQYPAH?Wl-=geVBOG86zI5S5uhH^8{^Xz8mznTQwW&rl1(Z|}LkIQd=U zdC{7MlgUg?i+84ID}9~*X=L7xQF7PuG1{nJA*hs{Nfk)<@yz=FdM7m;INLF@duYDq=OfI@EGJzN zf{Mp){p=T>+xUU%9m`fcaOKs1{N}IT&y6Pn{`JpJ^dB>B?{#qIqxAvwuY6#1=*zy} zsLiNSZKz<7=PzG=WMH6@hAZ`9dY<=M)dtB>$1`&AOa)U(_`aXd=WEn)?R;zV!ySve zDx0;O*ZA?1-?`~tH0Gpf^_^p5;!o=pduP|KFjOsf(tSAE(85ur7296)mS;OqbuUmQ z%I3!N{jWXrom6kx_@tD^ei$6a+eC5u;RhhVLTRh;8Xka}AMiijZD`*4a0-%D>T409F zFursw((L5@FTH4PzInsa^Z(_xJ6`?eVp;S%y z2*uhZy?t%|(?dsTVkX_`k52?Yc!^*CV!X3$>1Qt8|LEqplsqXB#?s>%tW}xX^%3@d zXZKCnQ?*K&b0p?an+&fNNs!rG?#ZW~xqba@#bR;)d+(9eiJ5HDU7n;>yQh8h)#7{E z%#=HScL1y$*n8acx2KjZTl%9%eq1ON;_-ynjLEKN%spSZ=fH!ToNEH%2KCXs1402r z5w2kiK>`{ITHM;UG}HrBr6mAC=rNpO@dLYPJU8^>?#uu1GsgFhJofyemAyWTdBAxL zx*x4YPIDqE6js}eFRi+0RaeJT?;ny>V)fDNUmZ_e|G@8)Jowa>gO5Iwr1ecw;S+Gj z5NR+%?K(z9%JKN}1wAL=Y-+B$v6Jp{k)Y;s*=L`7Zrx4mN~PeyfdgS(Q?oKawX~|8 z9gD2hd^StC19E?1p+F7 z8%dzzYcK6g*etTSFKqwd+Cy^rH-67c#*RGs(xD$b8HcBc1*8!W;?z8|xfv|9W9pyk z@iaA0>sZ5o)0%FCj4z78wXYg$jg5NeWd(6$Dg;fICdOxu~it>s^%!aalPOu`o7zEWQ6A?z(Xx zW7J=P({aZQf?$IpSG@?3#?bfeJ>9znaC{i^GE;r-=}U_ zd-$1G1wLVn2w)Ua9#qXFlyb2!Ff(2goT=tewGk1Mu~=;F4cBeov3=;s00}=93)QU3 zrb*eYQiQ7)sZ{E^wQE;@@`@k+=zqq>#!uIArPvfHLm4wZ$P%rJ5rq;Ip@x3L`3@&u zwQ8y5#T6SgW-ye51%+N=GBvQxKRHN-3)IB;wzlh0my)n$cu4ovPJ>|6Kg?2%y` zXeeR|fU*MXr)pg}v>BZfqhH;z_nP)#*|+~dVipQgg*3S42!|EEcD6dmsJZ#{f)=w_F?^86F)Si?mZ8Btd%ctU#4YK%Bb~IDbs2 z2I2Cy%g5F_gTcmL=u*`sZQkVjTjR&~Ky3gFkBt1;efJehB@sy`67an1v}fHz8!dec zAMh$3Bh}ZTgAENNsGIPGHly#v`~8Evp74uu`EOmcVrf@AcKD$ueQM0aNoTi=({W`i zMcQkGP{8@jE9v%`H8tbpSdnH$#3Vi6yXM+8Z|{8j=+Flw;I1yT6sTuBfiz3X&R)FF zley9qNeOVpj@=hsb@`iHwwyRI0>N}PE*Gb!vQ5hhB$WyndO{1Mssc5TaCBSeE1ZTI znhdJ7jV&qz0C-3D=ud~<4#M6iNmVt*K%``?Si7lsZF-!$OLflXk7*#7`&@3qf*6NrEP9!s#$q8%qDdMxeAxZT$2Jv?t?tu3!Jb z(W7r}-|qT8kw_Ga#UKcbF#;5d#UPjaS+D8r==_5deF>E%Yc6SD)*J6gYJ&%$0zqnO zWZA%LesRhIB&}-6+F!o@^6Q=5cPHB}EI8ppAc`;<6KGla z?%o82%f|={O~#)bd%Z3GUPIH^GG%K)r|HULKR*^DX#)#D3_t*7H{$M34MWme>wZHd z+16Ib=ja4`CLK3J%Rrctp;loPmUM!)q)W$^N>Wv=RizEpP1S~_Y)ggVw>C$kvoTpN z9L4tPIM6e5a{*jAwmFeMj*gD<)g*x+2#g2-XL1Hh#sBQ^zB08W!I*_n_!gehD11Vu zMr(S;TnqlxsefwLOP-}-!Sj7G%+BGdkyQ0Ok0e#0aB10nC@9tcpsN~}l^rCFF^Obb zu}}bT1|7RUjboJrorslmGe7Iz3Q?DXY28fE*=D-9wc4nZdwYAMAppSb8#eU!_g6NL z9Xs}a8#h+fH-~TE`^9(n?YsDrOFZ`ikFzT>Jp~ek3C$SOgG5pdA%H0P#*VF5ulm$0 zU;qAebB*CQOUD4RQ<-9+NCIVtf$}eaZcVj(TL}|)JQ1&Mp>Bep6a?YS$3;XW7LS*T zMGz3U^*Dz1hT*zP)#vL*p<71YCDn~nRT5N&OBHl8Qs*dWNh&IpDjtA(r`rI4w$zLl zzK!v2yyaE^Jv}|*PxtNOCH)(I_bvdhys$|d9zPWbEb8idVbiAD)~~Phqr30AE_MYc zf^n~uHGX&C6R^rBe(`kw;`6FoYmgdsT+{XL>*W-~*zE(=0S&q)Jb?1HniV*Zx|0A=h694n`t<~`+s`;Me znjVt^a7wce=eI_y&oX`8-C_&?s-76F(SS8X6CMyaoGz;i^~IZu({Xj7SvdVw7n%~E zD`D4x({Xj-T;gk+zRHcMM%hS;lS$)W+5R%hJ16z zOuw~nUoC*Lvav^<4+#M?q01*iMA4xV2C-4)2q$k|*u=~u^obexY?GBy@ z`NE)1xGs7G4jbH!y+O0o+bm_r?Z|q$3 z(4sq9AA5N5p48h(Z02K6mB0JYGi%}lzbxc*q0t?U?cyA<3WEOjZDUJ~5SC;CiAAeN zR5Ye5oE3F?dwb!_3k=u@v~!B{Bbia4r$0G@bu5((_70wuA zr_|s0uKK!nDnDMig(?IH7^NXdDyd3RJ)>vmlvQ!JH}D+Jt$60n`Kw(gXH@yL@7({$ z{Ba9@{`BhO3}B~9qH)`r#$XsSh>(OqY5^^ZL>62zWqosNEIYH%aVBi2lkAd`OG^tU zjqcuAeRAP!%bIiVoSK*3qZ0JHr79bC)d>X<1(Zrc2olhwc0wqXqQM@If?ii+WVZ zNyed1RxW&Y(fZF${HKMa0aa-TK#;7e{v68jOkPJ%{RcbG`|jnIW7qz3WnNj4L-*tx zzqVSn>#ILmv%O~R_C0HN?5U`%SyT0CMOF8~PSR2#390}fNecbnhK9x%gS3V$ZQ8hL zZ}FGUFBWU;x92@Lx#q=(X3xHB?q55udgQ_DN{*Ci0Dv{>%FCj!KRRdjopYDC*Ur8B zid+EzyX?|)_b&L!z2Cd*H}B`nx@X3izCa$^X=JIeYGYF_E zJkXGaFn|F)0w}9*$?)9V=poCo0c4Mj^|f^Za&qASWJn}a9DxV`g$e`~2?|w36$Dg; z5T&Xrjrt8$GGNQ`=<4i3R(6&%`jV+*tCuaQ>M-zHH@~*5?)sP#gz$JQXH|}UH9#s-}Z*;e>So%qq!mZ!5xh{9qsOZt>Lr#U{ z24x`;6Xdqj5o*6Qxs#(4Ffth0-VH22|@5z7IYpi!|zp#(*!$qMUN zT3<0WYN$q4jVg_Il9HN4^78Z0+0n_o{E>ZaZQcI3$arg;=H=yC=soJ{?n8(C3$*=U zN5-Ta$G^D!@LH5ct zuCczWxBE*MOzhiH)46;9S<}ASUE6FtO-neEAZ^%2ph_hm@aJjp=WT?lXMElKvCSC2 zq%y5B)G57uYH9t3%7dC{k7tw@W((p3B(J!@YO8J!I4gMtd4gsFRzYz=Z@e=B0Lf|V z2}olvC**%bRZFt$&QCW*o2sG41Dab}?wdQ;O(aAlGb01GeTf!MdwIE`W8kEvgTD$; zz@jY_SX2UPL7;~xY+$LY4l3r!-1E z;g}M={NY!Y{)~z4*4pX~Z#@3e^6EGN9(eod=W`yo@43I76?K~{mp%K!znX)cbZ^_% zbJLSA|FR^~UiH@R7p?2!={+$CIduq($c)}Fefoihh7DV{k|ddtk>R?o=XsW83DD=d zUQf@GB5P#s$dmsQO@#LS_?jUVqNGtZ3PXQP^KDaAwrL{p>VL)*RxlvpD#j*Lr9ju5)9*b50 diff --git a/docs/Metro Short.png b/docs/Metro Short.png deleted file mode 100644 index 0a7dbcf79468348647e5ccf053a5a7ea62dc67bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3622 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 diff --git a/docs/ciliora.png b/docs/ciliora.png new file mode 100644 index 0000000000000000000000000000000000000000..89650699a80dde07f6e4f81fe04b8b9bba197037 GIT binary patch literal 59237 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%0APMVO%r^rktatYvWr6_)%Oj($0mby;8UO}m9 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 VSR0pIj_?2g002ovPDHLkV1jK)V*>yH literal 0 HcmV?d00001 diff --git a/docs/dashes.png b/docs/dashes.png new file mode 100644 index 0000000000000000000000000000000000000000..cff914be15b8c592758107bad767137c85890438 GIT binary patch literal 59854 zcmeFYV|1lWw>G+B+qP}nw$rh>V%v7o9owCbZ6_Vu=r|plos;KzvEMz;H^v!zjPw25 zOQY_pIj@@Ys;apP_Z_9ID1`uv3kv`M5M-pqRRI8S%+ItDH00-R1?IIm004vQt*-5= zYV1J_bau3`wlgPo^#Ym`n|oSY005qAC0})t$#@XOKladFz){HoH{AM@hmbCBUWutZ zUsmtc1d>bABayK@A_mCvZu0`Rj|};XrM)Y?8ywO-7YsV!1sm`DW0!3e@9$s!nEY_O ze$UuT@bgaz6$^X3`LiZSb+ddujnoZ=?>pB6zp!*P_;xS;Bky`WAxID{O*`qzH~{iA zFDSZGX@459*Y(}3>)Eh{dHU5a;Jmo&BiHkrq13(0b;9MMh$G!CdXk#6OlLajB}D2| zN?9y-UsdW^lonLu$nVJg~zzUj|Hp`rHkpSzInXGF37^%@5*GS49O zemx%#Pbv40)t&htKPQ^}1jl}iWRM5^IEH$;_PBI-Y_fD`sRU{AiRK}Ts-bI_)J`1+=PeV z447ISNoK4c`jBML{=$n`y@u0y2|G=_`H|g8}rt1=?E9Ej64DIhZn$PO56YSSL*8LJv zkW_i^kL&iza{PxSY+CqR47%Lko7XR&EY8J#Z|4T|>i(&vWGek7`e6}QbYUpAUyFt? zMJ%72X}l2v3eM1{W7DPya~RyP5LT&doP?Wwjvw1+B%pJ5$aF#I#fCfaZrCYc5U{K8 zhsH%o`7vVRJ*Q>6uDJ-|JC^AsExfW?!Arb;r}Wpe4UU(EL4IBbBAcx|dCSJ?m_xT) z1A!JeQUfXV;IIH1K3nU_@P-4*Q{WE#s7cM_>|HL~Z#I|o{;jMD*(0cn+*NhG7T|Sr zjXPW;v(dV37}r#=+kIzMy8qJRx29Yw#oRsvD%;J~-*)k?FDoNwir;mn(hqvGv@dAp zWsPUY9hR-Rf|$N|334cF%KD`xcV)+6#DY$*Q|>!RQ8%hi8Cd(&R+whvajmKuOBb1K}zx=9Ag`+uR}jiI15cqMmo(R6akJx0 zu8+LS1;qPXC0pGz?*pWbVM&=l1xMYNS7!etpYPUF-+mB+`*vcoDIB?{N)bFqekWO< z3TvYBEtet|VK%u9GQ%)5eF;~w_qWjl?4e_NIz(q;sJiYKOG1I5f)&_iHK*s`2jeEh_VwoRXp+T7``ur_Ih zb1YH#;i%Fx;-?S}M;y zDy`L_sI|^xmnqz(ZFf1GW9KCk{1LO;Y*omp8YP-3OW$i3`aH$jv|FHxBC>1HA`C#}L)`0=o&a+Or|c^VIa z<>+6V--U1c?-JqHe=u8rV>yfUXC0#1TZqckN@_dH9x`jyt)}Jo6lfe~#QLF&@ZAY+ z28EfkgV)kx%^MLx* zUCyrw>%Aeq|MEqWEKVh1o>XAWz`ICbLwxWC+R-B83nPzLtjd%lvl0$Z*}O?|nRHno zWx#x$5(Ih)u&4Xb%NP@RRcOIeHN~&Q=7uA?eo-a;1A);o;d30_%3PhZzQ)QVuSe5V zb#{Jy-`(3%H!o5E!nzf;NjlDfSvuEG41^6=Yv>$-U!+u8(6rpz=>v#MZaSNDo5?tXVw zT<|Ru^VBEv6Zi9`uU_%y-NIIz>Ao6zp}4`;JI3UZN#07PV77>YL`1 zh>(?zE2@E%Yx{DsDk>0Tx+Ut~ zJex#xM#lLv$D=;;PBgXAdgll-v`C0PoDZ{YRUG=E-C{v7tz>B|q#N=#%D8rK9N6Dm zAQt)s-=Tkv@RkYTcns!H>Uh@S(;Fu;Tov1YwKKyNE2W8KTM-X&)enl?l5w^SLkR&V zDZKPL4nycE_1n=LueuCE%SRtFx~bylJn%l3SgR)JUD;pTK-%3exfnr#vj(S-DW-|c zhMOi|QD}#}i#19G4nul4?iY9TA9#lXR1;IcwC%khyO=ttbA9L_u{O^3{eE>M9r_w2wnouIiC&yK^0C5qdZ>M z2LM1qt;NKYWyHk(HB0)O8)f??2}lnpqlYP}Nzh`a?1_6_N1L1~E~zkxWpI;*-Sp*j{5t!xI> z230iXX$(g_tDU!gRi{-|uTljVbC>;~cgeAVhM_lsK^3PiFAQb18?;)MsY@)pZA}Q6 zxtH5l9n}CO8v&)AA@1PzS;ROC1g>enJ{HJPP%i(iH$ zoN1BP34(|iGz)6}PoS}>t+^|)iMge70AoP#LZnyovnec){YLue_j28A55OcKqeMOW+r=krvKD%ag}iY1o@{y|3?iM_0P#ald8Fk zqnop-xrDp9gDcs8LYSHUTOa7=Z1=Z2W~NN$cINh|_?XQx*-T6;LKGpw?``@Jh<@?{lpHd16yyA|gZhx64BQ8Mt zSN*(Zj;7XTyniQ|IZRBt#gDUXFQ$A3U5 zIa`1BN@KhKwCXP?vri}HjB9nGvQy#BwW{~A2R{QqcjX=|6y`n~?n`p1Y;Gk5yO z)juxntp6TL#KeCO3SMK=f4Jac>~3!Mx1FC@|0puGGIp>u|BN30?5_XHxBfqL1r8n) z787G0W(F2B_Rsd?VCH5pVdvyzFyY`b<1sd7=QcI}2YLTScX70E^)Ple7qR^0@sq31 z?)f)Y#MFN`6wQCP#ly<{uU7aZjDdxj;lBvu`6ppa|8$t?ubA;KkNKJYU!3s&E$|;f z=2Pz4|Msr` zrR#sh!2d}2e|y*eZ*;-_*K*3-;d2(`@wr&SR)8Y-Txda>$VrIPZTmrW14+Xlb& zT>I2=hp#%NSA@qi_SufsrFkU%2A--7%RK9@mhW-kv)vvznH$`?T@_9Mmjjj~kx))E zl;!7Q>WyJ*lB-9q0pdds5gz>Tpta{`_L>2SM@Qd46kE*lQhESvM**e>eD&`qbsB5X z;y0c!zV_SQU;yC5s-^K0)?yEeM?{Bt|C-d)>uUGAF<`8fBf<1!TqCdO=IJ5Mv}Q9D zspQ@3eF@8G)qwqUe)Q!fE8$Ix_fAGD5OGuIrK&hD=Oo;WPp3V2^r`w72lcLrq-L_K z)s73v&rh=^EsC1$=!L;zss}4i=e4>!>10&@;{Yp+qX@XDQ*??={sWdQLD6XvwmNR? z7g&ZhQzf0Sx>sul?`pRiW}a#W(tiEdF$pJmXW{N`52a^&;582s-OMm7o~c@<;7X@$ z@{v+~*?i%pjDxIg<*!;D8T+g=uA6BaACYCDKPMdGmtpZVx|o}e_g^a2=sRc@VOZ$4 zG5BN`#fF}%-yrn}hUXCAOH8S)TBcRWq_`5->uI`NIFCRWg{ImfzKn!p3-XJ@!8Mfg zNXl4Km@+p1(ftEht*n`mv8P8YH^sQ{haQo>^e%3W$0n(_nfyeZgks+#Ubo$RPR zA#HLf3l8GK*~Vs^V)5}zF?!$W&#%C)jTwn5Qx-G)8ZnqH90efv9R!r-nY8ARdWOK# zIR}dR6>g!3!I!p>pY3eJ(WEN(k*)~MXN;Km{AJUep)u=;5F%AtT1j|PYVBWlT+=|$ zdNEM_pWbNQkHd8z1lqC^Y+_KtJWNa{v58q=kt^Og1Z~@Cp%{2FJer_fjpk?M&XQfy zIRt(_#4eK^g^%P`rilF*0(tD;%@@rd{0SB#5N-?@9x~>`{c0gS^J5@H3Y8gk5sThW zA!vvLGT_x^XHqp#tR@}=6)OCiva+#OL2*)wbKES{8o4c^3b$=$A-gZgIm#%MaROPJ zU`i~7p$+yTOY256KENXp7oAs=N(xQp%FB?lx3_T*d`DTe@pc&^YJU}j4+Crb^uQLS6oSw4*!_V+wb__h12rrIxv0CtRFUe zOphDpk2xmw+?haK-1rYx=H%5)V(C-}k`ct4cV!VaG|+Ao#7+cTiqKEdRRh7qgX~oZ z^z&yC6;Rl(0^vbhdn-NbVIuo=otF9_%+uDiqmC&1!f*#7#1NHTQMJ0bwE*}wwlFs8 z7QuZGgql?<`O=B+jT~X*Hj-b`Vr(|cAz;CA#|u%jE2F3p1f09X-oHEVkN60xR5%pl z%Ffa_#(OG2#uv?mEe6ufTnYWWzs$jH?@3|ON@)<_si)HoimTND+c9kh2oav|=v#p0 zN>WO8>i_CI?Igh+E3biP1VR8wn4eXh$5*dA9r8t>(A2?lAbOP$kir16p`h@)FKPQc z+V2Qxjg1d&eUNTqG|InxmKNz1$TIsQ$zx^|XL=zx_P-z)bMcS)G1Ht$GIIh9r{yo#0JDK4;=103sOLKlY4 ztbysHq1&Gnn<>Rekfa;Y{Y@=mqne$WzMz5ey%zTj4|YL!p?c$5ny}P;dd@i>Mt5o6 zj%WgaiatHmm0CW?o^=F)cgtR1hO1+$O7&cgtzrO#!+A9Z^Dlj>gzS32leB?^dmN3|0G*nqLZJ^_pjV|853HL;Bp&=G$Qr8# zlm~Nd-;~a^){|@JKq8MIQOezTleDBJT;-=~Es8r~hpi_W-FEy#fY1n?QN>GSln)Au zC`^(dGTH}`vllXStFs5jLPpRUx?BXWzrzYBA#GKr@GhVU>|1I;plb|NM`CL2tx*}i z;As$Vl}5#(qL%V6Ajd&R?@`6A>qTf`=n#F~(a|Z-k5$he8rD!p7MAgW?((mY5|@O| z*0W9;P$G-CwIG!$;7t^>Mu}L60?llJsZ9&uG3-NN@5xt@qbIO_U()y6y5xv$TqfIwU zBd|svKH3)o!`}I2@K%|*GoVvEM0>e@Pap4Kj1xTHT~U>4PTF2NW+rWBO{k-=YFx;6(4OOYoVQBh60Dcz{K0v&hYn-~6?lSziI+1!u5P z`8vX?GLMz!uKo6Qk_zm^eEhC8wZZ)&M!^%FvW$h2*widC`|;{>bSV`mV)B+y7+@+^ z+}cJxo{}wc+_oi^)x%a0xM7;w*4#ydbOqoa2d^bKR{QRpb%s;P~NZ#A%{f=c0>i9(q)h6=z{y2rc(ttZ~@Gb z1gi#{mT2Vp!Rvix%{&{6^Dww!x7u#ZD{aF0EkXEjB@D>Uo{7`a;udX{BB`=zHi392 zNTLhDnly3X&Q3oK%7lRhxft3JK4GA*I-ppdk?vHfziFIBKz<@JwiaTZrBJ0Mr0-;=J%E<1AW9{O;|>&(4qF{sZ;Zq0@*!mX0MC&u?Z#$H! zxKM#`6XjT4$nGursC)$9&7`18CO(cZYOJr4438PfmY>_O1`M+CFF^xm=jFMjl?$A zUYQ|lubkob@LA_I@f!RPVi?Wxk8+Li1sLSo<;V*J$gf#>l0Ii9^6~~j6>b?pg%$hd zo|tSAjze!7=f?~iLD$zsRxP?~#h!1iH@^6PR0&c-e?kotS;Y`8F|j1PJr>9VO(Egj>!iu|c00!K#%a!^eqrWh{an>0p4b;f~kI zdOxqqY?gBGkRL)hIn`XV8 zVpb`a#x_<=Y1?dm-5*9UO~ECM>pF&TDrKQKwyTztTrv+l1wpxS8mx#D_R7R4drg^s z<_@hKg%+137v)5Zio4dP79J0Rll5@&{$0FEs}qwr@XfS@ZIoj~Gs;tA$|-?t$zBDv z)rwj`JS7`oPKi&qr#au_P{%H*neUMJP?juW;gY;*kn9~Y_gHQHcn!J^TSNV$z7#7#;~n9p(-!sZB(g;d|2wEQsa$u)uMruSUok;C<%}> zM1WFymb17Jsu9%|CI~s(P;2~?4k!ytuAQ)<8`AW<2g`OjfC*rPJZc=EY82*( zqCa6o0;@)bO4RaLT=_)rZ(u8XSRfp3?+(a8XQ12(td}t#5JX=$KkEP)OSrNGg5qi( zIrG68?}#&4(d$lh)lKHxA$K)Hmv9J@K9ClRwDajyu*QE0umf$hGcy^@OK^*HIJajw{Z}{_78bO-^apdVMRFx)Ktxv5+Ra?mh!$Ap(w3Xhg~^S2FtYdrDGnXA~#es9c*Jihtif+-^4 zV+E>On9_Q%u0syr3145e0a)<@4=>?1RT;dMp{3+4S6Sgv27y+ji*W|PAhtaC+}uE;?P=4g&)c}Gs=m>h*-~w@apf{75IIZ;hC=?+dz+UCR<(U{R+60@Ud`Azp zc()J2PxT%Q9zFcTdDWxdEsggjDwh2VobP>vk%YQVTWT`m=za3oXNU(tkenc#b}dWV z(Z$crb1~PvM?nzBHx-Wo^<--%Nz^BSa-vWix4HvJfD_eElXRJg>%t!u_Pk=)10X&%EvpO^^0| z^y~K+_OyfUV|+ij3R3)Hw|7&=z@f_(iU0)n8%_<~FNxH?;mMg<*-EerfH%c!bg5nd zKe%6Tq~Cc#A{u-V)3-f7_L}DXh8wd_S=;+Cle{9<^5h(i!{Lzx%N|Q1l{U%#Geg8+ zl7!f!Q4~VCZ((X6s8+ZnTL~+vVp3YQKuCs&taP49!^@}uHuTyey)DX2aH)_~f~Txz z_C^(FEZIXx$IB2l!Ys>aheJ~Kmv)$AV7ip~>KQcZGN`p#{9%Jt8u>zx`pp?S<46#h z!k!C4@&~~GmNs+ggKZxlQ~aR)XM1>qjMz*4AJ}X#w>v~GP+D-o#(KUde~iL$ zn+-S(jM9EMuq@vtYr|AP%Ic##N1W~U&hWg_0MynaA0Tkq@X>aqC!psRRj=7@m~Z=9 zQ$OGxVWq(*A*g*c3C`RqHZ(_FHi~&RD|vbPtrvd=k9@?k7M`t?3j5OYoPXnKGi z5a>b_fI=7%Ct8KGPfyB%zl-M6b9gcwPKL$0!?{PYLuwyrLY@Q#t6C9u>xB6*V$Em* zx#QA4y~Ag`Q^G|!O!0_>jM}eLks{4eyPyuurWTKuKM2oP3}j(>m!-{7OvlmJhEM_5 zmy7rGTCZ?cI+35IA7#{fTOIGzdnVQ1yo+3mz#hTaP*9#DzG+JkC)5`?@3;bFy^8KXagw-jqI^MtvO z3XOhb$qzTiq6!{DTTOo`l$5ENv?@*;C2NxhbkHM-(^T%EdmkXr+R_l4mUltTeI7)^ zKgH|b)t5hL$ba*sU`tP8MaAvwWn|AsOEuPCkuF35IHQ-!$>G=JU;vkaG+zl=>rr zU=mm}#WbXEA&NAwC%8ggp4ipCsjyOeFUH+^#DPup8(h1(YH(iJK(33h z+j;5H)O|jzHa-8gCTiv*H*bJU>zy9)ebdqCcaS4wmc)QF9sIm*Ov7#Kk&7V)l@lsR zmu>81Qc*AL=)1Asw;TPI``8G&0ZfhcaFE$|X6c5_v z@fzmDEL-+vtK|55ut>PFjiY4Fxxa;P;CVLt>XSO#=IZzM)eRQ{nX8E*MNAAE>^rN# z<4f6~QYh3Xoid~e&N}sZG%{pKD(i=+ar-ayYhXf(%b{rY21)RW6NzL$S6auVEWiR_ z)OV`@5)M)@NOg)z5O^MEjl_v@KnUv}@+pX~?%f(b)!$4=;HSaT0!I77CiOV=><2M!8&2g9P9Ki!{lS;NI1^2M z<4?Wxob_^f+DTYX!ph)x0MS09xGW)@AtJvN$*y*015SMddmEpg+Pg#O<^U7`zeWwB!16=VZhwk89G#&rm8YMefB}c$y`@}5uQ=967#Yb(XD8h zaNj9Im^lRwvy9)(PBOl>(ko>r@T_V!)W0iWYg{A7Ic7r=iV9rij~n>rvGI>G(lT8Q zGVtWFbrlpDo*k3aeY8n7msCk6fNHEio(p{l`#8(A(a-1yaCHI~Bq3qLOZJP6ywTSAvi|;a5Y@HHQ3c&_ZY{30YEY(h04A zWmLkI+5VUshdnMKQ2r<8GysIRv~2~N!LWZ#u?YT`PH4R8R^NS>n}tj|;C@{U^J+H} zkS4#+d?M3jWj2h$_r5<*!qL0P*t|}tqLG6#n0rnEK_Z#b?se1gO+feDohD!Xl`GAb zVUl5oi}95wAYiP?^0dbUR06h;NrJf;ZRY@wb7wmDo&N3ZNHFHdB%usq6ikn6p9BEp z@?$ASR~;0C%K{FV?qD1(8S=18HK5igT2K-SaFiqVz>V2pu#q3^#^2@BjYx4{|_ z3}~(IW*wuTIBY$8^cw9h$Lrd$b##u@`G$>)$Sy<2r(c3AAsjI~4o}kJRt#W3e2w0v z8fHUc=VlSB+CxO5ow=!`HCzbBAkJP37`(ViA)U@Om8e7ZPlvge%PhNN3j>+cub{Is z>k^?ft4OSsb)LqAA21nj!0g&lPj-_gAfbZCF^5#>_!(jZftPI;FVKo}g+6#@$Jr%WDyXJKIWtt;ZO2v1B?_j3q+28*77*oL_6lbb z=+|l*xNv3Ymn8#tD-rWN^QFNpBmkvWRv_cdvU5M*3eoDkaeG>k68tK~V7AjA5dpxG zM!Bn`L7ATgEZh4q%h+lg5##QNZMz9goy3B{F~~on8WrFv?Ys@q0WChFR)9zN7c1R? z7Zp%-&-Hq>?!Ohq)to@+_p{+bwYoe}3_G)~nzdLAKC%cVrquj%}n1>Z+aOBYa8C7fNwBtOQ`0(YhemaI$_RWGyk!_aDEhiMp( z!7?)HIIHe%5#Nm(qU+j=-yKVO1i(w!1d&mQf??wy$T7@MW?+Jlg%#o(Df5tMgJT;3 z6=X)0C2|V6pmrQ~cgt{V0_tm+=n`SW0^w!7!8J785MkqI#ta7J1R|P$CrP$_*GEA( zs@xGJIb58(?C%THvfBtd!G@_tW~uGvwj3Zd;s+h(du01G{Pq=qTkXsxf2K3i-IeyO$g~RljJXD96gn zjmg>@^tEp9nBL&IL{FHlVeFb=P87~C;3B0DfA1mS4b^`it^v@JVJZK)%vNj^S=Luq zqab3Vpb4S8vZ=9eB2P*4J_{5Vpxtv#9oVR*x9f|c>^pN>u);$GwQx&|%1mJr+f)a^ zCQi+)CTvo^&ux1_;w+6X2iIrr;H!QSwr{o45ea)KTGow{(|VX_LQy3}W3QL&rG3;Y zdoz>X2m~h{U6%&n_OGQ$B#Htq!q4Ya8-m0GgVa|s^?uNM_bI(u8L-&B+=w%I0>XW( zsVPV}0!4Op0zqlb03ifTMjPEf#qI#`&zDEONVU>btBH;`ON#0rqtV&HM}V4SblsX& zFRK!|z?~ozUwlBJWg4HAwD!=?+rk7S*k3x*ej@Lr>T>oOJc{4W&eqZb;d~y>W*;nf z`qLS*4ph^`-rM~q*oQo~o|3@TkDCHZ?gW&2Md9i10J%eMOfOp5%?B!jn~bfSAS!SS z;#O**?p0x8kGT=kn^#rb^?QxQs^SSj6p$}t_VOMeci7Wi^${mgp5;!m1$#o9GnXUU zpASe){r+;BjF{`L!v}={FnX^*$-R2Q2Ex(RA?Lyf9idI-1obGabfDmo9;y4NykczWfl(gcM%wNKq~@mJ#%Ai^5>yU1fLE;{PK|~ zwd6>aHf2;cMy3Qh0@}8wE}c&4$r_b)6?Uty+Fmw@gL3SFeE&Kd zjiZ8J#K)3g+4ata^7#67wFSo3=QYJJy57TP2LW5n6pa7x6|8>m z#r#*b$4W|R;7(1>$}^G2E}vm172a$cko>EXYCKCkjywx8nn}D`7ae8@H#1$}2uG-+-s-&!^GdLNN+q zFb!K-^VP{T2}1Q8hT5Lis0HY4eCb`DJ@m@Zip&j{nS2EJn0o?MvS0lgvwb5C%A6KF z>Icgp809zd;i)k`HRfS5J^9MaWN5{xkltUt56Z(5*E3`h@$yA^9Ak*eXJ84Q!oQ>A zZr66B7oo&%TQsW^G?qgp2XY0thRErT&-0GoT&&Js#aE)}$c849_St2WENJF5%#|_D zBG1!=LWlEnQ14-lxiZtZ!2Z^NYh;g3gc0kJag^1JQ%&7SMIp4Q(zZriEW{p!?g~7H zSl?tZ@#^GutnwcdKeUzLl@!eBJGNdS_;8z3w6?tM)aD z2>=N%Ugs9~umO@CaP%>JSb^69*%-F*tdXo=2w1B1P z0#;ik2zWR$L0|-e$|nj#NLK65Z(1)D!;FlBA4^BIdaql&B`}ojf<5}8bzmK(h^YdD zjx2zS%a1$be^!koz)c2^Zvmz#MRA0>#~{+Zq1Y(gmckXD9bP$)m8lJjk_l{30qAKw z@f5%U8g<7-5%} zf9{X0bkQAXE33v=YD7bWVKGKyr7S=Juw#NIV}x4}Ty=$8(tHK&S(8G)25}GXSH!eF zjRi!#Zoil`?qM%b0r`8iK5nR-*3d5c@2p>gWB>^z%l0au^sYEo65N((>nN~d$>u(Z zkg*E-w1liYF#LPg-wQBa*m9Tp^F9=i8eIAvV30QT_lUXv6a7UN5Hy#W|IGbv#j~?WmnG}1g-?dkOQGK z$M78z6G{N6ADUHmI1wRbn>bSCHve)(|-MjYL1)QIDGe)PD9Gu?)I^fBmhbhPpD`DgY$;e(HI zMhpuEOF970A1t397gLUFNeBXUzIte>g)fkp zD%P;f0p_F-mY7aqVe`s>Kr8TBxJ-FQw1+`Lsi4X~w2PP!I7UX3?V9UDIy9uUdcG%4 z-kUX)5G7Hn;rCKNs|C=xMPp%7OLF8og;B$BEA>t{QW$k&$MH}}O6n%w2oMDCA&m4O z$eQgAeUqr;eA?d{#w*$BaG28dxhk`fh*t&Q_Lu9aA@L+x=s3y&V#C+QVDOxmpfYAf zB}O6YQJ}niMQay!sGON35oZ2(wpa+-CCrHhEHNPvU3y6eeIgH5U6mTLq` z9kY?dYj^~uwQ!!dPbfgW&&h3!OW}N7aJ4~^N5*^-yQ2cf7;F6z+|RpEKQ5=Y5}qBP zZgV&>*BI!Vq1oWno?fVWh_p{Z-U*TKgLps>6M>vSqGL9~0LbiT8|K7)*?G!!9X@y? zn{$j`yBUTXqAf)q{e5CA4sWhVkA9{`1OXo{kgeDA0{Gm;d|z`AcPlbR0YeL!KQp0F zWfh|fq4CPvJx>F=;Woke&LIn+S3Dtsr?lSGF&RxRgiiA9$owQV zBzRU1(U{0_PPk#QDT>iVE=P7@sT;Po5dozggs}n;-&Qxg@kYWLjbC&bK1|fIK-ywE-4U>4%EFafDoozGLE0H=12d{pK=|lfr=9=@cIV)Wf<%S-9L3< zpm;PtaF>H&uuiACTkQC7Y=ZD-VGCU>J`{)FiIWf$2QP*%u?bsUYD6(r|#rrz@%ibtxAtKJF+?!~)??r1F)^ZGg!~m^4JxA0* zOu|Q_RHo-Mn4MitV6GL5f?7JP#tOZE9@o6}H~mpfvB=qrzac_i^Z*t`v z{G!$y#9}m$3cLVlqwVd?vRxUrbfa(kK6xDvl@$=U&Fo_G668y;=sNwX0%d95_F=63 zS_&b~!p!$goW7AP5Hsj`%q*-^L{A}iG|dswKP-lE=8`NPr{}suZl#M$1atfTkTKU& z5ft0^wGU+LIhTSN?BjYHtn)IQg(2)$;Vqf(E+t-UzLkvxyfbM(jT&0(Tj}F&^Us>0 z{?gm?kfmy{c2leKH_WMyM<(E5CTC%}p2Bolbc4+|@(3z)L4e6Hwp%ZXY2Eg`LjpG( zBlXgxDSBXE;EjGHx;ioQ2rP&aD`tIwQ?@?vb5#(|f~b=bm=-DpNlgg^XQ24yc(EOn zu>A_~ynseV$^B@GxY}@JgC;|$_SVlT#@<^mMMR42#gK+gTw;7Cy*0Z*Ayg5a8qIMRi^gVv6 zbNZ0iOEj~!q8?f%OKJp3UCI%xu82A!1j?j=Qu^7q?2NYyIoeK{UUXgIj> z@xznE1d0YfWrpPZRLzch7?N$NML_f1TqefchbVYdHjZ{pIp(|(F^=|?0=mbB7gz4} z9bMCBfj|ZJX_p#(g-20ev?0WeEVtKIGi4zi;auv~I2dm+ zr;x$kpG#US!jKJjsnCD9AqdsK3iopgmwl2@Fz^mDqaa`K(#{X+M4C*TZ}eTSdh(7l zXNYBgFQ9DQS^d6Vr3xFO=&ZH>h&e)$FRDw)`~k=0q>E!rtfN?l`dwMoMjDF`HuLb^ zpQ%j*vh8qhCZq-)pN)rPWnV`b-yyCSCConA&v-9)%oEx{++zU@dxAC1J4#llSNKqW z_XQqJnp!YL(pLtvUIAALly7YYjMFm^vL4=Rxrr9%P|Uq#GDsLBLZqPK9T1|%`4gV1 zEVr&_od#uyMJ3A5@mcfIce&&GAj_fe?2NwKcb=j3PxxbM^H|LnpR0OX!>o*N8x597 z2LATRe~1_HTUwIbi8O*6(u|=%YfUR7wsx(%CiYc3Jc;6f^UJy6U=6XWeef2)a3-$c zlLH#Q_TgK2BHmtuVnWGje?CWVT?;;OABY2xBHOW|13@db2!en_bPHUSZX}7&*)|6= zoqwUt#h708%={x)RxMX4ZuWB0e;fVUdDTgc)VSgc`MKK^YikdjndA2F$PE)ogFjz= zrr2;0&{7Qgvr_$_^KVTp64TQahY3ETTlrI^TZu*0J93^js9Fe#UQp@ zQ56w07B3tRrE$K`6N68h4hC~bJ4_gt^O zI;~ES==&a^GkRW^^x{fRusrzRu&une+nFx?M59lov}cW27kY9SFgLz^V8b_pxYRAEkeKWC2|r8$=MKpXk z41#J-gYqC`&xGNq;kHWgV{@7`t&merr+urNZ!wv4;kT$vNT3d@nyfKPGasczhnr-6 zuk5(G4R1fK%861^U?O9mYCCv`tWKqM$EiohTS+ct{u`PNNEQvcU1}w}8dY{XN9{fn z(lzF5mEu}>QWQ!uDalrhlwk&HNCd!JodkolBWly<;aA#^wwij`sopS;uG{aPuY8WZ zHL2yZQk2C7{nlRy4P`?UepAXtXzZRr{gezUu%J`no`< zPYc2rd98}J9gSz8Am2gSc^=_)JS~B- zdp8yZ1_Nmiz8|2><~U-d6;qHAlM0( z$RLsIKv*89A`sfacac$C36}>VIuaKf*-%w?=Yj4V&tGEO{X8*J%=e8kwFk@oD1h4C z4yF+SM_;0L6*zkvV`1Su8ijyJ=e-~rT2kJ|Khz*t!M5!%6hf7f`W)sdM25)0T2Sc{ zOu+AkxJe$eAbu<2(yg+LLmG~?M0nS^m=$zKRQ_2r|OZbFBS`;Nwg@qO^IoFjYXK!olqVUrS!bb-e}4QB+14} z^j-fC0DM4$zmk;DcUB@j^)wQ9>FPR=kGDjodX&L3nU7Ug3RjZ7O%D*Df*jJk6_!bG z>v8tiiC$3J-AF+Qi(r7G+#~{0AY3UEY5I@$(3GZPv0U<#WMI@E*}z7M3WluQQ`a0I zcgltV3YqsvCAU^YC%982hSq(qKFp(0WHQJ0u2{_ON;tqIW614sxs5=MDw-7INfqBBd{U(ZSw^?1%MpL0PfQ8ww ziNJ#NI%Qpi7d~GOUODgF7S21jS`~@8+1oMR8Oefy^R<7jkJ~PIDdP5cA#o9ac7%y< zegSI+2l43T*NEpHe%v$hrPH2-OTY2~tRE9#%0Q*Uqj)gorGg3>LffGh;t1%)eJ7}p zm!wQ9JY?l12XS105eBFba||8~z&xnffkQe0CdWdS5)m^Z^s)7!J8{ZmJFtB)zzrKa zc-PiVxsft{<|Y8Z631wxg-(>n_yCbIIYwHhICF)*awRN#8PThYfN7vmRkq>d9eCg& zPhKS}*yXV)^-3m+`?>BN2IM-85?s)5x_Y{WR`swolW_u9quJ-}JB&;+IA9FGK`-@f za>eLDxQ(?jt@d6kkqVvjF$D-mJFKX|=t5lV9L(33kdiX52> ztVcv}&L^RyGUg>Wb+DzjWC!w1sCUasM1o%4QCZAXjs*k|L<1h|$`^V_J~`l%2CH$h zoJPj!3N8U6z>xd1jxv?f-3vZ~$@UCrb`Cf?gZStXEX^Ip(%c~|&K<_${1GfJ9Kp5?cjMAcw*mXRz++ud zdmc14n^%U2_l*N{5pH=XlzJ^}c(VW|sM`jMcZgRya7e$_u01h6e^Va|i|!VkUts+A zm-^WIs9qW3z(M(({^FgZw88~l%DDZB*C1|sF?;q<-1Ai=OnryPIXor$qGH7RELZcr%~+Kpe-2xlS#XA-Ix-DiFlL_}mekd*6Ry-Tv*#eZ?^r7UyvN zt)Iuf2X|nwu!x<1{r^CS0A}<#MhrqkEwr*^h!j*{BMFH;26MAcZIzY_Xg~@aM<-aS z1UK1Tyo`#B;D(#Ug=kuyTd%URc!~ralcSd*v46N3(OnxIMyP05mKa}wVLv?d zxLQf(nDFpX_rj2z?x1B5xhh0tkp`}a18;i;E(9GsZmVS%WGzKB%AWws!97G`X zGmPi8+AD0P^ruGXDH+4)TA3P)A_uJ)7G%K0|Cx<&Q_VtR&_&S9o!l=dogW~dNd z>4>xi3vuzR*tJH=1Q!*;tk0z>5GCmn);^^=1k3vX`8+X=f{io^G?2znQ z(MY8WBmJT5sVdt@Bvghm!AoUZd(=~;OCLHz=Nwfa3c?jCYP7;#Cf>K!a?|EHyy)wv zVRG#Z5D(I5g+ZDQ5d(3Avv29)ZO{56yzi?o#l9mOfTbmX2z@5BdJ&=?aLK9n;hGEo zFYxFX(2amo7l8pMd zU;fGffAN2M*8L6QIZRB{Qv>RS%7GqDDr>iV&xvcrCQh z0?@}GjciEy6V#lz>>a0I0!ZUih?x=dAORHyY1BeIXsioEnvJ+1ZOl?4*6)7+XY9TM zhzAJ(0_5PrfddEd@^`!iTgTVoA~mah%)&!6h!p`G$z z+`s#y81F1Es6a%xFnScNd;bG=7Bgj4$wm`E`YQl+h}z_sYR!R!h1R2=*#c=-J8jDr%Kubj-c?{+bV^#R) z7*c8;KdHPzgf2!-u7x~*nW_sAg&o8w&+{ikkl3_Jr1E(hw?N?#CX0c|7}2;VAaGEq z^Ks}pj5O|u{4%eAZ$JJl*+z>eH~G8|X6EGZ1f*4h5#&`Yo`QE>>A^mt`} zLD%ojj2&O8N{^4KCHNRXng-L58-SA2D3sQvDtfy-KE9kcgN5pQ!90b)cB zg?Z!SkKjpnu19OEhv{`Qh~hyKwJ;!{9VGxmE5_tQ5w2=|6IV@r1Bl`j72x7;%)mSV zZUJKvFh;;wgh78Cy?txZo@nE5_beuhrh$_{B~;P_JVfyq5XY}U6xoCa-`URigAeyG zJ=Mb?U{U(Rf8GPQhxrBfF>%}n244g^BMpQRU#(UP=Z_u5mb?BC6WtER)=Vaom~mXx zYGLd60Nww7C+`04H)AlqR&3zj)EP)RZXU@U_lH_ zJ;QpchV`o?lWgZpe_Y%z8>@vxMwvrE0~pHt!UQ%*1Vy|qBkN@u)$aw_BrAA>LPiN_ zj$qNYW;sONiL_E0*e^5e0Hmv_ma_P9=q&nPfFZS*$OIf5oD4o$5xy7g?22H}$BG3u zI3gSLaoMb~QtqddrG8bgfh=AK);J@|N@agXfyEsT#h1S-@>wTz+&r>vR6_*hrVjWZi7iXxmb)xl+7z5$)1 zdmKax{&JHI0V2e43~-Du@niVobw~4DNI{OgEnAjfr0(4|GdznpUzPddC2XFhTY z27?G|*DZj!k0=^|1_PkQNt8mw>09}nM=qqF7m{}$UCcasI@)7nxO+0j-?w^bw?&{e zcv`cKMt2&7*@BbZyD@j(;-q&AxU9~b5J2G8<}H>v0+`NkqNN}RN$Dwah#st z6wDd++Vt>$Vsd6@Izb`-tC3G4Nrh-f5h#ihKmkCU&dAJ+eT#>2{rC)ip}!Sp^u~~d za}Gt^=v@wK)}|$=@k&+5u#am%VR$G$^xURgBx+mjY38~Z~;a{JS$EFTYq&RL=-;uS@0_Oz(wSOlR!cMSP80!Vlkf`kI@l!$zybEqaCA4A!E(Cfr_@1^_jhC5Ef znfupaey)S{r_H0&>4TyHC?0?)21Rk22GLT01qD<{g=}{3G!_n>idMIa2iL~eW6h#qc4*oXU<9~>5chg9w;iaX$IC|)}F+R5ZDG(uT>9zw1YbVEW z#oZsqZRh?p<~Cnaw4p0vCXO-w@4w?QP^o-%q2?$^Fak;l3<)Brkd>HZFd_!}3PKtS zph6tSDJfzMMiR*or=SAIaZw?op<yGk^H2FLxno4x@-|ry)nqlXKR!#<8{^6_cO= zFsNw||9;(v8bujKmnl&pl=}ok8#pxEVYqsX)un)Zpiwn1!DS?JNTczvAcHUT)T4cU zTwEj4{Y`)h-jwK6^h!(1RL8CU}GEIUXbDTEYjIP(9ZeNaP+OC7i-+I3qHqL_ziq!-XlhN)?ur+a&>LP#q|PT#_UQ$ap$VQ4-R~ z8|}|X?JqLGkAfQmA~2GN_WL3nhpmICr2UeF5tM=rp#X!L>S1sl068%!k^Wu85F|_> z?FY8>b||PI&r1ZGyF+_=9+gfIa*eEvLY0riAXKI5AcH$q0y4}Ph>0iok*(7tP1FuD zPy-TDKJ>>Q0|5qk*x-s5+$$q@y_S3O-ZW?oc-(~ zuYh$xq4m{|QH3jG8CzxIYV;63ksucm+0K8&I$d42^<&`kSm7GuUj zG{8b9#>Rd}S#_aYfxqiR?*;(8?KN*gqYA60Wlar?mE#{-@Hx#P+gFQLsyEJtFIJL*4#g>c}L5nosM}ViyV&=^;0@&cm4J=WXDp)K+q5_WOc?j)s zGxrE4xk6cWoN_>c1btutusN@VI_i~b7MV>!CUGHYX+(Nt4{30mfQ8hTgHp~FdrVpp z;v61j#2$bl*AXxPA=0@STp&Y64yZv0V)O##wp}^c;G2s=BN!S~5F|VAHproZ4MjT= zR1Oj$l0oB;D?kP&fp177O{rousQd{gs36w>A%vzvke4nQ0MP68@V*cH5#INKKWf%C zcPKU0k#;G(5HlwS7cPAiKlI=_Ja5k=dPh3gH?st4_s|{hqum)`Vmt;YPJ*Y2v9Qoa zZ?TQu!USm0K`ZW{#cllkSx4}XXCJ{>E2#p}NN!~b;NZ)@%|1;`wQz9vt1*4*n=!Sn znY4(xBe&w{p?9weP+^#MCL&CZPvG)B|B5>o58<&V{9xhF#sjp!^rtxOJDM@R2nQETL&}a@$jTD39vwzf&90NL+<79_NedN6$6tD~ENVd?V`3_>C#Ig+ zAvdfS3b0GQ8emH&?ENWvY9;RF-}P6qM-3Rcw@4b)MI88ec}qQA%}m8p_A z=D%gy9^`^CY$wwPx)GHDK|+feWUV^6WH`{^?g#cTNwNj3Km!zXkU<*@+1OzRxE283 zxsM-Fh@8{rw*dglO&0)%98@5olmi)&40*bmGV7}mD`llAD+JZK!EgmsAR8@gQ%I_f zvpvaS^)zFqODPd9bH2Ppr3X(!aC9&{OLV~DZCTE8gyIgT_4v-8Hs+E_aJZX7xI z6l^-{Eug3#AP~pBgs8E5&x)r%RI!7l8tdx0V`F2u?9ffP?~c8gyXeQ!`RpHH4~sk8zJNMJu}R>eFND&6tb_3ZPF~@=g5V%lAmw{sM(*Ot$$WRPFHqOf~$!>t5rn2*8reyNeE(_&$ zW^XzpPN>wOMnJm-JhX8U@7?eSPMPcAsgF(Ivi%b{|L}xC+CrFX z0Xx?8@bwKx@%0UJI5gEmr(KX%cy-zk4wui+Hi;aiK=h~;VX}1(9@+jsLG7z>+L^CF zD++TQ2k|WS@A??PU&Q1@8%-4zSqWRf)fMed7Z>qP4DR?{L=+*Ko(NoTroc#r`meh; z%z8>u`p0$wZ$*_1w!_QZKX?4npO4Jv9IdlUjg8N$mpUN;1zzzBG!8G+<5Up7i!}j< z9Lqxu=_&vNmtqc820B%-8%<%;@Bgp2Q80paTMNOILf(intPGjJhB*Pd}(<>To zwPVWQ@RB&1Ny?-X;fYnPxyDRXqD$0cy!N&UI2ijR+n<9Y#>$8bNx47LqY_F11#=vy z&aBcexx-|Y(^H+P!dWGUBV0QBh&qWXk9!hre3L81aPmn88H7VB=)HO%gT^zW>3%IK zK<5WAK?Tx?E{yFga{!Q?3qV6=Ogf1gl?Jsjj%++jB#u&>nkgyzF)AMenP5T*z!1XX zqQsrRml6R$A#V(_$;cxdzTB2-kQf_P?4~2!$$93)$xu0j(A=v!;j7P4)2E zZAUPOW#!N!fFhtB5jrr+-@u4e7?JfKS~|>}ppvqXU&g`RU%>nl0coB3^3jaiQT3B4j$eF%Ic%V>q z$l@1B2QO&E1Jwa86nWBS!h_7b$O;fa!V)%njBRQ_W@y=DyJFZ3%eEw!93&E=X=6mC zfwZ%kLwUtuI{sx*$}0a|&asfKt9GV(x;?4EL+N(Q*#)+_88yCL=<1!Apw8k`D@=6a?KWDp8*u%|!=R|FX>pjO~y zAQODhzUnS*u}KFST-&WOsmwubTU}#NATgvXdcg%4sC}fQ>SQfqfD<|QLKZbu0bmey zn>ySbJTIo+Yg>qQsYYi%=->qrLJSS|s>)D~v?@^y5+D%)=tR(RR~*=&{+Xb&!=hdq z1bd9>yiTmT(~$;ICNS-G8`IPC0B!~^-HfCAY{fj@N!~zf^??A(YV13D&70p&4gL7Z z%+)GJ-tvP6O*vy`kDu)K(hl%chF!+u4;4k2f}fA6hU?=m128H$%rBV3R#d3kdW3LL zK|M!f=H`)jvc{U+==GNiTyT|@gwDlaL{;kxkfiFq;l>TE3Wd@{2RlgT1Z!PNhhS4= zl=SP6al#dRKkL@D?o2o|G>0|iAs{ZowR4Btj80&df0zBvHFRDNJ(C3~owb^MTXJn}z}PikVFl{17jl_{%q>gD61JrSgqD-d( zFsQ_iS(KSxRk6b2gX*>mkyh%rb}6Lh@IncW1fBe&Iauu6ntDh*iw>L)D(Dry>zMUA z$iU9RK5o51X$6VqCsR|fB|e2J5oeALK2BYdCXM9Kk>DUYac*F{Ceulf;TWlygu z_lHit0z{aP*+J{j1Mr8Nhdeu{`eaoEF9by|@Ce#f1{K6#bUArEnx1FTavRlPmZBC| zcW`{Qz9k|C6N55?w`vkN9_!PO{@KVSXEUW-st>Q%hG+~-koK8l01!b1qGG&c5iKnG z3akMPTyi7Mv>B(JL}J>5CgtR52`!}CaO4ycIw!FkidccrVmjnoZ6u+BMHNXAKm)B} z2rD3lvRX}9|7gCeL{h1aS($}~#O+i9GLV5MDB6&XxsVJvLj@YhxC;Sj(7e_V!cCHW z;c~tVb>0==29oy|rGz{;T$lyY0w1TJ-o3X4JW;%px(ijb_v6{^BmH#zQ(X`qv@WpdEyWY;!|BebFCu0s#t6Pcoo7gv)^|C9~)9vBDK}g<8f|ug0dAz9i`2g5;pF z4`5K78O;~=*;6F_)jv~JhJT5jj$PF$I9Tt9`<*0|lJj6!xTqr3x~6vl46FcvD%V6d z9`#)Q+~so>@^SLfDrqKSDF7i_L3O-Ur`F+bvQf^&jACKoCdmXM{HR;0fcYyy7`?*| zpg{q;NaMdqWsb@LhAhfPl~F~JYv4jvKiFM*(gsx96d1e15+X@1ph1UYNkKALLOCjf z4c_2m?NQ637P4*6!V<1V59e@SyWmcWa3jX?dFp7#KO0MU0WaYR>hS<}MiKr6bhSFmEk!%@hHs&Tz8YHz{QI@_>0TB~h;G(L)(dpmGPsy(ScNy_xKn+V28_G}PKMnoJH9nRNsIX_pkIycdAPNj%T447 zuu+{T7QIkb+=Y;oW*t{>5jhUgZ&Z+0CQ)9jr+*l-$t6UZ(xRuHJ*(uslj$(H9SF0+ z1(U!+XVwE%!V)-*VAI0oxmf*Y&f1jSU_!|@7AG&rx&0*|15A=iElfm@8Bxca3!pK_ zrF}>f3W^050CE5g>R8sd`8{;ZS;(xZz^K%t^7AXcc+d>egdWYLdnZ+)N; zsc%B|Pd^9(q%G8*1%gu2IRGVMC%+N}JJvslMIBT~U)wmw^RZ;9S60J`06ShM!~j+^;^*V$KDpaKBQO>e^9t zPw$*%IsE`|db9>l>ujrZ{1xi)DH`QGo~GsNch9y!h2(hS`YZGrA0M+o1puIkFgDg% znVYI8pTQ9bCvk`-n)}#)rePkKxn3~!$Qs#YJkuzC#WLts;ah3Qg@W3p35f_<$L8QG zve!W26GUQb=xz!e@)d0f9#(B|iRiPQLcv^+iF5wl02LU;F_rF7iQXjX`w*al;+b3QG!xi*cmwml@_b8++^?eJmVX>#g3K^h@avsIpMVNWpEv%C?-SAG%zzvcLGQ z9Gm~7o}yAIO`beH4%~qckr!7WH_)JtE)igG0SJwy@AJ?{sQ0mi$a!2Bv9-;2e23y= z!xK<%Z?NP(F6tgP^LsStIrj}(or;YXAcG=i?S2hBqqZfS+4mgZu6TTl>@nTvxYG5P z-2wC5A5pXl-NTc`KTkpm!+0YnA9pp~OK7?0Rn-I|V5>Z-)dKsMT+4PrFw?SXO4i&S z-D$A_2Ulqx)iDC(PXTEkK3BczN?SzD3M093BsKqEip0pblfx5Jzy}Q+5WxitsSCaq%WY7Qx7Yev?Rzpbh{X05%Sa3uhpf+yAxOKHpQx`jh>U{EBZkO7eoX>;HhwB0LVc#UN(&C*1|1s6O6P`D;@vqVN^I*u-Q%G0WWg=B}xs2MZrm^EPtGo;2>1%?Gb z#rzBg&N_RW)@WQod4&!s=0KI|VFA(5Ll_8T_Bq`jkrFVHg(6Y85VIvXtbNwP)zZJQ z^1TSd(etW;h9uEyF%dCzSWJl!mZP-fxgRyDhNMw4oXwry`t}_ONOaa&+rmx|H#MM) z>Rzi>DFpYdNCD%;3{xcEXJhhr{a~2n$wbfu}Hdf|FArm1k2f0>=LUoJF>8Pq3$zk+{ zo*ojhCF;MC03x@FiztRbrY92=(a@k~_f!~p)hU{H?(3eZ(chm4wOe{!D07`F7G{7Ymaag=8!S&)VmnO<@55;+hS zgwFh=X>cE^M~%rDhYY6`leObQIh}k}c9=(QTvk@xR5`!favs>>QKYSS6j5gF{#<8;oG4GZiSkAGzvVXDNrG> z+D$0erdxOEd4B8)EEPQgb^sQ_HQ1+xt2M)F!`-OLIBCT6U0qg;6s-{K{#5Qvt_=>< z0v8{9%WQX0pFVp>&7C#*6_BP{S-M=>m;bwlJ{{u$BzkPqdc8toxQDj3GM8h-DJP{_|` zxbg(+$Re#ozc$@ZG}^IxGF7~8tMQNxUVnwpgwe|4@yzH2-I3PWw|&t=j?`6W1cUqj z$hv=-HQe3WD#+lT*HIy2v^<=aSE0<50SLna452yWS?VgmL4ao(eXA&HfvO8{ zyyI3CxWLQWAeypj>=iZH)@E9SGzr(Lr7406hNBNy{0gL|Jye-UN|0spq7~$KBS~g| zwIB={ZmhD)>azNSkAYy}RU-8(4WQI4P+dD}VPxQfKQgEZtCY%)p>jaTwGt^s5?D37 zQC`bfI{yUsf5QeYjY>z=3vOSIN2k(=II8}fD*-NWRa43BdPw{RZ158>+fFp+yaTRi zBDNz3*p_`RZBjW(!S$S+K2urrffZR%l6fVivWRAZ`pjH09fDU*9h6RAL(U-Lb_GEo zgKS%sS1LFDmc_a#Mq+dIADROfDC}55g|ox;~wbO zmCjj((F!!Az^?!{z;%>T<7If48(bJ&|5JklgB@Okki{T_2kBc3UzQ>r*j%j`auwtl z3ndCMCVeHFst6z-JA>D$dsnLCxf&~AFu+hrf3j&~kmxis8!`(cQph8#mNP9y1+Wlx zP^kSSypLq?i@zf5G$R!%n-OG()Y1t&%J_tos5&u8!?%<>biTgP zC(Bw{DuKNoE0GiGB?L?6NJ(T_=6Y}e3Vt4iCZn~&Y;RxN=^NcY!lH6*I2CCf(SD8U6EKoANpP`#6fYxz-u3kE7s&qwCt6JT&D?~yFJ zEyFXcxJ}b6<7r#Hd1~Oo*>$Arv7$OSH3!t=*Z>jOqkLFVf+6K?*t6)WOW03LUWiAe!axGCkz_6;+%BE>->kwb*Orr5tbE3MXUFoq~~W?hpD{ zSeQb4>?xR>yaLnfE(1lAN$bUPm^pka=H_lkf8kDyPt2g*YA^fk(}>1KrVofEU1)4% zpI^kOs?cwinNt$k5+z!umPcryA2V{y$D34=sC$>oNGPB08Q>v=&oLd5M>mRYF z<~@!;iso0Jk&3~TwJ{rJAf@ArR3M3k`%q5es(0I*SW^wD$B_LmKPBZ!PA>j6cAo5N zV+6Nv?UolBAQ?LiNkt}*L^WltIEz&~=Hy!3>Ty4)T;GqhyM|LcGO#dgO-qJMMx#w! zWCIKmPcex~UY-n5vd!lgS7J^j!mqrdhpV5HT=<$F9pIyX)slNf$luo1F$^|gn^l;C zDFD632FuujnoG*HaD`Q>jaJ=KXL&g6stm_A?rLG72eh7vjaz;Jt!PRz{+Q z>z@Mv7{s&KxBE|k{uePm-dTN}ZYXjV{C^2NV1ap-d?15!Q(~>VeZ=8S^^-QkF^3>D zG8ZrRU?{)^G{H3NkpKZ)VA)q!!G+v!qvSqW@wQ9nQdjCs<&+wduiapEWOe}!Bro6; ze;Je_2W7Wpw)t}C@urHzRJNN9gOZrQ3ZOu$AxQ<2z&V=58aTl@hM-@kNt>SP97oMa zXI*ds4zPth*l)ix}*pyhs_0Epuq<&n8&~P`F&jdtO39gz{&T!?gei8ddqp1 zn9@NNmK4J)-&q^k0U}hn7B^}DuVz$X8GfDV7*gQLIF1J~7MCu>8E3r-QB(~aXhl=l zwDp$|$FIiT9q-0?=Wax;)~eR(Eak#F00zrZa9H)$6N6-Wr2 z`M8;3F#3_kjBj<%#OzaFgfn)373&|o858ZmsW>!Rf$BCRVbhP?fDfMgkGST&Uq!E~ zO_VLuRvL^`_};gC7|*}$b$Ii?9uk3W8UkEUk7LE#CLy?m&iM)a?k`W`uio%yxV>l6 z-4Qna&<*&|dH;l;`Q2Nv6x=ohoc==m_V1sIe|y>Q;K9kG%dx~>Nx!(F7T9!M#Q~H65E+`4j6q7%-Tc<6ZjV+s_iM#5 zHH=Hv^;2ySfmG>nM=!Y02Up}newZei)}7Iq2*q6?i>v4TvW`AJ2bd8@IjcU$L*hitej(E-v}NbFuV$ zAH{tSaPXY462T^gJcLO`n<`6xDd~V5X6HrC!@&hpu}IMhmF&}i6VKSdxb}Z80C5ET zfA-EhOo}S|`=47KCMO1%A?KVC5L7Usn8TU_3W|V;BI=5PV8FC0EF%og{?R=htJ4H@-`^HbKTKCw-Kv|;J?DGR`5r}hf|VY**Ukfn z<2i9kge_2)0Ehq*AcFH;giNg&=A9$Pb_M6+icw<`HMs7-ltm@#nu{o(AkKJe#Hyy) zDxIWcJWjoovugBQMKRI1K z23!c&f6)-W{$D*}OQ$IRG_j3V+^*FS6 zai1`@XV|P4xS>(-h;XcYom>8~+HC}jI@z7jok6jBFUVMCuX`Rfxt`ZwYsr6xzs^!y z)f_U=?yi3_C3POdXKlvegLC*R(Qb_+vpeTEKEkpbH=vQXl286+V87F4(j<30k4{A^ zSa)1{jXoJ|HEO5+F*#O-YC9cpAyoTT@k)pQa6$_2rcQ0hp2RXi$Ha#0;^Y~@4{E${ z26!#_5rg}9EqHg+1wu$qNQ93ggP#XOjTY)C+9{I9hp6FfuPtyPG{6wvdx21G87ed) za!f__yFxbx+%0$A0z^pn9FkQsr3&Pf-glB9G&i{5IVXLhvPD2lga6Tcw~ad&l%r_E zRYnB!R4NVVIBg7F+W1`T*w5w>A90}Q49_`36S~a2j}A?PN0GMrD;B(%gYygu07L8E z^cXpi#%)tEIx8sOyP2F<7gJyff1jySH!_QJD9CrWwV^(Z1}1Q7=~3(waOQLPgWu5d zs1||{(>#l6F#Csi)ub$AY%@N%8VwrOXU4RD0PxWG$0;l<3|U0u#*KJp%0!-hb}IRK z`9aEp9=H%qouUbo2-`*xF1q823UH{dYZT#`YBCr+Bb#sqgbRW@av zOL2?-ph?g)_nKlv9Wt7NOGaW^_A&Kx7Ljau;mmk1JSP5bM%WJtyV5Stmq

5ii2_J5Xx;iW;PSdtkR~k`Ir}YB#DWRW&b#cXx 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 N002ovPDHLkV1mfWZUq1U literal 0 HcmV?d00001 diff --git a/docs/dots.png b/docs/dots.png new file mode 100644 index 0000000000000000000000000000000000000000..a73791ae0c48d7a3c7b4d67cbe04cc29ed40d6fd GIT binary patch literal 58809 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 Hu0mjfj}2L$ literal 0 HcmV?d00001 diff --git a/docs/metro.png b/docs/metro.png new file mode 100644 index 0000000000000000000000000000000000000000..edd6507b5dfc4c60bc13bf1cb83cf1e0e2a776af GIT binary patch literal 58884 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

D5RdUqP-6=9+`CDK3N=yh{6L2 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

{(<*+X%==*~Q58$D@ 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⁡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 z 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 literal 0 HcmV?d00001 diff --git a/install.sh b/install.sh index 0423af63..2fc3af3c 100755 --- a/install.sh +++ b/install.sh @@ -1,5 +1,5 @@ #!/bin/sh SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) sh $SCRIPT_DIR/build.sh -kpackagetool5 -i $SCRIPT_DIR/release/FancyTasks.tar.gz -sh ./iconinstall.sh \ No newline at end of file +kpackagetool6 -i $SCRIPT_DIR/release/FancyTasks.tar.gz +sh ./iconinstall.sh diff --git a/package/contents/config/config.qml b/package/contents/config/config.qml index 2e6565a4..0a4a85b0 100644 --- a/package/contents/config/config.qml +++ b/package/contents/config/config.qml @@ -10,18 +10,23 @@ import org.kde.plasma.configuration ConfigModel { ConfigCategory { - name: i18n("Appearance") - icon: "preferences-desktop-color" - source: "ConfigAppearance.qml" + name: i18n("Appearance") + icon: "preferences-desktop-color" + source: "ConfigAppearance.qml" } ConfigCategory { - name: i18n("Behavior") - icon: "preferences-desktop" - source: "ConfigBehavior.qml" + name: i18n("Behavior") + icon: "preferences-desktop" + source: "ConfigBehavior.qml" } ConfigCategory { name: i18n("Indicators") icon: "preferences-desktop-navigation" source: "ConfigIndicators.qml" } + ConfigCategory { + name: i18n("Pinned Applications") + icon: "window-pin" + source: "ConfigPinnedApps.qml" + } } diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index 3b77e122..dcb8c83e 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -1,21 +1,26 @@ - - - + + + - + false - + true - + true @@ -27,47 +32,58 @@ true - + 1 - + 1 - + 0 - + true - + true - - + + - - + + - + 1 - + true - + true - + 1 1 @@ -77,7 +93,8 @@ 1 - + false @@ -87,42 +104,48 @@ - - - + + + 1 - + true - + true - + true - - applications:systemsettings.desktop,applications:org.kde.discover.desktop,preferred://filemanager,preferred://browser + + applications:systemsettings.desktop,applications:org.kde.discover.desktop,preferred://filemanager,preferred://browser - - - - - - + + + + + + 2 - + true @@ -142,23 +165,28 @@ true - + true - + 0 - + true - + false - + 1 @@ -186,11 +214,13 @@ 1 - + 0 - + 0 @@ -252,7 +282,7 @@ 0 - + false @@ -282,9 +312,10 @@ false - + 0 - + false @@ -293,6 +324,16 @@ false + + 20 + + How much the icon should grow when hovered + + + 250 + + Duration of the zoom animation in milliseconds + diff --git a/package/contents/ui/ConfigAppearance.qml b/package/contents/ui/ConfigAppearance.qml index e9a337f1..ff77b408 100644 --- a/package/contents/ui/ConfigAppearance.qml +++ b/package/contents/ui/ConfigAppearance.qml @@ -19,6 +19,8 @@ KCMUtils.SimpleKCM { readonly property bool plasmoidVertical: Plasmoid.formFactor === PlasmaCore.Types.Vertical readonly property bool iconOnly: plasmoid.configuration.iconOnly + property alias cfg_iconZoomFactor: iconZoomFactor.value + property alias cfg_iconZoomDuration: iconZoomDuration.value property alias cfg_showToolTips: showToolTips.checked property alias cfg_highlightWindows: highlightWindows.checked property bool cfg_indicateAudioStreams @@ -76,6 +78,37 @@ KCMUtils.SimpleKCM { visible: !iconSizeOverride.checked } + Item { + Kirigami.FormData.isSection: true + Kirigami.FormData.label: i18n("Icon Hover Effects") + } + + SpinBox { + id: iconZoomFactor + Kirigami.FormData.label: i18n("Icon zoom factor (px):") + from: 0 + to: 50 + stepSize: 1 + value: plasmoid.configuration.iconZoomFactor + + ToolTip.delay: 1000 + ToolTip.visible: hovered + ToolTip.text: i18n("How much the icon should grow when hovered (in pixels)") + } + + SpinBox { + id: iconZoomDuration + Kirigami.FormData.label: i18n("Zoom animation duration (ms):") + from: 0 + to: 1000 + stepSize: 50 + value: plasmoid.configuration.iconZoomDuration + + ToolTip.delay: 1000 + ToolTip.visible: hovered + ToolTip.text: i18n("Duration of the zoom animation in milliseconds") + } + SpinBox { id: iconSizePx Kirigami.FormData.label: i18n("Icon Size (px):") @@ -112,16 +145,16 @@ KCMUtils.SimpleKCM { } CheckBox { - enabled: buttonColorize.checked id: buttonColorizeDominant + enabled: buttonColorize.checked text: i18n("Use dominant icon color") visible: buttonColorize.checked } KQuickAddons.ColorButton { + id: buttonColorizeCustom Layout.leftMargin: Kirigami.Units.GridUnit enabled: buttonColorize.checked & !buttonColorizeDominant.checked - id: buttonColorizeCustom Kirigami.FormData.label: i18n("Custom Color:") showAlphaChannel: true visible: buttonColorize.checked && !buttonColorizeDominant.checked @@ -163,12 +196,7 @@ KCMUtils.SimpleKCM { ComboBox { id: plasmaButtonDirection visible: overridePlasmaButtonDirection.checked - model: [ - i18n("North"), - i18n("South"), - i18n("West"), - i18n("East") - ] + model: [i18n("North"), i18n("South"), i18n("West"), i18n("East")] } Item { @@ -176,8 +204,8 @@ KCMUtils.SimpleKCM { } SpinBox { - visible: !plasmoidVertical && !iconOnly id: maxButtonLength + visible: !plasmoidVertical && !iconOnly Kirigami.FormData.label: i18n("Maximum button length (px):") from: 1 to: 9999 @@ -190,7 +218,6 @@ KCMUtils.SimpleKCM { to: 99 } - CheckBox { id: showToolTips Kirigami.FormData.label: i18nc("@label for several checkboxes", "General:") @@ -226,11 +253,7 @@ KCMUtils.SimpleKCM { Kirigami.FormData.label: i18nc("@label:listbox", "Maximum task width:") - model: [ - i18nc("@item:inlistbox how wide a task item should be", "Narrow"), - i18nc("@item:inlistbox how wide a task item should be", "Medium"), - i18nc("@item:inlistbox how wide a task item should be", "Wide") - ] + model: [i18nc("@item:inlistbox how wide a task item should be", "Narrow"), i18nc("@item:inlistbox how wide a task item should be", "Medium"), i18nc("@item:inlistbox how wide a task item should be", "Wide")] } Item { @@ -239,12 +262,10 @@ KCMUtils.SimpleKCM { RadioButton { id: forbidStripes - Kirigami.FormData.label: plasmoidVertical - ? i18nc("@label for radio button group, completes sentence: … when panel is low on space etc.", "Use multi-column view:") - : i18nc("@label for radio button group, completes sentence: … when panel is low on space etc.", "Use multi-row view:") + Kirigami.FormData.label: plasmoidVertical ? i18nc("@label for radio button group, completes sentence: … when panel is low on space etc.", "Use multi-column view:") : i18nc("@label for radio button group, completes sentence: … when panel is low on space etc.", "Use multi-row view:") onToggled: { if (checked) { - maxStripes.value = 1 + maxStripes.value = 1; } } text: i18nc("@option:radio Never use multi-column view for Task Manager", "Never") @@ -254,7 +275,7 @@ KCMUtils.SimpleKCM { id: allowStripes onToggled: { if (checked) { - maxStripes.value = Math.max(2, maxStripes.value) + maxStripes.value = Math.max(2, maxStripes.value); } } text: i18nc("@option:radio completes sentence: Use multi-column/row view", "When panel is low on space and thick enough") @@ -264,7 +285,7 @@ KCMUtils.SimpleKCM { id: forceStripes onToggled: { if (checked) { - maxStripes.value = Math.max(2, maxStripes.value) + maxStripes.value = Math.max(2, maxStripes.value); } } text: i18nc("@option:radio completes sentence: Use multi-column/row view", "Always when panel is thick enough") @@ -273,9 +294,7 @@ KCMUtils.SimpleKCM { SpinBox { id: maxStripes enabled: maxStripes.value > 1 - Kirigami.FormData.label: plasmoidVertical - ? i18nc("@label:spinbox maximum number of columns for tasks", "Maximum columns:") - : i18nc("@label:spinbox maximum number of rows for tasks", "Maximum rows:") + Kirigami.FormData.label: plasmoidVertical ? i18nc("@label:spinbox maximum number of columns for tasks", "Maximum columns:") : i18nc("@label:spinbox maximum number of rows for tasks", "Maximum rows:") from: 1 } @@ -311,9 +330,12 @@ KCMUtils.SimpleKCM { } switch (cfg_iconSpacing) { - case 0: return 0; // Small - case 1: return 1; // Normal - case 3: return 2; // Large + case 0: + return 0; // Small + case 1: + return 1; // Normal + case 3: + return 2; // Large } } onActivated: index => { diff --git a/package/contents/ui/ConfigPinnedApps.qml b/package/contents/ui/ConfigPinnedApps.qml new file mode 100644 index 00000000..3f490820 --- /dev/null +++ b/package/contents/ui/ConfigPinnedApps.qml @@ -0,0 +1,724 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Dialogs + +import org.kde.kcmutils as KCMUtils +import org.kde.kirigami as Kirigami +import org.kde.plasma.core as PlasmaCore +import org.kde.plasma.components as PlasmaComponents +import org.kde.plasma.extras as PlasmaExtras +import org.kde.plasma.plasmoid +import org.kde.plasma.plasma5support as P5Support + +KCMUtils.SimpleKCM { + id: pinnedAppsDialog + + property var pinnedLaunchers: plasmoid.configuration.launchers + property bool appsLoaded: false + property bool initialLoadDone: false + property bool isLoadingApps: false + property int appsBatchSize: 15 + + // App picker dialog + Dialog { + id: appPickerDialog + title: i18n("Add Application") + modal: true + standardButtons: Dialog.Close + + width: Math.min(800, parent.width - Kirigami.Units.gridUnit * 4) + height: Math.min(600, parent.height - Kirigami.Units.gridUnit * 4) + + anchors.centerIn: parent + + onOpened: { + if (!initialLoadDone) { + initialLoadDone = true; + initialLoadTimer.start(); + } + } + + ColumnLayout { + anchors.fill: parent + spacing: Kirigami.Units.smallSpacing + + PlasmaExtras.SearchField { + id: searchField + Layout.fillWidth: true + placeholderText: i18n("Search applications...") + onTextChanged: searchTimer.restart() + } + + Timer { + id: searchTimer + interval: 300 + onTriggered: filterAppsModel() + } + + ScrollView { + Layout.fillWidth: true + Layout.fillHeight: true + + ListView { + id: appsListView + model: filteredAppsModel + + onContentYChanged: { + if (contentY + height >= contentHeight - 200 && !isLoadingApps) { + loadMoreApps(); + } + } + + delegate: ItemDelegate { + width: appsListView.width + + contentItem: RowLayout { + spacing: Kirigami.Units.smallSpacing + + Kirigami.Icon { + source: model.icon || "application-x-executable" + Layout.preferredWidth: Kirigami.Units.iconSizes.medium + Layout.preferredHeight: Kirigami.Units.iconSizes.medium + } + + Label { + text: model.name || model.url + elide: Text.ElideRight + Layout.fillWidth: true + font.bold: true + } + + Button { + icon.name: "list-add" + text: i18n("Add") + onClicked: { + addLauncher(model.url); + appPickerDialog.close(); + } + } + } + } + } + } + + // Loading indicator + Item { + visible: isLoadingApps && filteredAppsModel.count === 0 + Layout.fillWidth: true + Layout.fillHeight: true + + BusyIndicator { + anchors.centerIn: parent + running: isLoadingApps + } + } + } + } + + // Initial app loading timer + Timer { + id: initialLoadTimer + interval: 200 + repeat: false + onTriggered: { + isLoadingApps = true; + loadInstalledApps(); + } + } + + // App loading data source + P5Support.DataSource { + id: appsSource + engine: "apps" + connectedSources: ["apps:"] + interval: 0 + + property var requestedSources: ({}) + + onSourceConnected: { + processAppSource(source); + } + } + + ListModel { + id: installedAppsModel + } + + ListModel { + id: filteredAppsModel + } + + function loadInstalledApps() { + // Add default special launchers + if (installedAppsModel.count === 0) { + installedAppsModel.append({ + name: i18n("Default Web Browser"), + icon: "internet-web-browser", + url: "preferred://browser", + keywords: "web browser internet" + }); + + installedAppsModel.append({ + name: i18n("Default File Manager"), + icon: "system-file-manager", + url: "preferred://filemanager", + keywords: "files folder" + }); + + installedAppsModel.append({ + name: i18n("Default Mail Client"), + icon: "internet-mail", + url: "preferred://mail", + keywords: "email mail" + }); + } + + // Start batch processing of app sources + startBatchProcessing(); + } + + function startBatchProcessing() { + // Create a prioritized list of desktop files + const desktopFiles = []; + const commonPrefixes = ["firefox", "chromium", "chrome", "brave", "dolphin", "konsole", "kate", "gnome-terminal", "org.kde"]; + + // Pre-sort desktop files with common ones first + for (let i = 0; i < appsSource.sources.length; i++) { + const source = appsSource.sources[i]; + if (source !== "apps:" && source.endsWith(".desktop")) { + // Check if it's a commonly used app + let priority = 1000; + const sourceLower = source.toLowerCase(); + + for (let j = 0; j < commonPrefixes.length; j++) { + if (sourceLower.includes(commonPrefixes[j])) { + priority = j; + break; + } + } + + desktopFiles.push({ + source: source, + priority: priority + }); + } + } + + // Sort by priority + desktopFiles.sort((a, b) => a.priority - b.priority); + + // Process in batches + let processedCount = 0; + + function processBatch() { + const batchSize = 15; + const end = Math.min(processedCount + batchSize, desktopFiles.length); + + for (let i = processedCount; i < end; i++) { + const source = desktopFiles[i].source; + + if (!appsSource.requestedSources[source]) { + appsSource.connectSource(source); + appsSource.requestedSources[source] = true; + } + } + + processedCount = end; + + if (processedCount < desktopFiles.length) { + // Schedule next batch + Qt.callLater(processBatch); + } else { + // All batches scheduled + isLoadingApps = false; + appsLoaded = true; + } + } + + // Start processing + processBatch(); + } + + function processAppSource(source) { + if (source === "apps:" || !source.endsWith(".desktop")) { + return; + } + + try { + // Extract app name + let appName = source.replace(".desktop", ""); + const lastSlash = appName.lastIndexOf("/"); + if (lastSlash !== -1) { + appName = appName.substring(lastSlash + 1); + } + appName = appName.split(/[-_.]/).map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" "); + + // Check for duplicates + for (let j = 0; j < installedAppsModel.count; j++) { + if (installedAppsModel.get(j).url === "applications:" + source) { + return; + } + } + + installedAppsModel.append({ + name: appName, + icon: appName.toLowerCase().replace(/\s+/g, "-") || "application-x-executable", + url: "applications:" + source, + keywords: "" + }); + + // Update filtered model if needed + if (searchField.text.length === 0 && filteredAppsModel.count < 100) { + filteredAppsModel.append({ + name: appName, + icon: appName.toLowerCase().replace(/\s+/g, "-") || "application-x-executable", + url: "applications:" + source, + keywords: "" + }); + } + } catch (e) { + console.log("Error processing app:", source, e); + } + } + + function filterAppsModel() { + const searchText = searchField.text.toLowerCase(); + + // Optimization for empty search with already filled model + if (searchText.length === 0 && filteredAppsModel.count > 0 && filteredAppsModel.count === Math.min(installedAppsModel.count, 100)) { + return; + } + + filteredAppsModel.clear(); + + for (let i = 0; i < installedAppsModel.count; i++) { + const app = installedAppsModel.get(i); + + // Apply search filter + if (searchText && searchText.length > 0) { + if (app.name.toLowerCase().includes(searchText) || app.url.toLowerCase().includes(searchText) || (app.keywords && app.keywords.toLowerCase().includes(searchText))) { + filteredAppsModel.append(app); + } + } else { + filteredAppsModel.append(app); + + // Limit initial load for better performance + if (filteredAppsModel.count >= 100) { + break; + } + } + } + } + + function loadMoreApps() { + if (isLoadingApps) + return; + + if (filteredAppsModel.count < installedAppsModel.count) { + const startIndex = filteredAppsModel.count; + const endIndex = Math.min(startIndex + 30, installedAppsModel.count); + + for (let i = startIndex; i < endIndex; i++) { + filteredAppsModel.append(installedAppsModel.get(i)); + } + } + } + + Component.onCompleted: { + refreshPinnedAppsModel(); + } + + function refreshPinnedAppsModel() { + pinnedAppsModel.clear(); + for (let i = 0; i < pinnedLaunchers.length; i++) { + let launcher = pinnedLaunchers[i]; + let name = getNameForUrl(launcher); + let icon = getIconForUrl(launcher); + pinnedAppsModel.append({ + "name": name, + "icon": icon, + "url": launcher + }); + } + } + + function getNameForUrl(url) { + let appName = url; + + if (appName.indexOf("preferred://") === 0) { + if (appName === "preferred://browser") + return i18n("Default Web Browser"); + if (appName === "preferred://filemanager") + return i18n("Default File Manager"); + if (appName === "preferred://mail") + return i18n("Default Mail Client"); + return i18n("Default Application"); + } + + if (appName.indexOf("applications:") === 0) { + // Check installed apps model first + for (let i = 0; i < installedAppsModel.count; i++) { + const app = installedAppsModel.get(i); + if (app.url === appName) { + return app.name; + } + } + + // Fallback formatting + appName = appName.substring(13); + if (appName.endsWith(".desktop")) { + appName = appName.substring(0, appName.length - 8); + } + appName = appName.split(/[-_.]/g).map(word => { + return word.charAt(0).toUpperCase() + word.slice(1); + }).join(" "); + } + + return appName; + } + + function getIconForUrl(url) { + let appId = url; + + // Check installed apps model first + for (let i = 0; i < installedAppsModel.count; i++) { + const app = installedAppsModel.get(i); + if (app.url === appId) { + return app.icon; + } + } + + if (appId.indexOf("preferred://") === 0) { + if (appId === "preferred://browser") + return "internet-web-browser"; + if (appId === "preferred://filemanager") + return "system-file-manager"; + if (appId === "preferred://mail") + return "internet-mail"; + return "preferences-desktop-default-applications"; + } + + if (appId.indexOf("applications:") === 0) { + appId = appId.substring(13); + if (appId.endsWith(".desktop")) { + return appId.substring(0, appId.length - 8).toLowerCase(); + } + return appId.toLowerCase(); + } + + return "application-x-executable"; + } + + ListModel { + id: pinnedAppsModel + } + + // For better drag and drop reordering + property int dragItemIndex: -1 + property int dropItemIndex: -1 + property bool isDragging: false + + ColumnLayout { + anchors.fill: parent + spacing: Kirigami.Units.largeSpacing + + Kirigami.InlineMessage { + Layout.fillWidth: true + type: Kirigami.MessageType.Information + text: i18n("Add applications to pin to the taskbar. Drag items to reorder them.") + visible: true + } + + ListView { + id: pinnedAppsList + Layout.fillWidth: true + Layout.fillHeight: true + + model: pinnedAppsModel + + // Disable animations during drag + interactive: !isDragging + + // Add scrollbar when needed + ScrollBar.vertical: ScrollBar {} + + // Add drop area to handle autoscroll + DropArea { + id: dropArea + anchors.fill: parent + + onEntered: { + if (isDragging) { + // Calculate new index based on drop position + var newIndex = Math.floor((drag.y + pinnedAppsList.contentY) / 48); // Approximate item height + if (newIndex >= 0 && newIndex < pinnedAppsModel.count) { + dropItemIndex = newIndex; + } + } + } + + onPositionChanged: { + if (isDragging) { + // Handle auto-scrolling + var localY = drag.y; + if (localY < 50) { + // Auto-scroll up + autoScrollTimer.direction = -1; + autoScrollTimer.running = true; + } else if (localY > pinnedAppsList.height - 50) { + // Auto-scroll down + autoScrollTimer.direction = 1; + autoScrollTimer.running = true; + } else { + // Stop auto-scrolling + autoScrollTimer.running = false; + } + + // Calculate drop index + var newIndex = Math.floor((localY + pinnedAppsList.contentY) / 48); + if (newIndex >= 0 && newIndex < pinnedAppsModel.count) { + dropItemIndex = newIndex; + } + } + } + + onDropped: { + autoScrollTimer.running = false; + } + + onExited: { + autoScrollTimer.running = false; + } + } + + // Timer for auto-scrolling during drag + Timer { + id: autoScrollTimer + interval: 50 + repeat: true + property int direction: 0 // -1 for up, 1 for down + property int scrollStep: 10 + + onTriggered: { + pinnedAppsList.contentY = Math.max(0, Math.min(pinnedAppsList.contentY + direction * scrollStep, pinnedAppsList.contentHeight - pinnedAppsList.height)); + } + } + + delegate: Item { + id: pinnedAppDelegate + width: ListView.view.width + height: 48 + + // Properties for drag operation + property bool beingDragged: index === dragItemIndex + + Drag.active: mouseArea.drag.active + Drag.source: pinnedAppDelegate + Drag.hotSpot.x: width / 2 + Drag.hotSpot.y: height / 2 + + // Visual representation during drag + states: [ + State { + when: beingDragged + ParentChange { + target: pinnedAppDelegate + parent: pinnedAppsDialog + } + PropertyChanges { + target: pinnedAppDelegate + z: 100 + opacity: 0.8 + } + } + ] + + Rectangle { + id: itemHighlight + anchors.fill: parent + color: dropItemIndex === index && isDragging ? Kirigami.Theme.highlightColor : mouseArea.containsMouse ? Kirigami.Theme.highlightColor.lighter(0.7) : "transparent" + opacity: 0.3 + radius: 3 + + Behavior on color { + ColorAnimation { + duration: 100 + } + } + } + + RowLayout { + anchors.fill: parent + anchors.margins: Kirigami.Units.smallSpacing + spacing: Kirigami.Units.smallSpacing + + // Drag handle + Item { + Layout.preferredWidth: Kirigami.Units.iconSizes.small + Layout.preferredHeight: parent.height + + Rectangle { + width: Kirigami.Units.smallSpacing + height: Kirigami.Units.iconSizes.small + radius: width / 2 + anchors.centerIn: parent + color: Kirigami.Theme.textColor + opacity: 0.5 + } + } + + Kirigami.Icon { + source: model.icon + Layout.preferredWidth: Kirigami.Units.iconSizes.medium + Layout.preferredHeight: Kirigami.Units.iconSizes.medium + } + + Label { + text: model.name + elide: Text.ElideRight + Layout.fillWidth: true + } + + Label { + text: model.url + opacity: 0.6 + font.pointSize: Kirigami.Theme.smallFont.pointSize + elide: Text.ElideMiddle + Layout.maximumWidth: parent.width / 3 + horizontalAlignment: Text.AlignRight + visible: Kirigami.Settings.isMobile ? false : true + } + + Button { + icon.name: "list-remove" + onClicked: { + let currentLaunchers = pinnedLaunchers; + currentLaunchers.splice(index, 1); + plasmoid.configuration.launchers = currentLaunchers; + pinnedLaunchers = currentLaunchers; + refreshPinnedAppsModel(); + } + ToolTip.text: i18n("Remove") + ToolTip.visible: hovered + ToolTip.delay: 1000 + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + cursorShape: pressed ? Qt.ClosedHandCursor : Qt.PointingHandCursor + + drag.target: pinnedAppDelegate + drag.axis: Drag.YAxis + + onPressed: { + // Start dragging + dragItemIndex = index; + isDragging = true; + } + + onReleased: { + // End dragging + isDragging = false; + + if (dropItemIndex !== -1 && dragItemIndex !== -1 && dropItemIndex !== dragItemIndex) { + // Move the item + moveItem(dragItemIndex, dropItemIndex); + } + + // Reset state + dragItemIndex = -1; + dropItemIndex = -1; + } + } + } + } + + RowLayout { + Layout.fillWidth: true + + Button { + id: addAppButton + icon.name: "list-add" + text: i18n("Add Application...") + onClicked: appPickerDialog.open() + Layout.fillWidth: true + } + + Button { + id: addSpecialButton + icon.name: "preferences-desktop-default-applications" + text: i18n("Add Special Launcher...") + onClicked: specialLauncherMenu.popup() + + Menu { + id: specialLauncherMenu + + MenuItem { + text: i18n("Default Web Browser") + icon.name: "internet-web-browser" + onTriggered: { + addLauncher("preferred://browser"); + } + } + + MenuItem { + text: i18n("Default File Manager") + icon.name: "system-file-manager" + onTriggered: { + addLauncher("preferred://filemanager"); + } + } + + MenuItem { + text: i18n("Default Mail Client") + icon.name: "internet-mail" + onTriggered: { + addLauncher("preferred://mail"); + } + } + } + } + } + } + + function addLauncher(url) { + let currentLaunchers = pinnedLaunchers; + + // Don't add if already in the list + if (currentLaunchers.indexOf(url) !== -1) { + return; + } + + currentLaunchers.push(url); + plasmoid.configuration.launchers = currentLaunchers; + pinnedLaunchers = currentLaunchers; + refreshPinnedAppsModel(); + } + + // Move item in the model and update configuration + function moveItem(fromIndex, toIndex) { + // First create a copy of the current launchers + let currentLaunchers = []; + for (let i = 0; i < pinnedLaunchers.length; i++) { + currentLaunchers.push(pinnedLaunchers[i]); + } + + // Move the item in the array + const item = currentLaunchers.splice(fromIndex, 1)[0]; + currentLaunchers.splice(toIndex, 0, item); + + console.log("Moving item from", fromIndex, "to", toIndex); + console.log("New order:", currentLaunchers.join(", ")); + + // Update the configuration + plasmoid.configuration.launchers = currentLaunchers; + pinnedLaunchers = currentLaunchers; + + // Refresh model to ensure view is updated + refreshPinnedAppsModel(); + } +} diff --git a/package/contents/ui/PipeWireThumbnail.qml b/package/contents/ui/PipeWireThumbnail.qml index 9209ab58..ec79b5e1 100644 --- a/package/contents/ui/PipeWireThumbnail.qml +++ b/package/contents/ui/PipeWireThumbnail.qml @@ -13,7 +13,21 @@ PipeWire.PipeWireSourceItem { readonly property alias hasThumbnail: pipeWireSourceItem.ready - anchors.fill: parent + // Center it in the parent + anchors.centerIn: parent + + // Maintain aspect ratio with smarter dimension calculation + width: parent.width + height: { + // If we have valid source dimensions, calculate proper height + if (sourceSize.width > 0 && sourceSize.height > 0) { + return Math.min(parent.height, parent.width * (sourceSize.height / sourceSize.width)); + } else { + // Fallback to a reasonable default + return Math.min(parent.height, parent.width * 0.75); // 4:3 aspect ratio as fallback + } + } + nodeId: waylandItem.nodeId TaskManager.ScreencastingRequest { diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index ec47ffe9..9873528e 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -30,33 +30,23 @@ PlasmaCore.ToolTipArea { readonly property bool isCiliora: plasmoid.configuration.indicatorStyle === 1 readonly property bool isDashes: plasmoid.configuration.indicatorStyle === 2 - property string tintColor: Kirigami.ColorUtils.brightnessForColor(Kirigami.Theme.backgroundColor) - === Kirigami.ColorUtils.Dark - ? "#ffffff" - : "#000000" + property string tintColor: Kirigami.ColorUtils.brightnessForColor(Kirigami.Theme.backgroundColor) === Kirigami.ColorUtils.Dark ? "#ffffff" : "#000000" // To achieve a bottom to top layout, the task manager is rotated by 180 degrees(see main.qml). // This makes the tasks mirrored, so we mirror them again to fix that. rotation: Plasmoid.configuration.reverseMode && Plasmoid.formFactor === PlasmaCore.Types.Vertical ? 180 : 0 - implicitHeight: inPopup - ? LayoutMetrics.preferredHeightInPopup() - : Math.max(tasksRoot.height / tasksRoot.plasmoid.configuration.maxStripes, - LayoutMetrics.preferredMinHeight()) - implicitWidth: tasksRoot.vertical - ? Math.max(LayoutMetrics.preferredMinWidth(), Math.min(LayoutMetrics.preferredMaxWidth(), tasksRoot.width / tasksRoot.plasmoid.configuration.maxStripes)) - : 0 + implicitHeight: inPopup ? LayoutMetrics.preferredHeightInPopup() : Math.max(tasksRoot.height / tasksRoot.plasmoid.configuration.maxStripes, LayoutMetrics.preferredMinHeight()) + implicitWidth: tasksRoot.vertical ? Math.max(LayoutMetrics.preferredMinWidth(), Math.min(LayoutMetrics.preferredMaxWidth(), tasksRoot.width / tasksRoot.plasmoid.configuration.maxStripes)) : 0 Layout.fillWidth: true Layout.fillHeight: !inPopup - Layout.maximumWidth: tasksRoot.vertical - ? -1 - : ((model.IsLauncher && !tasks.iconsOnly) ? tasksRoot.height / taskList.rows : LayoutMetrics.preferredMaxWidth()) + Layout.maximumWidth: tasksRoot.vertical ? -1 : ((model.IsLauncher && !tasks.iconsOnly) ? tasksRoot.height / taskList.rows : LayoutMetrics.preferredMaxWidth()) Layout.maximumHeight: tasksRoot.vertical ? LayoutMetrics.preferredMaxHeight() : -1 required property var model required property int index - required property /*main.qml*/ Item tasksRoot + required property /*main.qml*/ Item tasksRoot readonly property int pid: model.AppPid readonly property string appName: model.AppName @@ -81,9 +71,7 @@ PlasmaCore.ToolTipArea { readonly property bool playingAudio: hasAudioStream && audioStreams.some(item => !item.corked) readonly property bool muted: hasAudioStream && audioStreams.every(item => item.muted) - readonly property bool highlighted: (inPopup && activeFocus) || (!inPopup && containsMouse) - || (task.contextMenu && task.contextMenu.status === PlasmaExtras.Menu.Open) - || (!!tasksRoot.groupDialog && tasksRoot.groupDialog.visualParent === task) + readonly property bool highlighted: (inPopup && activeFocus) || (!inPopup && containsMouse) || (task.contextMenu && task.contextMenu.status === PlasmaExtras.Menu.Open) || (!!tasksRoot.groupDialog && tasksRoot.groupDialog.visualParent === task) property int itemIndex: index // fancytasks @@ -162,7 +150,7 @@ PlasmaCore.ToolTipArea { } if (model.IsLauncher) { - return i18nc("@info:usagetip %1 application name", "Launch %1", model.display) + return i18nc("@info:usagetip %1 application name", "Launch %1", model.display); } let smartLauncherDescription = ""; @@ -174,18 +162,20 @@ PlasmaCore.ToolTipArea { switch (Plasmoid.configuration.groupedTaskVisualization) { case 0: break; // Use the default description - case 1: { - if (Plasmoid.configuration.showToolTips) { - return `${i18nc("@info:usagetip %1 task name", "Show Task tooltip for %1", model.display)}; ${smartLauncherDescription}`; + case 1: + { + if (Plasmoid.configuration.showToolTips) { + return `${i18nc("@info:usagetip %1 task name", "Show Task tooltip for %1", model.display)}; ${smartLauncherDescription}`; + } + // fallthrough } - // fallthrough - } - case 2: { - if (effectWatcher.registered) { - return `${i18nc("@info:usagetip %1 task name", "Show windows side by side for %1", model.display)}; ${smartLauncherDescription}`; + case 2: + { + if (effectWatcher.registered) { + return `${i18nc("@info:usagetip %1 task name", "Show windows side by side for %1", model.display)}; ${smartLauncherDescription}`; + } + // fallthrough } - // fallthrough - } default: return `${i18nc("@info:usagetip %1 task name", "Open textual list of windows for %1", model.display)}; ${smartLauncherDescription}`; } @@ -219,13 +209,19 @@ PlasmaCore.ToolTipArea { backend.cancelHighlightWindows(); } - onPidChanged: updateAudioStreams({delay: false}) - onAppNameChanged: updateAudioStreams({delay: false}) + onPidChanged: updateAudioStreams({ + delay: false + }) + onAppNameChanged: updateAudioStreams({ + delay: false + }) onIsWindowChanged: { if (model.IsWindow) { taskInitComponent.createObject(task); - updateAudioStreams({delay: false}); + updateAudioStreams({ + delay: false + }); } } @@ -240,8 +236,7 @@ PlasmaCore.ToolTipArea { onIndexChanged: { hideToolTip(); - if (!inPopup && !tasksRoot.vertical - && !Plasmoid.configuration.separateLaunchers) { + if (!inPopup && !tasksRoot.vertical && !Plasmoid.configuration.separateLaunchers) { tasksRoot.requestLayout(); } } @@ -277,8 +272,8 @@ PlasmaCore.ToolTipArea { Keys.onMenuPressed: event => contextMenuTimer.start() Keys.onReturnPressed: event => TaskTools.activateTask(modelIndex(), model, event.modifiers, task, Plasmoid, tasksRoot, effectWatcher.registered) - Keys.onEnterPressed: event => Keys.returnPressed(event); - Keys.onSpacePressed: event => Keys.returnPressed(event); + Keys.onEnterPressed: event => Keys.returnPressed(event) + Keys.onSpacePressed: event => Keys.returnPressed(event) Keys.onUpPressed: event => Keys.leftPressed(event) Keys.onDownPressed: event => Keys.rightPressed(event) Keys.onLeftPressed: event => { @@ -297,9 +292,7 @@ PlasmaCore.ToolTipArea { } function modelIndex(): /*QModelIndex*/ var { - return inPopup - ? tasksModel.makeModelIndex(groupDialog.visualParent.index, index) - : tasksModel.makeModelIndex(index); + return inPopup ? tasksModel.makeModelIndex(groupDialog.visualParent.index, index) : tasksModel.makeModelIndex(index); } function showContextMenu(args: var): void { @@ -353,9 +346,7 @@ PlasmaCore.ToolTipArea { // Will also be called in activateTaskAtIndex(index) function updateMainItemBindings(): void { - if ((mainItem.parentTask === this && mainItem.rootIndex.row === index) - || (tasksRoot.toolTipOpenedByClick === null && !active) - || (tasksRoot.toolTipOpenedByClick !== null && tasksRoot.toolTipOpenedByClick !== this)) { + if ((mainItem.parentTask === this && mainItem.rootIndex.row === index) || (tasksRoot.toolTipOpenedByClick === null && !active) || (tasksRoot.toolTipOpenedByClick !== null && tasksRoot.toolTipOpenedByClick !== this)) { return; } @@ -389,7 +380,9 @@ PlasmaCore.ToolTipArea { target: pulseAudio.item ignoreUnknownSignals: true // Plasma-PA might not be available function onStreamsChanged(): void { - task.updateAudioStreams({delay: true}) + task.updateAudioStreams({ + delay: true + }); } } @@ -403,13 +396,19 @@ PlasmaCore.ToolTipArea { var h, s, l = (max + min) / 2; if (max == min) { h = s = 0; // achromatic - }else { + } else { var d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - switch(max){ - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; } h /= 6; } @@ -424,9 +423,7 @@ PlasmaCore.ToolTipArea { id: colorOverride anchors.fill: frame source: frame - color: plasmoid.configuration.buttonColorizeDominant ? - frame.indicatorColor : - plasmoid.configuration.buttonColorizeCustom + color: plasmoid.configuration.buttonColorizeDominant ? frame.indicatorColor : plasmoid.configuration.buttonColorizeCustom visible: plasmoid.configuration.buttonColorize ? true : false } @@ -448,7 +445,7 @@ PlasmaCore.ToolTipArea { // Repeater { // model: { - + // if(!plasmoid.configuration.indicatorsEnabled) // return 0; // if(task.childCount < plasmoid.configuration.indicatorMinLimit) @@ -461,7 +458,7 @@ PlasmaCore.ToolTipArea { // return Math.min((task.childCount === 0) ? 1 : task.childCount, maxStates); // } // readonly property int maxStates: plasmoid.configuration.indicatorMaxLimit - + // Rectangle{ // id: stateRect // Behavior on height { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } @@ -541,7 +538,7 @@ PlasmaCore.ToolTipArea { // colorCalc = Qt.hsla(colorHSL.h, colorHSL.s*0.5, colorHSL.l*.8, 1) // } // else if(!isFirst && plasmoid.configuration.indicatorStyle === 0 && task.state !== "minimized") {//Metro specific handling - // colorCalc = Qt.darker(colorEval, 1.2) + // colorCalc = Qt.darker(colorEval, 1.2) // } // else { // colorCalc = colorEval @@ -577,7 +574,7 @@ PlasmaCore.ToolTipArea { // } // } // } - + // states:[ // State { // name: "bottom" @@ -681,7 +678,9 @@ PlasmaCore.ToolTipArea { // When we're a launcher, there's no window controls, so we can show all // places without the menu getting super huge. if (model.IsLauncher) { - showContextMenu({showAllPlaces: true}) + showContextMenu({ + showAllPlaces: true + }); } else { showContextMenu(); } @@ -692,7 +691,8 @@ PlasmaCore.ToolTipArea { acceptedButtons: Qt.RightButton acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus gesturePolicy: TapHandler.WithinBounds // Release grab when menu appears - onPressedChanged: if (pressed) contextMenuTimer.start() + onPressedChanged: if (pressed) + contextMenuTimer.start() } Timer { @@ -721,7 +721,7 @@ PlasmaCore.ToolTipArea { if (Plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.NewInstance) { tasksModel.requestNewInstance(modelIndex()); } else if (Plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.Close) { - tasksRoot.taskClosedWithMouseMiddleButton = model.WinIdList.slice() + tasksRoot.taskClosedWithMouseMiddleButton = model.WinIdList.slice(); tasksModel.requestClose(modelIndex()); } else if (Plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.ToggleMinimized) { tasksModel.requestToggleMinimized(modelIndex()); @@ -785,7 +785,7 @@ PlasmaCore.ToolTipArea { while (item.parent) { item = item.parent; if (item.appletRequestsInhibitDnD !== undefined) { - item.appletRequestsInhibitDnD = value + item.appletRequestsInhibitDnD = value; } } } @@ -803,7 +803,7 @@ PlasmaCore.ToolTipArea { dragHelper.Drag.mimeData = { "text/x-orgkdeplasmataskmanager_taskurl": backend.tryDecodeApplicationsUrl(model.LauncherUrlWithoutIcon).toString(), [model.MimeType]: model.MimeData, - "application/x-orgkdeplasmataskmanager_taskbuttonitem": model.MimeData, + "application/x-orgkdeplasmataskmanager_taskbuttonitem": model.MimeData }; dragHelper.Drag.active = dragHandler.active; }); @@ -837,12 +837,10 @@ PlasmaCore.ToolTipArea { } width: task.inPopup ? Math.max(Kirigami.Units.iconSizes.sizeForLabels, Kirigami.Units.iconSizes.medium) : Math.min(task.parent?.minimumWidth ?? 0, task.height) - height: task.inPopup ? width : (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - - adjustMargin(false, parent.height, taskFrame.margins.bottom)) + height: task.inPopup ? width : (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - adjustMargin(false, parent.height, taskFrame.margins.bottom)) asynchronous: true - active: height >= Kirigami.Units.iconSizes.small - && task.smartLauncherItem && task.smartLauncherItem.countVisible + active: height >= Kirigami.Units.iconSizes.small && task.smartLauncherItem && task.smartLauncherItem.countVisible source: "TaskBadgeOverlay.qml" function adjustMargin(isVertical: bool, size: real, margin: real): real { @@ -861,14 +859,14 @@ PlasmaCore.ToolTipArea { Kirigami.Icon { id: icon - property int growSize: active ? 20 : 0 + property int growSize: active ? plasmoid.configuration.iconZoomFactor : 0 width: parent.width + growSize height: parent.height + growSize anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter Behavior on growSize { NumberAnimation { - duration: 250 + duration: plasmoid.configuration.iconZoomDuration easing.type: Easing.InOutQuad } } @@ -895,9 +893,7 @@ PlasmaCore.ToolTipArea { PropertyChanges { target: iconBox anchors.leftMargin: 0 - width: Math.min(task.parent.minimumWidth, tasks.height) - - adjustMargin(true, task.width, taskFrame.margins.left) - - adjustMargin(true, task.width, taskFrame.margins.right) + width: Math.min(task.parent.minimumWidth, tasks.height) - adjustMargin(true, task.width, taskFrame.margins.left) - adjustMargin(true, task.width, taskFrame.margins.right) } } ] @@ -914,8 +910,7 @@ PlasmaCore.ToolTipArea { PlasmaComponents3.Label { id: label - visible: (inPopup || !iconsOnly && !model.IsLauncher - && (parent.width - iconBox.height - Kirigami.Units.smallSpacing) >= LayoutMetrics.spaceRequiredToShowText()) + visible: (inPopup || !iconsOnly && !model.IsLauncher && (parent.width - iconBox.height - Kirigami.Units.smallSpacing) >= LayoutMetrics.spaceRequiredToShowText()) anchors { fill: parent @@ -954,7 +949,7 @@ PlasmaCore.ToolTipArea { target: frame basePrefix: "" } - PropertyChanges { + PropertyChanges { target: colorOverride visible: false } @@ -968,7 +963,7 @@ PlasmaCore.ToolTipArea { basePrefix: "attention" visible: (plasmoid.configuration.buttonColorize && !frame.isHovered) || !plasmoid.configuration.buttonColorize } - PropertyChanges { + PropertyChanges { target: colorOverride visible: (plasmoid.configuration.buttonColorize && frame.isHovered) } @@ -982,11 +977,11 @@ PlasmaCore.ToolTipArea { basePrefix: "minimized" visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? false : true } - PropertyChanges { + PropertyChanges { target: colorOverride visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? true : false } - PropertyChanges{ + PropertyChanges { target: indicator visible: plasmoid.configuration.disableInactiveIndicators ? false : true } @@ -1000,11 +995,11 @@ PlasmaCore.ToolTipArea { basePrefix: "minimized" visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true } - PropertyChanges { + PropertyChanges { target: colorOverride visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true } - PropertyChanges{ + PropertyChanges { target: indicator visible: plasmoid.configuration.disableInactiveIndicators ? false : true } @@ -1017,11 +1012,11 @@ PlasmaCore.ToolTipArea { target: frame basePrefix: "focus" } - PropertyChanges { + PropertyChanges { target: colorOverride visible: plasmoid.configuration.buttonColorize ? true : false } - PropertyChanges{ + PropertyChanges { target: indicator visible: plasmoid.configuration.indicatorsEnabled ? true : false } @@ -1029,15 +1024,15 @@ PlasmaCore.ToolTipArea { State { name: "inactive" when: model.IsActive === false && !frame.isHovered && !plasmoid.configuration.disableButtonInactiveSvg - PropertyChanges { + PropertyChanges { target: colorOverride visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? true : false } - PropertyChanges { + PropertyChanges { target: frame visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? false : true } - PropertyChanges{ + PropertyChanges { target: indicator visible: plasmoid.configuration.disableInactiveIndicators ? false : true } @@ -1045,15 +1040,15 @@ PlasmaCore.ToolTipArea { State { name: "inactiveNoDecoration" when: (model.IsActive === false && !frame.isHovered) && plasmoid.configuration.disableButtonInactiveSvg - PropertyChanges { + PropertyChanges { target: colorOverride visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true } - PropertyChanges { + PropertyChanges { target: frame visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true } - PropertyChanges{ + PropertyChanges { target: indicator visible: plasmoid.configuration.disableInactiveIndicators ? false : true } @@ -1061,15 +1056,15 @@ PlasmaCore.ToolTipArea { State { name: "hover" when: frame.isHovered - PropertyChanges { + PropertyChanges { target: colorOverride visible: plasmoid.configuration.buttonColorize ? true : false } - PropertyChanges { + PropertyChanges { target: frame visible: plasmoid.configuration.buttonColorize ? false : true } - PropertyChanges{ + PropertyChanges { target: indicator visible: plasmoid.configuration.disableInactiveIndicators ? false : true } @@ -1078,12 +1073,14 @@ PlasmaCore.ToolTipArea { Component.onCompleted: { if (!inPopup && model.IsWindow) { - if (plasmoid.configuration.groupIconEnabled){ + if (plasmoid.configuration.groupIconEnabled) { const component = Qt.createComponent("GroupExpanderOverlay.qml"); component.createObject(task); component.destroy(); } - updateAudioStreams({delay: false}); + updateAudioStreams({ + delay: false + }); } if (!inPopup && !model.IsWindow) { diff --git a/package/contents/ui/ToolTipDelegate.qml b/package/contents/ui/ToolTipDelegate.qml index 894a310c..17671ead 100644 --- a/package/contents/ui/ToolTipDelegate.qml +++ b/package/contents/ui/ToolTipDelegate.qml @@ -24,16 +24,16 @@ Loader { id: toolTipDelegate property Task parentTask - property /*QModelIndex*/var rootIndex + property /*QModelIndex*/ var rootIndex property string appName property int pidParent property bool isGroup - property /*list where WId = int|string*/ var windows: [] + property /*list where WId = int|string*/ var windows: [] readonly property bool isWin: windows.length > 0 - property /*QIcon*/ var icon + property /*QIcon*/ var icon property url launcherUrl property bool isLauncher property bool isMinimized @@ -41,7 +41,7 @@ Loader { // Needed for generateSubtext() property string display property string genericName - property /*list*/ var virtualDesktops: [] // Can't use list because of QTBUG-127600 + property /*list*/ var virtualDesktops: [] // Can't use list because of QTBUG-127600 property bool isOnAllVirtualDesktops property list activities: [] diff --git a/package/contents/ui/ToolTipInstance.qml b/package/contents/ui/ToolTipInstance.qml index 8fcb23d5..6d040deb 100644 --- a/package/contents/ui/ToolTipInstance.qml +++ b/package/contents/ui/ToolTipInstance.qml @@ -25,12 +25,12 @@ ColumnLayout { id: root required property int index - required property /*QModelIndex*/ var submodelIndex + required property /*QModelIndex*/ var submodelIndex required property int appPid required property string display required property bool isMinimized required property bool isOnAllVirtualDesktops - required property /*list*/ var virtualDesktops // Can't use list because of QTBUG-127600 + required property /*list*/ var virtualDesktops // Can't use list because of QTBUG-127600 required property list activities // HACK: Avoid blank space in the tooltip after closing a window @@ -157,13 +157,18 @@ ColumnLayout { id: thumbnailSourceItem Layout.fillWidth: true - Layout.preferredHeight: Kirigami.Units.gridUnit * 8 + Layout.preferredHeight: Math.min(Kirigami.Units.gridUnit * 12, Screen.desktopAvailableHeight * 0.4) + + // Add maximum width constraint to help with portrait windows + Layout.maximumWidth: Math.min(Layout.preferredHeight * 1.77, Screen.desktopAvailableWidth * 0.3) + + // Center in available space + Layout.alignment: Qt.AlignCenter clip: true visible: toolTipDelegate.isWin - readonly property /*undefined|WId where WId = int|string*/ var winId: - toolTipDelegate.isWin ? toolTipDelegate.windows[root.index] : undefined + readonly property /*undefined|WId where WId = int|string*/ var winId: toolTipDelegate.isWin ? toolTipDelegate.windows[root.index] : undefined // There's no PlasmaComponents3 version PlasmaExtras.Highlight { @@ -175,10 +180,7 @@ ColumnLayout { Loader { id: thumbnailLoader - active: !toolTipDelegate.isLauncher - && !albumArtImage.visible - && (Number.isInteger(thumbnailSourceItem.winId) || pipeWireLoader.item && !pipeWireLoader.item.hasThumbnail) - && root.index !== -1 // Avoid loading when the instance is going to be destroyed + active: !toolTipDelegate.isLauncher && !albumArtImage.visible && (Number.isInteger(thumbnailSourceItem.winId) || pipeWireLoader.item && !pipeWireLoader.item.hasThumbnail) && root.index !== -1 // Avoid loading when the instance is going to be destroyed asynchronous: true visible: active anchors.fill: hoverHandler @@ -223,7 +225,6 @@ ColumnLayout { to: 1 } } - } } } @@ -287,8 +288,7 @@ ColumnLayout { // if this is a group tooltip, we check if window title and track match, to allow distinguishing the different windows // if this app is a browser, we also check the title, so album art is not shown when the user is on some other tab // in all other cases we can safely show the album art without checking the title - readonly property bool available: (status === Image.Ready || status === Image.Loading) - && (!(toolTipDelegate.isGroup || backend.applicationCategories(launcherUrl).includes("WebBrowser")) || root.titleIncludesTrack) + readonly property bool available: (status === Image.Ready || status === Image.Loading) && (!(toolTipDelegate.isGroup || backend.applicationCategories(launcherUrl).includes("WebBrowser")) || root.titleIncludesTrack) anchors.fill: hoverHandler // Indent by one pixel to make sure we never cover up the entire highlight @@ -330,11 +330,7 @@ ColumnLayout { // Volume controls Loader { - active: toolTipDelegate.parentTask !== null - && pulseAudio.item !== null - && toolTipDelegate.parentTask.audioIndicatorsEnabled - && toolTipDelegate.parentTask.hasAudioStream - && root.index !== -1 // Avoid loading when the instance is going to be destroyed + active: toolTipDelegate.parentTask !== null && pulseAudio.item !== null && toolTipDelegate.parentTask.audioIndicatorsEnabled && toolTipDelegate.parentTask.hasAudioStream && root.index !== -1 // Avoid loading when the instance is going to be destroyed asynchronous: true visible: active Layout.fillWidth: true @@ -342,25 +338,24 @@ ColumnLayout { Layout.leftMargin: header.Layout.margins Layout.rightMargin: header.Layout.margins sourceComponent: RowLayout { - PlasmaComponents3.ToolButton { // Mute button + PlasmaComponents3.ToolButton { + // Mute button icon.width: Kirigami.Units.iconSizes.small icon.height: Kirigami.Units.iconSizes.small icon.name: if (checked) { - "audio-volume-muted" + "audio-volume-muted"; } else if (slider.displayValue <= 25) { - "audio-volume-low" + "audio-volume-low"; } else if (slider.displayValue <= 75) { - "audio-volume-medium" + "audio-volume-medium"; } else { - "audio-volume-high" + "audio-volume-high"; } onClicked: toolTipDelegate.parentTask.toggleMuted() checked: toolTipDelegate.parentTask.muted PlasmaComponents3.ToolTip { - text: parent.checked - ? i18nc("button to unmute app", "Unmute %1", toolTipDelegate.parentTask.appName) - : i18nc("button to mute app", "Mute %1", toolTipDelegate.parentTask.appName) + text: parent.checked ? i18nc("button to unmute app", "Unmute %1", toolTipDelegate.parentTask.appName) : i18nc("button to mute app", "Mute %1", toolTipDelegate.parentTask.appName) } } @@ -368,8 +363,7 @@ ColumnLayout { id: slider readonly property int displayValue: Math.round(value / to * 100) - readonly property int loudestVolume: toolTipDelegate.parentTask.audioStreams - .reduce((loudestVolume, stream) => Math.max(loudestVolume, stream.volume), 0) + readonly property int loudestVolume: toolTipDelegate.parentTask.audioStreams.reduce((loudestVolume, stream) => Math.max(loudestVolume, stream.volume), 0) Layout.fillWidth: true from: pulseAudio.item.minimalVolume @@ -380,17 +374,19 @@ ColumnLayout { Accessible.name: i18nc("Accessibility data on volume slider", "Adjust volume for %1", toolTipDelegate.parentTask.appName) - onMoved: toolTipDelegate.parentTask.audioStreams.forEach((stream) => { - let v = Math.max(from, value) - if (v > 0 && loudestVolume > 0) { // prevent divide by 0 + onMoved: toolTipDelegate.parentTask.audioStreams.forEach(stream => { + let v = Math.max(from, value); + if (v > 0 && loudestVolume > 0) { + // prevent divide by 0 // adjust volume relative to the loudest stream - v = Math.min(Math.round(stream.volume / loudestVolume * v), to) + v = Math.min(Math.round(stream.volume / loudestVolume * v), to); } - stream.model.Volume = v - stream.model.Muted = v === 0 + stream.model.Volume = v; + stream.model.Muted = v === 0; }) } - PlasmaComponents3.Label { // percent label + PlasmaComponents3.Label { + // percent label Layout.alignment: Qt.AlignHCenter Layout.minimumWidth: percentMetrics.advanceWidth horizontalAlignment: Qt.AlignRight @@ -414,30 +410,23 @@ ColumnLayout { return virtualDesktopInfo.desktopNames[index]; }); - subTextEntries.push(i18nc("Comma-separated list of desktops", "On %1", - virtualDesktopNameList.join(", "))); + subTextEntries.push(i18nc("Comma-separated list of desktops", "On %1", virtualDesktopNameList.join(", "))); } else if (isOnAllVirtualDesktops) { subTextEntries.push(i18nc("Comma-separated list of desktops", "Pinned to all desktops")); } } if (activities.length === 0 && activityInfo.numberOfRunningActivities > 1) { - subTextEntries.push(i18nc("Which virtual desktop a window is currently on", - "Available on all activities")); + subTextEntries.push(i18nc("Which virtual desktop a window is currently on", "Available on all activities")); } else if (activities.length > 0) { - const activityNames = activities - .filter(activity => activity !== activityInfo.currentActivity) - .map(activity => activityInfo.activityName(activity)) - .filter(activityName => activityName !== ""); + const activityNames = activities.filter(activity => activity !== activityInfo.currentActivity).map(activity => activityInfo.activityName(activity)).filter(activityName => activityName !== ""); if (Plasmoid.configuration.showOnlyCurrentActivity) { if (activityNames.length > 0) { - subTextEntries.push(i18nc("Activities a window is currently on (apart from the current one)", - "Also available on %1", activityNames.join(", "))); + subTextEntries.push(i18nc("Activities a window is currently on (apart from the current one)", "Also available on %1", activityNames.join(", "))); } } else if (activityNames.length > 0) { - subTextEntries.push(i18nc("Which activities a window is currently on", - "Available on %1", activityNames.join(", "))); + subTextEntries.push(i18nc("Which activities a window is currently on", "Available on %1", activityNames.join(", "))); } } diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 61abab0d..a08c1d24 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -6,6 +6,7 @@ import QtQuick import QtQuick.Layouts +import QtQuick.Controls import org.kde.plasma.plasmoid import org.kde.plasma.components as PlasmaComponents3 @@ -42,7 +43,7 @@ PlasmoidItem { readonly property Component pulseAudioComponent: Qt.createComponent("PulseAudio.qml") property bool needLayoutRefresh: false - property /*list where WId = int|string*/ var taskClosedWithMouseMiddleButton: [] + property /*list where WId = int|string*/ var taskClosedWithMouseMiddleButton: [] property alias taskList: taskList preferredRepresentation: fullRepresentation @@ -70,7 +71,7 @@ PlasmoidItem { return !vertical ? 0 : LayoutMetrics.preferredMinHeight(); } -//BEGIN TODO: this is not precise enough: launchers are smaller than full tasks + //BEGIN TODO: this is not precise enough: launchers are smaller than full tasks Layout.preferredWidth: { if (shouldShrinkToZero) { return 0.01; @@ -78,18 +79,18 @@ PlasmoidItem { if (vertical) { return Kirigami.Units.gridUnit * 10; } - return taskList.Layout.maximumWidth + return taskList.Layout.maximumWidth; } Layout.preferredHeight: { if (shouldShrinkToZero) { return 0.01; } if (vertical) { - return taskList.Layout.maximumHeight + return taskList.Layout.maximumHeight; } return Kirigami.Units.gridUnit * 2; } -//END TODO + //END TODO property Item dragSource @@ -111,8 +112,7 @@ PlasmoidItem { const task = taskItems[i]; if (!task.model.IsLauncher && !task.model.IsStartup) { - tasksModel.requestPublishDelegateGeometry(tasksModel.makeModelIndex(task.index), - backend.globalRect(task), task); + tasksModel.requestPublishDelegateGeometry(tasksModel.makeModelIndex(task.index), backend.globalRect(task), task); } } } @@ -153,8 +153,7 @@ PlasmoidItem { sortMode: sortModeEnumValue(Plasmoid.configuration.sortingStrategy) launchInPlace: tasks.iconsOnly && Plasmoid.configuration.sortingStrategy === 1 separateLaunchers: { - if (!tasks.iconsOnly && !Plasmoid.configuration.separateLaunchers - && Plasmoid.configuration.sortingStrategy === 1) { + if (!tasks.iconsOnly && !Plasmoid.configuration.separateLaunchers && Plasmoid.configuration.sortingStrategy === 1) { return false; } @@ -163,8 +162,7 @@ PlasmoidItem { groupMode: groupModeEnumValue(Plasmoid.configuration.groupingStrategy) groupInline: !Plasmoid.configuration.groupPopups && !tasks.iconsOnly - groupingWindowTasksThreshold: (Plasmoid.configuration.onlyGroupWhenFull && !tasks.iconsOnly - ? LayoutMetrics.optimumCapacity(width, height) + 1 : -1) + groupingWindowTasksThreshold: (Plasmoid.configuration.onlyGroupWhenFull && !tasks.iconsOnly ? LayoutMetrics.optimumCapacity(width, height) + 1 : -1) onLauncherListChanged: { Plasmoid.configuration.launchers = launcherList; @@ -302,8 +300,7 @@ PlasmoidItem { Binding { target: Plasmoid property: "status" - value: (tasksModel.anyTaskDemandsAttention && Plasmoid.configuration.unhideOnAttention - ? PlasmaCore.Types.NeedsAttentionStatus : PlasmaCore.Types.PassiveStatus) + value: (tasksModel.anyTaskDemandsAttention && Plasmoid.configuration.unhideOnAttention ? PlasmaCore.Types.NeedsAttentionStatus : PlasmaCore.Types.PassiveStatus) restoreMode: Binding.RestoreBinding } @@ -311,7 +308,7 @@ PlasmoidItem { target: Plasmoid.configuration function onLaunchersChanged(): void { - tasksModel.launcherList = Plasmoid.configuration.launchers + tasksModel.launcherList = Plasmoid.configuration.launchers; } function onGroupingAppIdBlacklistChanged(): void { tasksModel.groupingAppIdBlacklist = Plasmoid.configuration.groupingAppIdBlacklist; @@ -426,20 +423,20 @@ PlasmoidItem { Layout.maximumWidth: { const totalMaxWidth = children.reduce((accumulator, child) => { - if (!isFinite(child.Layout.maximumWidth)) { - return accumulator; - } - return accumulator + child.Layout.maximumWidth - }, 0); + if (!isFinite(child.Layout.maximumWidth)) { + return accumulator; + } + return accumulator + child.Layout.maximumWidth; + }, 0); return Math.round(totalMaxWidth / widthOccupation); } Layout.maximumHeight: { const totalMaxHeight = children.reduce((accumulator, child) => { - if (!isFinite(child.Layout.maximumHeight)) { - return accumulator; - } - return accumulator + child.Layout.maximumHeight - }, 0); + if (!isFinite(child.Layout.maximumHeight)) { + return accumulator; + } + return accumulator + child.Layout.maximumHeight; + }, 0); return Math.round(totalMaxHeight / heightOccupation); } width: { @@ -465,9 +462,9 @@ PlasmoidItem { flow: { if (tasks.vertical) { - return Plasmoid.configuration.forceStripes ? Grid.LeftToRight : Grid.TopToBottom + return Plasmoid.configuration.forceStripes ? Grid.LeftToRight : Grid.TopToBottom; } - return Plasmoid.configuration.forceStripes ? Grid.TopToBottom : Grid.LeftToRight + return Plasmoid.configuration.forceStripes ? Grid.TopToBottom : Grid.LeftToRight; } onAnimatingChanged: { @@ -483,9 +480,7 @@ PlasmoidItem { tasksRoot: tasks } onItemRemoved: (index, item) => { - if (tasks.containsMouse && index !== taskRepeater.count && - item.model.WinIdList.length > 0 && - taskClosedWithMouseMiddleButton.includes(item.winIdList[0])) { + if (tasks.containsMouse && index !== taskRepeater.count && item.model.WinIdList.length > 0 && taskClosedWithMouseMiddleButton.includes(item.winIdList[0])) { needLayoutRefresh = true; } taskClosedWithMouseMiddleButton = []; @@ -534,7 +529,7 @@ PlasmoidItem { visualParent: rootTask, modelIndex, mpris2Source, - backend, + backend }); return contextMenuComponent.createObject(rootTask, initialArgs); } diff --git a/update.sh b/update.sh index ec956000..f15926bf 100755 --- a/update.sh +++ b/update.sh @@ -1,7 +1,7 @@ #!/bin/sh SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) sh $SCRIPT_DIR/build.sh -kpackagetool5 -u $SCRIPT_DIR/release/FancyTasks.tar.gz +kpackagetool6 -u $SCRIPT_DIR/release/FancyTasks.tar.gz killall plasmashell kstart5 plasmashell -sh ./iconinstall.sh \ No newline at end of file +sh ./iconinstall.sh From d64d242b83bc21eb4667d2d7c111a110aee9d9b8 Mon Sep 17 00:00:00 2001 From: Naman Rajhans Date: Wed, 26 Mar 2025 00:09:19 +0530 Subject: [PATCH 123/141] Update README.MD --- README.MD | 1 + 1 file changed, 1 insertion(+) diff --git a/README.MD b/README.MD index 2877daa9..c8e32bba 100644 --- a/README.MD +++ b/README.MD @@ -9,6 +9,7 @@ You can reach me at ideas@alexankitty.com, by putting an issue on this github, b # FancyTasks+ ![Fancy Tasks Icon](https://github.com/alexankitty/FancyTasks/blob/main/package/FancyTasks.png?raw=true) + This is a fork of [FancyTasks](https://github.com//alexankitty/FancyTasks) and [Luis Bocanegra's plasma6,hover-zoom branch](https://github.com/luisbocanegra/FancyTasks) with additional features: - Configurable icon zoom on hover - With better padding on hover previews From 47d90f745caff7f5269c3728be8c52d1802141a5 Mon Sep 17 00:00:00 2001 From: Naman Rajhans Date: Wed, 26 Mar 2025 00:10:12 +0530 Subject: [PATCH 124/141] Update README.MD --- README.MD | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/README.MD b/README.MD index c8e32bba..0d712a5e 100644 --- a/README.MD +++ b/README.MD @@ -1,11 +1,3 @@ -# Notice -Development of this project has more or less resumed. Help is always wanted and appreciated, however. -I'm struggling with burn out at the moment. I'm hoping to return to the project soon but I need to get that under control. -Currently I'm almost done with the overhauls of indicators which should finalize the Plasma 5 version of this plasmoid. Once that is completed, Plasma 5 will be split into its own fork and the main branch will be for Plasma 6. Any new features and code improvements the plasma 6 widget offers will be back ported in. I'm also in the process of modularizing the FancyTasks additions in order to make development simpler. - -# Contact -You can reach me at ideas@alexankitty.com, by putting an issue on this github, by commenting on the [AUR package](https://aur.archlinux.org/packages/fancytasks), by commenting on the kde-look page, or on the [FancyTasks KDE Reddit community](https://www.reddit.com/r/fancytaskskde/). - # FancyTasks+ ![Fancy Tasks Icon](https://github.com/alexankitty/FancyTasks/blob/main/package/FancyTasks.png?raw=true) @@ -14,6 +6,10 @@ This is a fork of [FancyTasks](https://github.com//alexankitty/FancyTasks) and [ - Configurable icon zoom on hover - With better padding on hover previews - With a option in configuration which allows you to choose apps to pin and rearrange them + +# Contact +You can reach me at ideas@alexankitty.com, by putting an issue on this github, by commenting on the [AUR package](https://aur.archlinux.org/packages/fancytasks), by commenting on the kde-look page, or on the [FancyTasks KDE Reddit community](https://www.reddit.com/r/fancytaskskde/). + ## Installing If your distro does not include kirigami2, install it now. It's required for the settings, and used for the dominant icon color effect. Python3 is required for installing. From a2f5f77de560d582d13f58b4ec5a72603a8314dc Mon Sep 17 00:00:00 2001 From: SushiTrash Date: Mon, 30 Jun 2025 21:17:55 +0530 Subject: [PATCH 125/141] fixed for plasma 6.4 --- package/contents/ui/Task.qml | 2 +- package/contents/ui/main.qml | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 9873528e..77a712db 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -206,7 +206,7 @@ PlasmaCore.ToolTipArea { onHighlightedChanged: { // ensure it doesn't get stuck with a window highlighted - backend.cancelHighlightWindows(); + tasksRoot.cancelHighlightWindows(); } onPidChanged: updateAudioStreams({ diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index a08c1d24..2b2a8bf1 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -98,6 +98,24 @@ PlasmoidItem { signal windowsHovered(var winIds, bool hovered) signal activateWindowView(var winIds) + onWindowsHovered: (winIds, hovered) => { + if (!Plasmoid.configuration.highlightWindows) { + return; + } + DBus.SessionBus.asyncCall({ + service: "org.kde.KWin.HighlightWindow", + path: "/org/kde/KWin/HighlightWindow", + iface: "org.kde.KWin.HighlightWindow", + member: "highlightWindows", + arguments: [hovered ? winIds : []], + signature: "(as)" + }); + } + + function cancelHighlightWindows(): DBus.DBusPendingReply { + return DBus.SessionBus.asyncCall({service: "org.kde.KWin.HighlightWindow", path: "/org/kde/KWin/HighlightWindow", iface: "org.kde.KWin.HighlightWindow", member: "highlightWindows", arguments: [[]], signature: "(as)"}); + } + onDragSourceChanged: { if (dragSource === null) { tasksModel.syncLaunchers(); @@ -214,7 +232,6 @@ PlasmoidItem { readonly property TaskManagerApplet.Backend backend: TaskManagerApplet.Backend { id: backend - highlightWindows: Plasmoid.configuration.highlightWindows onAddLauncher: { tasks.addLauncher(url); @@ -549,7 +566,7 @@ PlasmoidItem { Component.onCompleted: { TaskTools.taskManagerInstanceCount += 1; requestLayout.connect(iconGeometryTimer.restart); - windowsHovered.connect(backend.windowsHovered); + windowsHovered.connect(tasks.windowsHovered); activateWindowView.connect(backend.activateWindowView); } From 375c7dd6fc3d96066a182d87c46f12016d445c21 Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Sun, 21 Dec 2025 23:41:50 +0200 Subject: [PATCH 126/141] First fix for Plasma 6.5 compatible --- README.MD | 2 ++ build.sh | 0 iconinstall.sh | 0 package/contents/ui/ConfigIndicators.qml | 6 ++--- package/contents/ui/ConfigPinnedApps.qml | 1 - package/contents/ui/PipeWireThumbnail.qml | 7 ++--- package/contents/ui/code/layout.js | 4 +-- package/contents/ui/main.qml | 33 +++++++++++++---------- package/translate/build | 8 ++++-- testing.sh | 2 +- update.sh | 11 ++++++-- 11 files changed, 46 insertions(+), 28 deletions(-) mode change 100644 => 100755 build.sh mode change 100644 => 100755 iconinstall.sh diff --git a/README.MD b/README.MD index 0d712a5e..46a62c07 100644 --- a/README.MD +++ b/README.MD @@ -14,6 +14,8 @@ You can reach me at ideas@alexankitty.com, by putting an issue on this github, b If your distro does not include kirigami2, install it now. It's required for the settings, and used for the dominant icon color effect. Python3 is required for installing. +**Note for Plasma 6:** This plasmoid requires `Qt5Compat.GraphicalEffects` (often packaged as `qt6-5compat` or similar) to be installed on your system. + 1. Clone this repository with the following command `git clone https://github.com/alexankitty/FancyTasks` 2. CD into the folder and run the script `install.sh`, you may need to chmod +x or prepend your shell before the script in order to run it 3. Right click your panel, click add widgets and search for fancy tasks. diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 diff --git a/iconinstall.sh b/iconinstall.sh old mode 100644 new mode 100755 diff --git a/package/contents/ui/ConfigIndicators.qml b/package/contents/ui/ConfigIndicators.qml index ccb45612..98f833d1 100644 --- a/package/contents/ui/ConfigIndicators.qml +++ b/package/contents/ui/ConfigIndicators.qml @@ -1,6 +1,6 @@ -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts import org.kde.kcmutils as KCMUtils import org.kde.kirigami as Kirigami diff --git a/package/contents/ui/ConfigPinnedApps.qml b/package/contents/ui/ConfigPinnedApps.qml index 3f490820..f714ec15 100644 --- a/package/contents/ui/ConfigPinnedApps.qml +++ b/package/contents/ui/ConfigPinnedApps.qml @@ -1,7 +1,6 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts -import QtQuick.Dialogs import org.kde.kcmutils as KCMUtils import org.kde.kirigami as Kirigami diff --git a/package/contents/ui/PipeWireThumbnail.qml b/package/contents/ui/PipeWireThumbnail.qml index ec79b5e1..d719a440 100644 --- a/package/contents/ui/PipeWireThumbnail.qml +++ b/package/contents/ui/PipeWireThumbnail.qml @@ -20,11 +20,12 @@ PipeWire.PipeWireSourceItem { width: parent.width height: { // If we have valid source dimensions, calculate proper height - if (sourceSize.width > 0 && sourceSize.height > 0) { - return Math.min(parent.height, parent.width * (sourceSize.height / sourceSize.width)); + if (implicitWidth > 0 && implicitHeight > 0) { + return Math.min(parent.height, parent.width * (implicitHeight / implicitWidth)); } else { // Fallback to a reasonable default - return Math.min(parent.height, parent.width * 0.75); // 4:3 aspect ratio as fallback + return Math.min(parent.height, parent.width * 0.75); + // 4:3 aspect ratio as fallback } } diff --git a/package/contents/ui/code/layout.js b/package/contents/ui/code/layout.js index 4969fd93..b51778b0 100644 --- a/package/contents/ui/code/layout.js +++ b/package/contents/ui/code/layout.js @@ -4,8 +4,8 @@ SPDX-License-Identifier: GPL-2.0-or-later */ -.import org.kde.plasma.core 2.0 as PlasmaCore -.import org.kde.kirigami 2.19 as Kirigami +.import org.kde.plasma.core as PlasmaCore +.import org.kde.kirigami as Kirigami const iconMargin = Math.round(Kirigami.Units.smallSpacing / 4); const labelMargin = Kirigami.Units.smallSpacing; diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 2b2a8bf1..ed6370e1 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -57,18 +57,23 @@ PlasmoidItem { } Layout.fillWidth: vertical ? true : Plasmoid.configuration.fill - Layout.fillHeight: !vertical ? true : Plasmoid.configuration.fill + Layout.fillHeight: !vertical ? + true : Plasmoid.configuration.fill Layout.minimumWidth: { if (shouldShrinkToZero) { - return Kirigami.Units.gridUnit; // For edit mode + return Kirigami.Units.gridUnit; + // For edit mode } - return vertical ? 0 : LayoutMetrics.preferredMinWidth(); + return vertical ? + 0 : LayoutMetrics.preferredMinWidth(); } Layout.minimumHeight: { if (shouldShrinkToZero) { - return Kirigami.Units.gridUnit; // For edit mode + return Kirigami.Units.gridUnit; + // For edit mode } - return !vertical ? 0 : LayoutMetrics.preferredMinHeight(); + return !vertical ? + 0 : LayoutMetrics.preferredMinHeight(); } //BEGIN TODO: this is not precise enough: launchers are smaller than full tasks @@ -128,7 +133,6 @@ PlasmoidItem { } for (let i = 0; i < taskItems.length - 1; ++i) { const task = taskItems[i]; - if (!task.model.IsLauncher && !task.model.IsStartup) { tasksModel.requestPublishDelegateGeometry(tasksModel.makeModelIndex(task.index), backend.globalRect(task), task); } @@ -144,10 +148,8 @@ PlasmoidItem { } let startupsWithLaunchers = 0; - for (let i = 0; i < taskRepeater.count; ++i) { const item = taskRepeater.itemAt(i); - // During destruction required properties such as item.model can go null for a while, // so in paths that can trigger on those moments, they need to be guarded if (item?.model?.IsStartup && item.model.HasLauncher) { @@ -167,7 +169,8 @@ PlasmoidItem { filterByActivity: Plasmoid.configuration.showOnlyCurrentActivity filterNotMinimized: Plasmoid.configuration.showOnlyMinimized - hideActivatedLaunchers: tasks.iconsOnly || Plasmoid.configuration.hideLauncherOnStart + hideActivatedLaunchers: tasks.iconsOnly || + Plasmoid.configuration.hideLauncherOnStart sortMode: sortModeEnumValue(Plasmoid.configuration.sortingStrategy) launchInPlace: tasks.iconsOnly && Plasmoid.configuration.sortingStrategy === 1 separateLaunchers: { @@ -294,6 +297,7 @@ PlasmoidItem { TaskManager.ActivityInfo { id: activityInfo + readonly property string nullUuid: "00000000-0000-0000-0000-000000000000" } @@ -345,7 +349,8 @@ PlasmoidItem { id: dragHelper Drag.dragType: Drag.Automatic - Drag.supportedActions: Qt.CopyAction | Qt.MoveAction | Qt.LinkAction + Drag.supportedActions: Qt.CopyAction | Qt.MoveAction | + Qt.LinkAction Drag.onDragFinished: dropAction => { tasks.dragSource = null; } @@ -479,9 +484,11 @@ PlasmoidItem { flow: { if (tasks.vertical) { - return Plasmoid.configuration.forceStripes ? Grid.LeftToRight : Grid.TopToBottom; + return Plasmoid.configuration.forceStripes ? + Grid.LeftToRight : Grid.TopToBottom; } - return Plasmoid.configuration.forceStripes ? Grid.TopToBottom : Grid.LeftToRight; + return Plasmoid.configuration.forceStripes ? + Grid.TopToBottom : Grid.LeftToRight; } onAnimatingChanged: { @@ -566,8 +573,6 @@ PlasmoidItem { Component.onCompleted: { TaskTools.taskManagerInstanceCount += 1; requestLayout.connect(iconGeometryTimer.restart); - windowsHovered.connect(tasks.windowsHovered); - activateWindowView.connect(backend.activateWindowView); } Component.onDestruction: { diff --git a/package/translate/build b/package/translate/build index 93c29fa9..18d98106 100644 --- a/package/translate/build +++ b/package/translate/build @@ -45,8 +45,12 @@ echo "[build] Done building messages" if [ "$1" = "--restartplasma" ]; then echo "[build] Restarting plasmashell" - killall plasmashell - kstart5 plasmashell + if systemctl --user is-active --quiet plasma-plasmashell.service; then + systemctl --user restart plasma-plasmashell.service + else + killall plasmashell + plasmashell > /dev/null 2>&1 & + fi echo "[build] Done restarting plasmashell" else echo "[build] (re)install the plasmoid and restart plasmashell to test." diff --git a/testing.sh b/testing.sh index e2b55fc8..340b2ff2 100755 --- a/testing.sh +++ b/testing.sh @@ -1,5 +1,5 @@ #!/bin/sh SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) sh $SCRIPT_DIR/build.sh -kpackagetool5 -u $SCRIPT_DIR/release/FancyTasks.tar.gz +kpackagetool6 -u $SCRIPT_DIR/release/FancyTasks.tar.gz QML_DISABLE_DISK_CACHE=true plasmawindowed alexankitty.fancytasks \ No newline at end of file diff --git a/update.sh b/update.sh index f15926bf..a6808410 100755 --- a/update.sh +++ b/update.sh @@ -2,6 +2,13 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) sh $SCRIPT_DIR/build.sh kpackagetool6 -u $SCRIPT_DIR/release/FancyTasks.tar.gz -killall plasmashell -kstart5 plasmashell + +# Restart plasmashell +if systemctl --user is-active --quiet plasma-plasmashell.service; then + systemctl --user restart plasma-plasmashell.service +else + killall plasmashell + plasmashell > /dev/null 2>&1 & +fi + sh ./iconinstall.sh From ebb89ea9bb6ece38e5bfa6ca9356246b27b0f9e5 Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Mon, 22 Dec 2025 14:31:16 +0200 Subject: [PATCH 127/141] Fix windows close throw thumbnails middle click --- package/contents/ui/ToolTipInstance.qml | 9 ++++---- .../contents/ui/ToolTipWindowMouseArea.qml | 23 +++++++++++++------ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/package/contents/ui/ToolTipInstance.qml b/package/contents/ui/ToolTipInstance.qml index 6d040deb..bb19abe5 100644 --- a/package/contents/ui/ToolTipInstance.qml +++ b/package/contents/ui/ToolTipInstance.qml @@ -48,7 +48,8 @@ ColumnLayout { } // Normally the window title will always have " — [app name]" at the end of - // the window-provided title. But if it doesn't, this is intentional 100% + // the window-provided title. + // But if it doesn't, this is intentional 100% // of the time because the developer or user has deliberately removed that // part, so just display it with no more fancy processing. if (!text.match(/\s+(—|-|–)/)) { @@ -146,7 +147,9 @@ ColumnLayout { visible: toolTipDelegate.isWin icon.name: "window-close" onClicked: { - backend.cancelHighlightWindows(); + if (toolTipDelegate.parentTask && toolTipDelegate.parentTask.tasksRoot) { + toolTipDelegate.parentTask.tasksRoot.cancelHighlightWindows(); + } tasksModel.requestClose(root.submodelIndex); } } @@ -402,7 +405,6 @@ ColumnLayout { function generateSubText(): string { const subTextEntries = []; - if (!Plasmoid.configuration.showOnlyCurrentDesktop && virtualDesktopInfo.numberOfDesktops > 1) { if (!isOnAllVirtualDesktops && virtualDesktops.length > 0) { const virtualDesktopNameList = virtualDesktops.map(virtualDesktop => { @@ -420,7 +422,6 @@ ColumnLayout { subTextEntries.push(i18nc("Which virtual desktop a window is currently on", "Available on all activities")); } else if (activities.length > 0) { const activityNames = activities.filter(activity => activity !== activityInfo.currentActivity).map(activity => activityInfo.activityName(activity)).filter(activityName => activityName !== ""); - if (Plasmoid.configuration.showOnlyCurrentActivity) { if (activityNames.length > 0) { subTextEntries.push(i18nc("Activities a window is currently on (apart from the current one)", "Also available on %1", activityNames.join(", "))); diff --git a/package/contents/ui/ToolTipWindowMouseArea.qml b/package/contents/ui/ToolTipWindowMouseArea.qml index d226a7bd..b042aa25 100644 --- a/package/contents/ui/ToolTipWindowMouseArea.qml +++ b/package/contents/ui/ToolTipWindowMouseArea.qml @@ -11,9 +11,9 @@ pragma ComponentBehavior: Bound import QtQuick MouseArea { - required property /*QModelIndex*/var modelIndex - required property /*undefined|WId where WId = int|string*/ var winId - required property Task rootTask + required property var modelIndex + required property var winId + required property var rootTask // Используем var вместо Task, чтобы избежать циклических зависимостей acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton hoverEnabled: true @@ -24,19 +24,28 @@ MouseArea { case Qt.LeftButton: tasksModel.requestActivate(modelIndex); rootTask.hideImmediately(); - backend.cancelHighlightWindows(); + // Используем tasksRoot для доступа к корневому элементу + if (rootTask.tasksRoot) { + rootTask.tasksRoot.cancelHighlightWindows(); + } break; case Qt.MiddleButton: - backend.cancelHighlightWindows(); + if (rootTask.tasksRoot) { + rootTask.tasksRoot.cancelHighlightWindows(); + } tasksModel.requestClose(modelIndex); break; case Qt.RightButton: - tasks.createContextMenu(rootTask, modelIndex).show(); + if (rootTask.tasksRoot) { + rootTask.tasksRoot.createContextMenu(rootTask, modelIndex).show(); + } break; } } onContainsMouseChanged: { - tasks.windowsHovered([winId], containsMouse); + if (rootTask.tasksRoot) { + rootTask.tasksRoot.windowsHovered([winId], containsMouse); + } } } From 5ef88c63b937f2934b9946c345930d677fafd43d Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Mon, 22 Dec 2025 14:34:28 +0200 Subject: [PATCH 128/141] Add Russian(RU_ru) locale --- build.sh | 38 +- iconinstall.sh | 6 +- install.sh | 16 +- .../plasma_applet_alexankitty.fancytasks.mo | Bin 11514 -> 6218 bytes .../plasma_applet_alexankitty.fancytasks.mo | Bin 12792 -> 7411 bytes .../plasma_applet_alexankitty.fancytasks.mo | Bin 0 -> 17570 bytes .../plasma_applet_alexankitty.fancytasks.mo | Bin 10678 -> 5888 bytes package/metadata.json | 2 +- package/translate/build | 42 +- package/translate/get_metadata.sh | 21 + package/translate/merge | 201 +--- package/translate/nl.po | 580 +++++++++-- package/translate/plasmoidlocaletest | 38 +- package/translate/pt_BR.po | 566 ++++++++-- package/translate/ru_RU.po | 978 ++++++++++++++++++ package/translate/template.pot | 292 +++++- package/translate/zh_CN.po | 564 ++++++++-- update.sh | 23 +- 18 files changed, 2754 insertions(+), 613 deletions(-) create mode 100644 package/contents/locale/ru_RU/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo mode change 100644 => 100755 package/translate/build create mode 100755 package/translate/get_metadata.sh mode change 100644 => 100755 package/translate/merge mode change 100644 => 100755 package/translate/plasmoidlocaletest create mode 100644 package/translate/ru_RU.po diff --git a/build.sh b/build.sh index 95f3ab43..a3c122ba 100755 --- a/build.sh +++ b/build.sh @@ -1,16 +1,22 @@ -#!/bin/sh -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -cd $SCRIPT_DIR/package/translate/ -sh ./merge -sh ./build -cd $SCRIPT_DIR -rm -rf $SCRIPT_DIR/release -mkdir $SCRIPT_DIR/build -mkdir $SCRIPT_DIR/release -cp -r $SCRIPT_DIR/package/contents $SCRIPT_DIR/build -cp $SCRIPT_DIR/package/metadata.json $SCRIPT_DIR/build -cp $SCRIPT_DIR/package/FancyTasks.png $SCRIPT_DIR/build -cd $SCRIPT_DIR/build -tar cf $SCRIPT_DIR/release/FancyTasks.tar.gz . -cd $SCRIPT_DIR -rm -rf $SCRIPT_DIR/build \ No newline at end of file +#!/bin/bash +SCRIPT_DIR=$(dirname $(readlink -f "$0")) + +cd "$SCRIPT_DIR/package/translate/" +bash ./merge +bash ./build +cd "$SCRIPT_DIR" + +rm -rf "$SCRIPT_DIR/release" +mkdir -p "$SCRIPT_DIR/build" +mkdir -p "$SCRIPT_DIR/release" + +cp -r "$SCRIPT_DIR/package/contents" "$SCRIPT_DIR/build" +cp "$SCRIPT_DIR/package/metadata.json" "$SCRIPT_DIR/build" +cp "$SCRIPT_DIR/package/FancyTasks.png" "$SCRIPT_DIR/build" + +cd "$SCRIPT_DIR/build" +tar cf "$SCRIPT_DIR/release/FancyTasks.tar.gz" . +cd "$SCRIPT_DIR" + +rm -rf "$SCRIPT_DIR/build" +echo "Build complete: $SCRIPT_DIR/release/FancyTasks.tar.gz" diff --git a/iconinstall.sh b/iconinstall.sh index 1b666271..f66ab480 100755 --- a/iconinstall.sh +++ b/iconinstall.sh @@ -1 +1,5 @@ -cp ./package/FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png \ No newline at end of file +#!/bin/bash +SCRIPT_DIR=$(dirname $(readlink -f "$0")) +mkdir -p ~/.local/share/icons/hicolor/256x256/apps/ +cp "$SCRIPT_DIR/package/FancyTasks.png" ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png +echo "Icon installed." diff --git a/install.sh b/install.sh index 2fc3af3c..12ac26dc 100755 --- a/install.sh +++ b/install.sh @@ -1,5 +1,11 @@ -#!/bin/sh -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -sh $SCRIPT_DIR/build.sh -kpackagetool6 -i $SCRIPT_DIR/release/FancyTasks.tar.gz -sh ./iconinstall.sh +#!/bin/bash +SCRIPT_DIR=$(dirname $(readlink -f "$0")) + +echo "Compiling translations..." +bash "$SCRIPT_DIR/package/translate/build" + +echo "Installing plasmoid ..." +kpackagetool6 -t Plasma/Applet --install "$SCRIPT_DIR/package" + +bash "$SCRIPT_DIR/iconinstall.sh" +echo "Install complete." diff --git a/package/contents/locale/nl/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo b/package/contents/locale/nl/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo index 7fa395ea288a090df7dd8e67f2f50a3f01884087..083ee067a9c6ac0f36ca834c44c52d84e5d7f505 100644 GIT binary patch delta 2508 zcmYk+X>6259LMo#fr3B}%2`Y0DYT_6g>oMSk8+f@w6;)MtRVQbJZ;x*pIvvi<&vyQ zj4{F+A4`IXG4X|HB$AY9j4^lyNfTZOAt7o2&lrP{V2BCCCKKyWT|00R?#6NW6i&t{PQ$~f>t4aR zcmn6)$F_YPSJNJIpE2W&Nt$(3G~h;T#b%s|Z($amMF%h7RJ@53F`chvn2C&Os!=zt zM+P=qu>{+36+Vkv$cL!w&f!GvZ!S>L09UNv<5=3ip$58zn#i9x9W$714$ekRXd$Y< z+V=0j8MJ$>NmOQzBSV;Xk&pR+uT|XNd`=}7?^-j-rzYSai#5fVkCmvDZ?XMbaSH97 zsO$T17RFFFdKop*^eK~t$k3(?wcwRmV}Z* zGsCEXu2`?3CiV;J6#s#F_z#jilg9zk1j|t4tVQ*=pswq*{f9@|Ni#@AGe3N9}Pf>IKwj`=3U==w84KJ^yb~QHtI{ z#xz5y)BKffUq?;w4k{CRxRt5#sFhAZ{ePad0{NH~d}+J})Wlp==Ax+oAI4lg|1VO} zK(8SmbBZtB=nK?JhHd{wso-b-RO5(d^)C(WRUQ78AE~cf+B0aI?55*ibSpI8@RfOqhQ#c&_xK(;Q;4-7&YX qkLmEy9DUQ~#d^bD$oKrePqD%UDprhSNOqDMeV=$o*;4n literal 11514 zcmchcYmgk(b;ldCyaYDE5I^F8FT@&2NV_YoOn?#CtR(aRtt4w#62@TMJ9BrYnV#-R zch9a?5F@a$i329QVyJvc#c>i$Dyc+YNL(RtS*eO07fuy%9ykvd<&;T<*rbwR=jG)0 zzkTPi+T|g;DqVZ#-}m-?oO{l>=bU@@@7_A{Sitic=qI5+9|?lz!28ePhv%=(3xYR; ze+`}qej7X&{0?{q_@5wuuF*vT8mrx9;25|LOu?JL%fLSYe+v93Uq1gWL2wo23Gghi z1#0{pJP6(ez8(BJ$Y1c!{21`Refi?^gJ7KU29LLZ7gD|-Tm}9zxEXv3JRAIbQ2f0J zYM$?cYWH6tf5DkQR`T&S@NJYY0e=F#0<3`h!7IT9@PpuQgW~g?3(9rg23pEr16g8l z#aqkywt<@G22gw)^!Q;=@@s(NrvOnwa14|@?gf7wd;pYuKMQJoPlFogtDxlab#N{C zEl}%wGmX^mB5(q{9E8>2R*=6S;YZ)^@%4{`TJMt{{|MB4e+i23mq79NJy7dEosUcv zZ1K1kl%7IR{4atsp^t*%^FHuW@FDPB;Bip=d<~SGz6r{nz5}Y?zk%-re*hxN;2kil zaW4no0gi*>YZs_-rv3LisP+-4@$T^DyFu~y2q-;21zrn&0hE0H0~DVd5Q6$&0ZxNE z!TsPbfycm?z+1pJgY5#p0v6zfFf{|-2de$wf;WO=EMgmY6l5vEGobYI94Nbb9@KjN z-Iw1&rS{1>P~Z3PBRgn-vXc~)-0uXnz6U|A=P?k~1fK&XkKgn4UjZfG=RuYjya` z4qkF`5WEMx43r*rdc4i!0;qW&1f}O+0mbjHgI9xp0Nwz84}|q#>m`f{-pbDw@J>+e zp9T+{76i|N8t+n5>h-;#-2KKFvs^M^o<*9K*G_kq&S!=Uv01St8u07?%p`tr*l ztOT!sYJU;J)41;fHP2d*Pr=oo=D8Vkas;LCyTFa$1uqAm0x_xJFF^7CGHAe8K=Jc-oUr&=2TC8;fT%K<@%0^0 z^7xql{s5?XKL?7RnWn;F;h*f?C(hp!9q;lWLz{0Loq}zWjdBtqWAY+d%O-2TDF25Eg@bK*|3% z!1dr4K#lWlQ2iAw)&b{&n&%2oa<~E1I2P2n3*gz{-5x&$%0D~;s^8~9t@{r_>HS$y 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 diff --git a/package/contents/locale/ru_RU/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo b/package/contents/locale/ru_RU/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo new file mode 100644 index 0000000000000000000000000000000000000000..defaa7361afbba59c791ae7a1bb22ccbe499fd5e GIT binary patch literal 17570 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 literal 0 HcmV?d00001 diff --git a/package/contents/locale/zh_CN/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo b/package/contents/locale/zh_CN/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo index b22c7c292f3c7e53e5ddf7e9ea0cf9f2c6634f03..af193e54e85b7cf6d5cd61c905ddb4b692ee5049 100644 GIT binary patch delta 2530 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 /dev/null 2>&1 & - fi - echo "[build] Done restarting plasmashell" -else - echo "[build] (re)install the plasmoid and restart plasmashell to test." -fi \ No newline at end of file diff --git a/package/translate/get_metadata.sh b/package/translate/get_metadata.sh new file mode 100755 index 00000000..d08e8331 --- /dev/null +++ b/package/translate/get_metadata.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Скрипт для извлечения значений из metadata.json +# Использование: ./get_metadata.sh "Ключ" + +DIR=$(dirname $(readlink -f "$0")) +METADATA_FILE="$DIR/../metadata.json" +KEY="$1" + +if [ -z "$KEY" ] || [ ! -f "$METADATA_FILE" ]; then + exit 1 +fi + +# 1. Пробуем grep -P (быстро и точно) +val=$(grep -oP "\"$KEY\"\s*:\s*\"\K[^\"]+" "$METADATA_FILE" 2> /dev/null) + +# 2. Если grep -P нет, используем sed (резерв) +if [ -z "$val" ]; then + val=$(grep "\"$KEY\":" "$METADATA_FILE" | head -n 1 | sed -E 's/.*"'"$KEY"'"\s*:\s*"([^"]+)".*/\1/') +fi + +echo "$val" diff --git a/package/translate/merge b/package/translate/merge old mode 100644 new mode 100755 index 7aa879ba..a6134652 --- a/package/translate/merge +++ b/package/translate/merge @@ -1,61 +1,33 @@ -#!/bin/sh -# Version: 22 +#!/bin/bash +# Version: 24 (Modular) -# https://techbase.kde.org/Development/Tutorials/Localization/i18n_Build_Systems -# https://techbase.kde.org/Development/Tutorials/Localization/i18n_Build_Systems/Outside_KDE_repositories -# https://invent.kde.org/sysadmin/l10n-scripty/-/blob/master/extract-messages.sh +DIR=$(dirname $(readlink -f "$0")) -DIR=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd` -plasmoidName=`python3 $DIR/jsonParse.py $DIR/../metadata.json KPlugin.Name` -widgetName="${plasmoidName##*.}" # Strip namespace -website=`python3 $DIR/jsonParse.py $DIR/../metadata.json KPlugin.Website` -bugAddress="$website" -packageRoot=".." # Root of translatable sources -projectName="plasma_applet_${plasmoidName}" # project name +# Используем единый скрипт для получения данных +plasmoidName=$("$DIR/get_metadata.sh" "Id") +widgetName="${plasmoidName##*.}" +bugAddress=$("$DIR/get_metadata.sh" "Website") + +packageRoot=".." +projectName="plasma_applet_${plasmoidName}" -#--- if [ -z "$plasmoidName" ]; then - echo "[merge] Error: Couldn't read plasmoidName." - exit + echo "[merge] Error: Couldn't read 'Id' from metadata.json." + exit 1 fi if [ -z "$(which xgettext)" ]; then - echo "[merge] Error: xgettext command not found. Need to install gettext" + echo "[merge] Error: xgettext command not found." echo "[merge] Running 'sudo apt install gettext'" sudo apt install gettext - echo "[merge] gettext installation should be finished. Going back to merging translations." fi -#--- echo "[merge] Extracting messages" potArgs="--from-code=UTF-8 --width=200 --add-location=file" -# Note: xgettext v0.20.1 (Kubuntu 20.04) and below will attempt to translate Icon, -# so we need to specify Name, GenericName, Comment, and Keywords. -# https://github.com/Zren/plasma-applet-lib/issues/1 -# https://savannah.gnu.org/support/?108887 - -# find "${packageRoot}" -name '*.desktop' | sort > "${DIR}/infiles.list" -# xgettext \ -# ${potArgs} \ -# --files-from="${DIR}/infiles.list" \ -# --language=Desktop \ -# -k -kName -kGenericName -kComment -kKeywords \ -# -D "${packageRoot}" \ -# -D "${DIR}" \ -# -o "template.pot.new" \ -# || \ -# { echo "[merge] error while calling xgettext. aborting."; exit 1; } +find "${packageRoot}" -name '*.cpp' -o -name '*.h' -o -name '*.c' -o -name '*.qml' -o -name '*.js' | \ +sort > "${DIR}/infiles.list" -# sed -i 's/"Content-Type: text\/plain; charset=CHARSET\\n"/"Content-Type: text\/plain; charset=UTF-8\\n"/' "template.pot.new" - -# See Ki18n's extract-messages.sh for a full example: -# https://invent.kde.org/sysadmin/l10n-scripty/-/blob/master/extract-messages.sh#L25 -# The -kN_ and -kaliasLocale keywords are mentioned in the Outside_KDE_repositories wiki. -# We don't need -kN_ since we don't use intltool-extract but might as well keep it. -# I have no idea what -kaliasLocale is used for. Googling aliasLocale found only listed kde1 code. -# We don't need to parse -ki18nd since that'll extract messages from other domains. -find "${packageRoot}" -name '*.cpp' -o -name '*.h' -o -name '*.c' -o -name '*.qml' -o -name '*.js' | sort > "${DIR}/infiles.list" xgettext \ ${potArgs} \ --files-from="${DIR}/infiles.list" \ @@ -74,166 +46,53 @@ xgettext \ --msgid-bugs-address="${bugAddress}" \ -D "${packageRoot}" \ -D "${DIR}" \ - -o "template.pot.new" \ - || \ - { echo "[merge] error while calling xgettext. aborting."; exit 1; } + -o "template.pot.new" + +if [ $? -ne 0 ]; then + echo "[merge] error while calling xgettext. aborting." + exit 1 +fi sed -i 's/# SOME DESCRIPTIVE TITLE./'"# Translation of ${widgetName} in LANGUAGE"'/' "template.pot.new" sed -i 's/# Copyright (C) YEAR THE PACKAGE'"'"'S COPYRIGHT HOLDER/'"# Copyright (C) $(date +%Y)"'/' "template.pot.new" if [ -f "template.pot" ]; then - newPotDate=`grep "POT-Creation-Date:" template.pot.new | sed 's/.\{3\}$//'` - oldPotDate=`grep "POT-Creation-Date:" template.pot | sed 's/.\{3\}$//'` + newPotDate=$(grep "POT-Creation-Date:" template.pot.new | sed 's/.\{3\}$//') + oldPotDate=$(grep "POT-Creation-Date:" template.pot | sed 's/.\{3\}$//') sed -i 's/'"${newPotDate}"'/'"${oldPotDate}"'/' "template.pot.new" - changes=`diff "template.pot" "template.pot.new"` + changes=$(diff "template.pot" "template.pot.new") if [ ! -z "$changes" ]; then - # There's been changes sed -i 's/'"${oldPotDate}"'/'"${newPotDate}"'/' "template.pot.new" mv "template.pot.new" "template.pot" - - addedKeys=`echo "$changes" | grep "> msgid" | cut -c 9- | sort` - removedKeys=`echo "$changes" | grep "< msgid" | cut -c 9- | sort` - echo "" - echo "Added Keys:" - echo "$addedKeys" - echo "" - echo "Removed Keys:" - echo "$removedKeys" - echo "" - + echo "Template updated." else - # No changes rm "template.pot.new" + echo "No changes in template." fi else - # template.pot didn't already exist mv "template.pot.new" "template.pot" fi -potMessageCount=`expr $(grep -Pzo 'msgstr ""\n(\n|$)' "template.pot" | grep -c 'msgstr ""')` -echo "| Locale | Lines | % Done|" > "./Status.md" -echo "|----------|---------|-------|" >> "./Status.md" -entryFormat="| %-8s | %7s | %5s |" -templateLine=`perl -e "printf(\"$entryFormat\", \"Template\", \"${potMessageCount}\", \"\")"` -echo "$templateLine" >> "./Status.md" - rm "${DIR}/infiles.list" echo "[merge] Done extracting messages" -#--- echo "[merge] Merging messages" -catalogs=`find . -name '*.po' | sort` +catalogs=$(find . -name '*.po' | sort) for cat in $catalogs; do echo "[merge] $cat" - catLocale=`basename ${cat%.*}` - - widthArg="" - catUsesGenerator=`grep "X-Generator:" "$cat"` - if [ -z "$catUsesGenerator" ]; then - widthArg="--width=400" - fi - - compendiumArg="" - if [ ! -z "$COMPENDIUM_DIR" ]; then - langCode=`basename "${cat%.*}"` - compendiumPath=`realpath "$COMPENDIUM_DIR/compendium-${langCode}.po"` - if [ -f "$compendiumPath" ]; then - echo "compendiumPath=$compendiumPath" - compendiumArg="--compendium=$compendiumPath" - fi - fi - + catLocale=$(basename "${cat%.*}") + cp "$cat" "$cat.new" sed -i 's/"Content-Type: text\/plain; charset=CHARSET\\n"/"Content-Type: text\/plain; charset=UTF-8\\n"/' "$cat.new" msgmerge \ - ${widthArg} \ + --width=400 \ --add-location=file \ --no-fuzzy-matching \ - ${compendiumArg} \ -o "$cat.new" \ "$cat.new" "${DIR}/template.pot" sed -i 's/# SOME DESCRIPTIVE TITLE./'"# Translation of ${widgetName} in ${catLocale}"'/' "$cat.new" - sed -i 's/# Translation of '"${widgetName}"' in LANGUAGE/'"# Translation of ${widgetName} in ${catLocale}"'/' "$cat.new" - sed -i 's/# Copyright (C) YEAR THE PACKAGE'"'"'S COPYRIGHT HOLDER/'"# Copyright (C) $(date +%Y)"'/' "$cat.new" - - poEmptyMessageCount=`expr $(grep -Pzo 'msgstr ""\n(\n|$)' "$cat.new" | grep -c 'msgstr ""')` - poMessagesDoneCount=`expr $potMessageCount - $poEmptyMessageCount` - poCompletion=`perl -e "printf(\"%d\", $poMessagesDoneCount * 100 / $potMessageCount)"` - poLine=`perl -e "printf(\"$entryFormat\", \"$catLocale\", \"${poMessagesDoneCount}/${potMessageCount}\", \"${poCompletion}%\")"` - echo "$poLine" >> "./Status.md" - - # mv "$cat" "$cat.old" mv "$cat.new" "$cat" done echo "[merge] Done merging messages" - -#--- -# echo "[merge] Updating .desktop file" - -# # Generate LINGUAS for msgfmt -# if [ -f "$DIR/LINGUAS" ]; then -# rm "$DIR/LINGUAS" -# fi -# touch "$DIR/LINGUAS" -# for cat in $catalogs; do -# catLocale=`basename ${cat%.*}` -# echo "${catLocale}" >> "$DIR/LINGUAS" -# done - -# cp -f "$DIR/../metadata.desktop" "$DIR/template.desktop" -# sed -i '/^Name\[/ d; /^GenericName\[/ d; /^Comment\[/ d; /^Keywords\[/ d' "$DIR/template.desktop" - -# msgfmt \ -# --desktop \ -# --template="$DIR/template.desktop" \ -# -d "$DIR/" \ -# -o "$DIR/new.desktop" - -# # Delete empty msgid messages that used the po header -# if [ ! -z "$(grep '^Name=$' "$DIR/new.desktop")" ]; then -# echo "[merge] Name in metadata.desktop is empty!" -# sed -i '/^Name\[/ d' "$DIR/new.desktop" -# fi -# if [ ! -z "$(grep '^GenericName=$' "$DIR/new.desktop")" ]; then -# echo "[merge] GenericName in metadata.desktop is empty!" -# sed -i '/^GenericName\[/ d' "$DIR/new.desktop" -# fi -# if [ ! -z "$(grep '^Comment=$' "$DIR/new.desktop")" ]; then -# echo "[merge] Comment in metadata.desktop is empty!" -# sed -i '/^Comment\[/ d' "$DIR/new.desktop" -# fi -# if [ ! -z "$(grep '^Keywords=$' "$DIR/new.desktop")" ]; then -# echo "[merge] Keywords in metadata.desktop is empty!" -# sed -i '/^Keywords\[/ d' "$DIR/new.desktop" -# fi - -# # Place translations at the bottom of the desktop file. -# translatedLines=`cat "$DIR/new.desktop" | grep "]="` -# if [ ! -z "${translatedLines}" ]; then -# sed -i '/^Name\[/ d; /^GenericName\[/ d; /^Comment\[/ d; /^Keywords\[/ d' "$DIR/new.desktop" -# if [ "$(tail -c 2 "$DIR/new.desktop" | wc -l)" != "2" ]; then -# # Does not end with 2 empty lines, so add an empty line. -# echo "" >> "$DIR/new.desktop" -# fi -# echo "${translatedLines}" >> "$DIR/new.desktop" -# fi - -# # Cleanup -# mv "$DIR/new.desktop" "$DIR/../metadata.desktop" -# rm "$DIR/template.desktop" -# rm "$DIR/LINGUAS" - -#--- -# Populate ReadMe.md -echo "[merge] Updating translate/ReadMe.md" -sed -i -E 's`share\/plasma\/plasmoids\/(.+)\/translate`share/plasma/plasmoids/'"${plasmoidName}"'/translate`' ./ReadMe.md -if [[ "$website" == *"github.com"* ]]; then - sed -i -E 's`\[new issue\]\(https:\/\/github\.com\/(.+)\/(.+)\/issues\/new\)`[new issue]('"${website}"'/issues/new)`' ./ReadMe.md -fi -sed -i '/^|/ d' ./ReadMe.md # Remove status table from ReadMe -cat ./Status.md >> ./ReadMe.md -rm ./Status.md - -echo "[merge] Done" \ No newline at end of file diff --git a/package/translate/nl.po b/package/translate/nl.po index 1adaf9ea..ee7bee4e 100644 --- a/package/translate/nl.po +++ b/package/translate/nl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-13 22:51-0600\n" +"POT-Creation-Date: 2025-12-22 13:42+0200\n" "PO-Revision-Date: 2023-07-13 22:27+0200\n" "Last-Translator: Heimen Stoffels \n" "Language-Team: \n" @@ -29,6 +29,30 @@ msgstr "Gedrag" msgid "Indicators" msgstr "Indicators" +#: ../contents/config/config.qml +msgid "Pinned Applications" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@action:button" +msgid "Unmute" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@action:button" +msgid "Mute" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@info:tooltip %1 is the window title" +msgid "Unmute %1" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@info:tooltip %1 is the window title" +msgid "Mute %1" +msgstr "" + #: ../contents/ui/Badge.qml msgctxt "Invalid number of new messages, overlay, keep short" msgid "—" @@ -40,27 +64,31 @@ msgid "9,999+" msgstr "9,999+" #: ../contents/ui/ConfigAppearance.qml -msgid "General:" -msgstr "Algemeen:" +msgid "Use plasma borders" +msgstr "Plasmakaders gebruiken" #: ../contents/ui/ConfigAppearance.qml -msgid "Show tooltips" -msgstr "Vensterminiaturen tonen" +msgid "Icon Scale" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Highlight windows when hovering over task tooltips" -msgstr "Vensters voorvertonen na aanwijzen van vensterminiaturen" +msgid "Icon Hover Effects" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Mark applications that play audio" -msgstr "Programma's die audio afspelen markeren" +msgid "Icon zoom factor (px):" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Use plasma borders" -msgstr "Plasmakaders gebruiken" +msgid "How much the icon should grow when hovered (in pixels)" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Icon Scale" +msgid "Zoom animation duration (ms):" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Duration of the zoom animation in milliseconds" msgstr "" #: ../contents/ui/ConfigAppearance.qml @@ -136,32 +164,97 @@ msgid "East" msgstr "Rechts" #: ../contents/ui/ConfigAppearance.qml -msgid "Maximum columns:" -msgstr "Maximaal aantal kolommen:" +msgid "Maximum button length (px):" +msgstr "Maximale knopbreedte (in px):" #: ../contents/ui/ConfigAppearance.qml -msgid "Maximum rows:" -msgstr "Maximaal aantal rijen:" +msgid "Space between taskbar items (px):" +msgstr "Ruimte tussen taakbalkitems (in px):" #: ../contents/ui/ConfigAppearance.qml -msgid "Always arrange tasks in rows of as many columns" -msgstr "Taken altijd verdelen over zoveel mogelijk kolommen" +msgctxt "@label for several checkboxes" +msgid "General:" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Always arrange tasks in columns of as many rows" -msgstr "Taken altijd verdelen over zoveel mogelijk rijen" +msgctxt "@option:check section General" +msgid "Show small window previews when hovering over tasks" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Maximum button length (px):" -msgstr "Maximale knopbreedte (in px):" +msgctxt "@option:check section General" +msgid "Hide other windows when hovering over previews" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Space between taskbar items (px):" -msgstr "Ruimte tussen taakbalkitems (in px):" +msgctxt "@option:check section General" +msgid "Mark applications that play audio" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:check section General" +msgid "Fill free space on panel" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:listbox" +msgid "Maximum task width:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Narrow" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Medium" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Wide" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label for radio button group, completes sentence: … when panel is low on space etc." +msgid "Use multi-column view:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label for radio button group, completes sentence: … when panel is low on space etc." +msgid "Use multi-row view:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio Never use multi-column view for Task Manager" +msgid "Never" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio completes sentence: Use multi-column/row view" +msgid "When panel is low on space and thick enough" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio completes sentence: Use multi-column/row view" +msgid "Always when panel is thick enough" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:spinbox maximum number of columns for tasks" +msgid "Maximum columns:" +msgstr "" #: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:spinbox maximum number of rows for tasks" +msgid "Maximum rows:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:listbox" msgid "Spacing between icons:" -msgstr "Ruimte tussen pictogrammen:" +msgstr "" #: ../contents/ui/ConfigAppearance.qml msgctxt "@item:inlistbox Icon spacing" @@ -180,8 +273,8 @@ msgstr "Groot" #: ../contents/ui/ConfigAppearance.qml msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" -msgid "Automatically set to Large when in Touch Mode" -msgstr "Automatisch ingesteld op ‘Groot’ als de aanraakmodus is ingeschakeld" +msgid "Automatically set to Large when in Touch mode" +msgstr "" #: ../contents/ui/ConfigBehavior.qml msgid "Display:" @@ -196,204 +289,219 @@ msgid "Show icons only" msgstr "Alleen pictogrammen" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox how to group tasks" msgid "Group:" -msgstr "Groeperen:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox how to group tasks" msgid "Do not group" -msgstr "Niet groeperen" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox how to group tasks" msgid "By program name" -msgstr "Op programmanaam" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox completes sentence like: … cycles through tasks" msgid "Clicking grouped task:" -msgstr "Actie na aanklikken van gegroepeerde taak:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Completes the sentence 'Clicking grouped task cycles through tasks' " +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task cycles through tasks' " msgid "Cycles through tasks" -msgstr "Van taak wisselen" - -#: ../contents/ui/ConfigBehavior.qml -msgctxt "" -"Completes the sentence 'Clicking grouped task shows tooltip window " -"thumbnails' " -msgid "Shows tooltip window thumbnails" -msgstr "Vensterminiaturen tonen" - -#: ../contents/ui/ConfigBehavior.qml -msgctxt "" -"Completes the sentence 'Clicking grouped task shows windows side by side' " -msgid "Shows windows side by side" -msgstr "Vensters naast elkaar tonen" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Completes the sentence 'Clicking grouped task shows textual list' " -msgid "Shows textual list" -msgstr "Vensterlijst tonen" +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows small window previews' " +msgid "Shows small window previews" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgid "" -"Tooltips are disabled, so the windows will be displayed side by side instead." +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows large window previews' " +msgid "Shows large window previews" msgstr "" -"Vensterminiaturen zijn uitgeschakeld; vensters worden naast elkaar getoond." #: ../contents/ui/ConfigBehavior.qml -msgid "" -"Tooltips are disabled, and the compositor does not support displaying " -"windows side by side, so a textual list will be displayed instead" +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows textual list' " +msgid "Shows textual list" msgstr "" -"Vensterminiaturen zijn uitgeschakeld en de compositor heeft geen " -"ondersteuning voor het tonen van vensters naast elkaar. Er wordt in plaats " -"daarvan een lijst getoond." #: ../contents/ui/ConfigBehavior.qml -msgid "" -"The compositor does not support displaying windows side by side, so a " -"textual list will be displayed instead." +msgctxt "@info displayed as InlineMessage" +msgid "The compositor does not support displaying windows side by side, so a textual list will be displayed instead." msgstr "" -"De compositor heeft geen ondersteuning voor het tonen van vensters naast " -"elkaar; er wordt een lijst getoond." #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check grouped task" msgid "Combine into single button" -msgstr "Combineren tot één knop" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check grouped task" msgid "Group only when the Task Manager is full" -msgstr "Alleen groeperen als takenbeheer vol is" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox sort tasks in grouped task" msgid "Sort:" -msgstr "Rangschikken:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Do not sort" -msgstr "Niet rangschikken" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Manually" -msgstr "Handmatig" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Alphabetically" -msgstr "Op alfabetische volgorde" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "By desktop" -msgstr "Op bureaublad" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "By activity" -msgstr "Op activiteit" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check configure task sorting" msgid "Keep launchers separate" -msgstr "Starters gescheiden houden" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check for icons-and-text task manager" +msgid "Hide launchers after application startup" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgctxt "@label for checkbox Part of a sentence: 'Clicking active task minimizes the task'" msgid "Clicking active task:" -msgstr "Actie na aanklikken van actieve taak:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgctxt "@option:check Part of a sentence: 'Clicking active task minimizes the task'" msgid "Minimizes the task" -msgstr "Taak minimaliseren" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox completes sentence like: … does nothing" msgid "Middle-clicking any task:" -msgstr "Actie na middelklikken op een taak:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task does nothing'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task does nothing'" msgid "Does nothing" -msgstr "Niets doen" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task closes window or group'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task closes window or group'" msgid "Closes window or group" -msgstr "Venster of groep sluiten" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task opens a new window'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task opens a new window'" msgid "Opens a new window" -msgstr "Nieuw venster openen" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "" -"Part of a sentence: 'Middle-clicking any task minimizes/restores window or " -"group'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" msgid "Minimizes/Restores window or group" -msgstr "Venster of groep minimaliseren/herstellen" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task toggles grouping'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task toggles grouping'" msgid "Toggles grouping" -msgstr "Groeperen in-/uitschakelen" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "" -"Part of a sentence: 'Middle-clicking any task brings it to the current " -"virtual desktop'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" msgid "Brings it to the current virtual desktop" -msgstr "Verplaatsen naar huidig virtueel bureaublad" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgctxt "@label for checkbox Part of a sentence: 'Mouse wheel cycles through tasks'" msgid "Mouse wheel:" -msgstr "Muiswiel:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgctxt "@option:check Part of a sentence: 'Mouse wheel cycles through tasks'" msgid "Cycles through tasks" -msgstr "Van taak wisselen" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check mouse wheel task cycling" msgid "Skip minimized tasks" -msgstr "Geminimaliseerde taken overslaan" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for checkbox group, completes sentence like: … from current screen" msgid "Show only tasks:" -msgstr "Alleen taken tonen van:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "From current screen" -msgstr "Huidig scherm" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "From current desktop" -msgstr "Huidig bureaublad" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "From current activity" -msgstr "Huidige activiteit" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "That are minimized" -msgstr "Geminimaliseerde vensters" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for checkbox, completes sentence: … unhide if window wants attention" msgid "When panel is hidden:" -msgstr "Als het paneel verborgen is:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: When panel is hidden" msgid "Unhide when a window wants attention" -msgstr "Tonen als een venster om aandacht vraagt" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for radiobutton group completes sentence like: … on the bottom" msgid "New tasks appear:" -msgstr "Nieuwe taken tonen aan:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" +msgid "On the bottom" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" msgid "To the right" -msgstr "Rechterkant" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" msgid "To the left" -msgstr "Linkerkant" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" +msgid "On the top" +msgstr "" #: ../contents/ui/ConfigIndicators.qml msgid "Indicators:" @@ -527,6 +635,50 @@ msgstr "Indicatorkleur:" msgid "Use plasma accent color" msgstr "Plasma-accentkleur" +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Application" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Search applications..." +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Web Browser" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default File Manager" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Mail Client" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Application" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add applications to pin to the taskbar. Drag items to reorder them." +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Remove" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Application..." +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Special Launcher..." +msgstr "" + #: ../contents/ui/ContextMenu.qml msgid "Places" msgstr "Locaties" @@ -594,11 +746,6 @@ msgstr "Verplaa&tsen naar huidig bureaublad" msgid "&All Desktops" msgstr "&Alle bureaubladen" -#: ../contents/ui/ContextMenu.qml -msgctxt "1 = number of desktop, 2 = desktop name" -msgid "&%1 %2" -msgstr "&%1 %2" - #: ../contents/ui/ContextMenu.qml msgid "&New Desktop" msgstr "&Nieuw bureaublad" @@ -675,10 +822,42 @@ msgstr "Op&rollen" msgid "Allow this program to be grouped" msgstr "Groeperen toestaan" +#: ../contents/ui/ContextMenu.qml +msgctxt "@item:inmenu" +msgid "&Close All" +msgstr "" + #: ../contents/ui/ContextMenu.qml msgid "&Close" msgstr "&Sluiten" +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 application name" +msgid "Launch %1" +msgstr "" + +#: ../contents/ui/Task.qml +msgctxt "@info:tooltip" +msgid "There is %1 new message." +msgid_plural "There are %1 new messages." +msgstr[0] "" +msgstr[1] "" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Show Task tooltip for %1" +msgstr "" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Show windows side by side for %1" +msgstr "" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Open textual list of windows for %1" +msgstr "" + #: ../contents/ui/Task.qml msgid "Activate %1" msgstr "%1 activeren" @@ -733,6 +912,181 @@ msgctxt "Which activities a window is currently on" msgid "Available on %1" msgstr "Actief op %1" +#~ msgid "General:" +#~ msgstr "Algemeen:" + +#~ msgid "Show tooltips" +#~ msgstr "Vensterminiaturen tonen" + +#~ msgid "Highlight windows when hovering over task tooltips" +#~ msgstr "Vensters voorvertonen na aanwijzen van vensterminiaturen" + +#~ msgid "Mark applications that play audio" +#~ msgstr "Programma's die audio afspelen markeren" + +#~ msgid "Maximum columns:" +#~ msgstr "Maximaal aantal kolommen:" + +#~ msgid "Maximum rows:" +#~ msgstr "Maximaal aantal rijen:" + +#~ msgid "Always arrange tasks in rows of as many columns" +#~ msgstr "Taken altijd verdelen over zoveel mogelijk kolommen" + +#~ msgid "Always arrange tasks in columns of as many rows" +#~ msgstr "Taken altijd verdelen over zoveel mogelijk rijen" + +#~ msgid "Spacing between icons:" +#~ msgstr "Ruimte tussen pictogrammen:" + +#~ msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" +#~ msgid "Automatically set to Large when in Touch Mode" +#~ msgstr "Automatisch ingesteld op ‘Groot’ als de aanraakmodus is ingeschakeld" + +#~ msgid "Group:" +#~ msgstr "Groeperen:" + +#~ msgid "Do not group" +#~ msgstr "Niet groeperen" + +#~ msgid "By program name" +#~ msgstr "Op programmanaam" + +#~ msgid "Clicking grouped task:" +#~ msgstr "Actie na aanklikken van gegroepeerde taak:" + +#~ msgctxt "Completes the sentence 'Clicking grouped task cycles through tasks' " +#~ msgid "Cycles through tasks" +#~ msgstr "Van taak wisselen" + +#~ msgctxt "Completes the sentence 'Clicking grouped task shows tooltip window thumbnails' " +#~ msgid "Shows tooltip window thumbnails" +#~ msgstr "Vensterminiaturen tonen" + +#~ msgctxt "Completes the sentence 'Clicking grouped task shows windows side by side' " +#~ msgid "Shows windows side by side" +#~ msgstr "Vensters naast elkaar tonen" + +#~ msgctxt "Completes the sentence 'Clicking grouped task shows textual list' " +#~ msgid "Shows textual list" +#~ msgstr "Vensterlijst tonen" + +#~ msgid "Tooltips are disabled, so the windows will be displayed side by side instead." +#~ msgstr "Vensterminiaturen zijn uitgeschakeld; vensters worden naast elkaar getoond." + +#~ msgid "Tooltips are disabled, and the compositor does not support displaying windows side by side, so a textual list will be displayed instead" +#~ msgstr "Vensterminiaturen zijn uitgeschakeld en de compositor heeft geen ondersteuning voor het tonen van vensters naast elkaar. Er wordt in plaats daarvan een lijst getoond." + +#~ msgid "The compositor does not support displaying windows side by side, so a textual list will be displayed instead." +#~ msgstr "De compositor heeft geen ondersteuning voor het tonen van vensters naast elkaar; er wordt een lijst getoond." + +#~ msgid "Combine into single button" +#~ msgstr "Combineren tot één knop" + +#~ msgid "Group only when the Task Manager is full" +#~ msgstr "Alleen groeperen als takenbeheer vol is" + +#~ msgid "Sort:" +#~ msgstr "Rangschikken:" + +#~ msgid "Do not sort" +#~ msgstr "Niet rangschikken" + +#~ msgid "Manually" +#~ msgstr "Handmatig" + +#~ msgid "Alphabetically" +#~ msgstr "Op alfabetische volgorde" + +#~ msgid "By desktop" +#~ msgstr "Op bureaublad" + +#~ msgid "By activity" +#~ msgstr "Op activiteit" + +#~ msgid "Keep launchers separate" +#~ msgstr "Starters gescheiden houden" + +#~ msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +#~ msgid "Clicking active task:" +#~ msgstr "Actie na aanklikken van actieve taak:" + +#~ msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +#~ msgid "Minimizes the task" +#~ msgstr "Taak minimaliseren" + +#~ msgid "Middle-clicking any task:" +#~ msgstr "Actie na middelklikken op een taak:" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task does nothing'" +#~ msgid "Does nothing" +#~ msgstr "Niets doen" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task closes window or group'" +#~ msgid "Closes window or group" +#~ msgstr "Venster of groep sluiten" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task opens a new window'" +#~ msgid "Opens a new window" +#~ msgstr "Nieuw venster openen" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" +#~ msgid "Minimizes/Restores window or group" +#~ msgstr "Venster of groep minimaliseren/herstellen" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task toggles grouping'" +#~ msgid "Toggles grouping" +#~ msgstr "Groeperen in-/uitschakelen" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" +#~ msgid "Brings it to the current virtual desktop" +#~ msgstr "Verplaatsen naar huidig virtueel bureaublad" + +#~ msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +#~ msgid "Mouse wheel:" +#~ msgstr "Muiswiel:" + +#~ msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +#~ msgid "Cycles through tasks" +#~ msgstr "Van taak wisselen" + +#~ msgid "Skip minimized tasks" +#~ msgstr "Geminimaliseerde taken overslaan" + +#~ msgid "Show only tasks:" +#~ msgstr "Alleen taken tonen van:" + +#~ msgid "From current screen" +#~ msgstr "Huidig scherm" + +#~ msgid "From current desktop" +#~ msgstr "Huidig bureaublad" + +#~ msgid "From current activity" +#~ msgstr "Huidige activiteit" + +#~ msgid "That are minimized" +#~ msgstr "Geminimaliseerde vensters" + +#~ msgid "When panel is hidden:" +#~ msgstr "Als het paneel verborgen is:" + +#~ msgid "Unhide when a window wants attention" +#~ msgstr "Tonen als een venster om aandacht vraagt" + +#~ msgid "New tasks appear:" +#~ msgstr "Nieuwe taken tonen aan:" + +#~ msgid "To the right" +#~ msgstr "Rechterkant" + +#~ msgid "To the left" +#~ msgstr "Linkerkant" + +#~ msgctxt "1 = number of desktop, 2 = desktop name" +#~ msgid "&%1 %2" +#~ msgstr "&%1 %2" + #~ msgid "Press OK to fix layout issues." #~ msgstr "Klik op oké om indelingsproblemen op te lossen." diff --git a/package/translate/plasmoidlocaletest b/package/translate/plasmoidlocaletest old mode 100644 new mode 100755 index 5cd76a21..2f4ac2c4 --- a/package/translate/plasmoidlocaletest +++ b/package/translate/plasmoidlocaletest @@ -1,16 +1,11 @@ #!/bin/bash -# Version 9 -# Requires plasmoidviewer v5.13.0 +# Version 10 function checkIfLangInstalled { if [ -x "$(command -v dpkg)" ]; then - dpkg -l ${1} >/dev/null 2>&1 || ( \ - echo -e "${1} not installed.\nInstalling now before continuing.\n" \ - ; sudo apt install ${1} \ - ) || ( \ - echo -e "\nError trying to install ${1}\nPlease run 'sudo apt install ${1}'\n" \ - ; exit 1 \ - ) + dpkg -l ${1} >/dev/null 2>&1 || \ + ( echo -e "${1} not installed.\nInstalling now...\n"; sudo apt install ${1} ) || \ + ( echo -e "\nError trying to install ${1}\n"; exit 1 ) elif [ -x "$(command -v pacman)" ]; then # TODO: run `locale -a` and check if the locale is enabled. if false; then @@ -137,7 +132,7 @@ declare -a langArr=( for i in "${langArr[@]}"; do IFS=: read -r l1 l2 l3 <<< "$i" - if [ "$langInput" == "$l2" ]; then + if [ "$langInput" == "$l2" ] || [ "$langInput" == "$l1" ]; then lang="${l1}:${l2}" languagePack="language-pack-${l2}" fi @@ -147,13 +142,7 @@ if [ -z "$lang" ]; then echo "plasmoidlocaletest doesn't recognize the language '$lang'" echo "Eg:" scriptcmd='sh ./plasmoidlocaletest' - for i in "${langArr[@]}"; do - IFS=: read -r l1 l2 l3 <<< "$i" - echo " ${scriptcmd} ${l2} | ${l3}" - done - echo "" - echo "Or use a the full locale code:" - echo " ${scriptcmd} ar_EG:ar" + echo " ${scriptcmd} ru_RU" exit 1 fi @@ -162,20 +151,19 @@ l1="${l1}.UTF-8" # Check if language is installed if [ ! -z "$languagePack" ]; then - if [ "$lang" == "zh_CN:zh" ]; then languagePack="language-pack-zh-hans" - fi + if [ "$lang" == "zh_CN:zh" ]; then languagePack="language-pack-zh-hans"; fi checkIfLangInstalled "$languagePack" || exit 1 fi - echo "LANGUAGE=\"${lang}\"" echo "LANG=\"${l1}\"" -scriptDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -packageDir="${scriptDir}/.." +SCRIPT_DIR=$(dirname $(readlink -f "$0")) +# Absolute path to package +PACKAGE_DIR=$(readlink -f "$SCRIPT_DIR/..") -# Build local translations for plasmoidviewer -sh "${scriptDir}/build" +# Build local translations +bash "${SCRIPT_DIR}/build" -LANGUAGE="${lang}" LANG="${l1}" LC_TIME="${l1}" QML_DISABLE_DISK_CACHE=true plasmoidviewer -a "$packageDir" -l topedge -f horizontal -x 0 -y 0 \ No newline at end of file +LANGUAGE="${lang}" LANG="${l1}" LC_ALL="${l1}" QML_DISABLE_DISK_CACHE=true plasmawindowed "$PACKAGE_DIR" diff --git a/package/translate/pt_BR.po b/package/translate/pt_BR.po index 8b429286..56d512bf 100644 --- a/package/translate/pt_BR.po +++ b/package/translate/pt_BR.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Fancy Tasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-13 22:51-0600\n" +"POT-Creation-Date: 2025-12-22 13:42+0200\n" "PO-Revision-Date: 2023-09-21 16:18-0300\n" "Last-Translator: Douglas Guimarães <>\n" "Language-Team: \n" @@ -29,6 +29,30 @@ msgstr "Comportamento" msgid "Indicators" msgstr "Indicadores" +#: ../contents/config/config.qml +msgid "Pinned Applications" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@action:button" +msgid "Unmute" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@action:button" +msgid "Mute" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@info:tooltip %1 is the window title" +msgid "Unmute %1" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@info:tooltip %1 is the window title" +msgid "Mute %1" +msgstr "" + #: ../contents/ui/Badge.qml msgctxt "Invalid number of new messages, overlay, keep short" msgid "—" @@ -40,28 +64,32 @@ msgid "9,999+" msgstr "9,999+" #: ../contents/ui/ConfigAppearance.qml -msgid "General:" -msgstr "Geral" +msgid "Use plasma borders" +msgstr "Usar bordas do plasma" #: ../contents/ui/ConfigAppearance.qml -msgid "Show tooltips" -msgstr "Mostrar visualizações" +msgid "Icon Scale" +msgstr "Escala do ícone" #: ../contents/ui/ConfigAppearance.qml -msgid "Highlight windows when hovering over task tooltips" -msgstr "Destacar janelas quando passar o cursor sobre as visualizações" +msgid "Icon Hover Effects" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Mark applications that play audio" -msgstr "Marque os programas que estiverem tocando áudio" +msgid "Icon zoom factor (px):" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Use plasma borders" -msgstr "Usar bordas do plasma" +msgid "How much the icon should grow when hovered (in pixels)" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Icon Scale" -msgstr "Escala do ícone" +msgid "Zoom animation duration (ms):" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Duration of the zoom animation in milliseconds" +msgstr "" #: ../contents/ui/ConfigAppearance.qml msgid "Icon Size (px):" @@ -136,32 +164,97 @@ msgid "East" msgstr "Leste" #: ../contents/ui/ConfigAppearance.qml -msgid "Maximum columns:" -msgstr "Máximo de colunas:" +msgid "Maximum button length (px):" +msgstr "Comprimento máximo do botão (px):" #: ../contents/ui/ConfigAppearance.qml -msgid "Maximum rows:" -msgstr "Máximo de linhas" +msgid "Space between taskbar items (px):" +msgstr "Espaço entre os itens da barra de tarefas (px):" #: ../contents/ui/ConfigAppearance.qml -msgid "Always arrange tasks in rows of as many columns" -msgstr "Sempre organize as tarefas em linhas com o máximo de colunas" +msgctxt "@label for several checkboxes" +msgid "General:" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Always arrange tasks in columns of as many rows" -msgstr "Sempre organize as tarefas em colunas com o máximo de linhas" +msgctxt "@option:check section General" +msgid "Show small window previews when hovering over tasks" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Maximum button length (px):" -msgstr "Comprimento máximo do botão (px):" +msgctxt "@option:check section General" +msgid "Hide other windows when hovering over previews" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Space between taskbar items (px):" -msgstr "Espaço entre os itens da barra de tarefas (px):" +msgctxt "@option:check section General" +msgid "Mark applications that play audio" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:check section General" +msgid "Fill free space on panel" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:listbox" +msgid "Maximum task width:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Narrow" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Medium" +msgstr "" #: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Wide" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label for radio button group, completes sentence: … when panel is low on space etc." +msgid "Use multi-column view:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label for radio button group, completes sentence: … when panel is low on space etc." +msgid "Use multi-row view:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio Never use multi-column view for Task Manager" +msgid "Never" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio completes sentence: Use multi-column/row view" +msgid "When panel is low on space and thick enough" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio completes sentence: Use multi-column/row view" +msgid "Always when panel is thick enough" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:spinbox maximum number of columns for tasks" +msgid "Maximum columns:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:spinbox maximum number of rows for tasks" +msgid "Maximum rows:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:listbox" msgid "Spacing between icons:" -msgstr "Espaço entre os ícones:" +msgstr "" #: ../contents/ui/ConfigAppearance.qml msgctxt "@item:inlistbox Icon spacing" @@ -180,8 +273,8 @@ msgstr "Grande" #: ../contents/ui/ConfigAppearance.qml msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" -msgid "Automatically set to Large when in Touch Mode" -msgstr "Definir automaticamente para grande no \"Touch Mode\"" +msgid "Automatically set to Large when in Touch mode" +msgstr "" #: ../contents/ui/ConfigBehavior.qml msgid "Display:" @@ -196,186 +289,219 @@ msgid "Show icons only" msgstr "Exibir apenas os ícones" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox how to group tasks" msgid "Group:" -msgstr "Agrupar pelo:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox how to group tasks" msgid "Do not group" -msgstr "Não agrupe" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox how to group tasks" msgid "By program name" -msgstr "Nome do programa" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox completes sentence like: … cycles through tasks" msgid "Clicking grouped task:" -msgstr "Ao clicar em tarefas agrupadas:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Completes the sentence 'Clicking grouped task cycles through tasks' " +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task cycles through tasks' " msgid "Cycles through tasks" -msgstr "Percorra entre as tarefas" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Completes the sentence 'Clicking grouped task shows tooltip window thumbnails' " -msgid "Shows tooltip window thumbnails" -msgstr "Mostre as visualizações da janela" +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows small window previews' " +msgid "Shows small window previews" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Completes the sentence 'Clicking grouped task shows windows side by side' " -msgid "Shows windows side by side" -msgstr "Mostre as janelas lado a lado" +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows large window previews' " +msgid "Shows large window previews" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Completes the sentence 'Clicking grouped task shows textual list' " +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows textual list' " msgid "Shows textual list" -msgstr "Mostre uma lista com seus títulos" - -#: ../contents/ui/ConfigBehavior.qml -msgid "Tooltips are disabled, so the windows will be displayed side by side instead." -msgstr "As visualizações estão desativada, portanto as janelas serão exibidas lado a lado" - -#: ../contents/ui/ConfigBehavior.qml -msgid "Tooltips are disabled, and the compositor does not support displaying windows side by side, so a textual list will be displayed instead" -msgstr "As visualizações estão desativada e o compositor não suporta exibir as janelas lado a lado, portanto as janelas serão exibidas atráves da lista de títulos" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@info displayed as InlineMessage" msgid "The compositor does not support displaying windows side by side, so a textual list will be displayed instead." -msgstr "O compositor não suporta exibir as janelas lado a lado, portanto as janelas serão exibidas atráves da lista de títulos" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check grouped task" msgid "Combine into single button" -msgstr "Combine em um único botão" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check grouped task" msgid "Group only when the Task Manager is full" -msgstr "Agrupe apenas quando o gerenciador de tarefas estiver cheio" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox sort tasks in grouped task" msgid "Sort:" -msgstr "Organizar:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Do not sort" -msgstr "Não organize" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Manually" -msgstr "Manualmente" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Alphabetically" -msgstr "Alfabeticamente" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "By desktop" -msgstr "Por área de trabalho" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "By activity" -msgstr "Por Atividade" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check configure task sorting" msgid "Keep launchers separate" -msgstr "Manter launchers separados " +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check for icons-and-text task manager" +msgid "Hide launchers after application startup" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgctxt "@label for checkbox Part of a sentence: 'Clicking active task minimizes the task'" msgid "Clicking active task:" -msgstr "Clicando em tarefas abertas:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgctxt "@option:check Part of a sentence: 'Clicking active task minimizes the task'" msgid "Minimizes the task" -msgstr "Minimize a tarefa" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox completes sentence like: … does nothing" msgid "Middle-clicking any task:" -msgstr "Clicando no botão do scroll em qualquer tarefa:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task does nothing'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task does nothing'" msgid "Does nothing" -msgstr "Não faz nada" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task closes window or group'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task closes window or group'" msgid "Closes window or group" -msgstr "Fecha a janela ou o grupo de janelas" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task opens a new window'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task opens a new window'" msgid "Opens a new window" -msgstr "Abre uma nova janela" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" msgid "Minimizes/Restores window or group" -msgstr "Minimiza/restaura a janela ou grupo de janelas" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task toggles grouping'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task toggles grouping'" msgid "Toggles grouping" -msgstr "Agrupa/desagrupa janelas" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" msgid "Brings it to the current virtual desktop" -msgstr "Traz para a área de trabalho virtual atual" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgctxt "@label for checkbox Part of a sentence: 'Mouse wheel cycles through tasks'" msgid "Mouse wheel:" -msgstr "Scroll do mouse" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgctxt "@option:check Part of a sentence: 'Mouse wheel cycles through tasks'" msgid "Cycles through tasks" -msgstr "Percorre entre as tarefas" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check mouse wheel task cycling" msgid "Skip minimized tasks" -msgstr "Ignorar tarefas minimizadas" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for checkbox group, completes sentence like: … from current screen" msgid "Show only tasks:" -msgstr "Exibir apenas tarefas:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "From current screen" -msgstr "No monitor atual" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "From current desktop" -msgstr "Na área de trabalho atual" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "From current activity" -msgstr "Na atividade atual" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "That are minimized" -msgstr "Que estão minimizadas" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for checkbox, completes sentence: … unhide if window wants attention" msgid "When panel is hidden:" -msgstr "Quando o painel está ocultado:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: When panel is hidden" msgid "Unhide when a window wants attention" -msgstr "Desocultar quando uma janela necessita de atenção" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for radiobutton group completes sentence like: … on the bottom" msgid "New tasks appear:" -msgstr "Novas tarefas aparecem:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" +msgid "On the bottom" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" msgid "To the right" -msgstr "Na direita" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" msgid "To the left" -msgstr "Na esquerda" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" +msgid "On the top" +msgstr "" #: ../contents/ui/ConfigIndicators.qml msgid "Indicators:" @@ -509,6 +635,50 @@ msgstr "Cor do indicador:" msgid "Use plasma accent color" msgstr "Usar cor de acentuação do Plasma" +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Application" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Search applications..." +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Web Browser" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default File Manager" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Mail Client" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Application" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add applications to pin to the taskbar. Drag items to reorder them." +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Remove" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Application..." +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Special Launcher..." +msgstr "" + #: ../contents/ui/ContextMenu.qml msgid "Places" msgstr "Locais" @@ -576,11 +746,6 @@ msgstr "Mover ¶ a área de trabalho atual" msgid "&All Desktops" msgstr "&Todas as áreas de trabalho" -#: ../contents/ui/ContextMenu.qml -msgctxt "1 = number of desktop, 2 = desktop name" -msgid "&%1 %2" -msgstr "&%1 %2" - #: ../contents/ui/ContextMenu.qml msgid "&New Desktop" msgstr "&Nova área de trabalho" @@ -657,10 +822,42 @@ msgstr "&Sombreado" msgid "Allow this program to be grouped" msgstr "Permitir que este programa seja agrupado" +#: ../contents/ui/ContextMenu.qml +msgctxt "@item:inmenu" +msgid "&Close All" +msgstr "" + #: ../contents/ui/ContextMenu.qml msgid "&Close" msgstr "&Fechar" +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 application name" +msgid "Launch %1" +msgstr "" + +#: ../contents/ui/Task.qml +msgctxt "@info:tooltip" +msgid "There is %1 new message." +msgid_plural "There are %1 new messages." +msgstr[0] "" +msgstr[1] "" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Show Task tooltip for %1" +msgstr "" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Show windows side by side for %1" +msgstr "" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Open textual list of windows for %1" +msgstr "" + #: ../contents/ui/Task.qml msgid "Activate %1" msgstr "Ativo %1" @@ -714,3 +911,178 @@ msgstr "Disponível também em %1" msgctxt "Which activities a window is currently on" msgid "Available on %1" msgstr "Disponível em %1" + +#~ msgid "General:" +#~ msgstr "Geral" + +#~ msgid "Show tooltips" +#~ msgstr "Mostrar visualizações" + +#~ msgid "Highlight windows when hovering over task tooltips" +#~ msgstr "Destacar janelas quando passar o cursor sobre as visualizações" + +#~ msgid "Mark applications that play audio" +#~ msgstr "Marque os programas que estiverem tocando áudio" + +#~ msgid "Maximum columns:" +#~ msgstr "Máximo de colunas:" + +#~ msgid "Maximum rows:" +#~ msgstr "Máximo de linhas" + +#~ msgid "Always arrange tasks in rows of as many columns" +#~ msgstr "Sempre organize as tarefas em linhas com o máximo de colunas" + +#~ msgid "Always arrange tasks in columns of as many rows" +#~ msgstr "Sempre organize as tarefas em colunas com o máximo de linhas" + +#~ msgid "Spacing between icons:" +#~ msgstr "Espaço entre os ícones:" + +#~ msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" +#~ msgid "Automatically set to Large when in Touch Mode" +#~ msgstr "Definir automaticamente para grande no \"Touch Mode\"" + +#~ msgid "Group:" +#~ msgstr "Agrupar pelo:" + +#~ msgid "Do not group" +#~ msgstr "Não agrupe" + +#~ msgid "By program name" +#~ msgstr "Nome do programa" + +#~ msgid "Clicking grouped task:" +#~ msgstr "Ao clicar em tarefas agrupadas:" + +#~ msgctxt "Completes the sentence 'Clicking grouped task cycles through tasks' " +#~ msgid "Cycles through tasks" +#~ msgstr "Percorra entre as tarefas" + +#~ msgctxt "Completes the sentence 'Clicking grouped task shows tooltip window thumbnails' " +#~ msgid "Shows tooltip window thumbnails" +#~ msgstr "Mostre as visualizações da janela" + +#~ msgctxt "Completes the sentence 'Clicking grouped task shows windows side by side' " +#~ msgid "Shows windows side by side" +#~ msgstr "Mostre as janelas lado a lado" + +#~ msgctxt "Completes the sentence 'Clicking grouped task shows textual list' " +#~ msgid "Shows textual list" +#~ msgstr "Mostre uma lista com seus títulos" + +#~ msgid "Tooltips are disabled, so the windows will be displayed side by side instead." +#~ msgstr "As visualizações estão desativada, portanto as janelas serão exibidas lado a lado" + +#~ msgid "Tooltips are disabled, and the compositor does not support displaying windows side by side, so a textual list will be displayed instead" +#~ msgstr "As visualizações estão desativada e o compositor não suporta exibir as janelas lado a lado, portanto as janelas serão exibidas atráves da lista de títulos" + +#~ msgid "The compositor does not support displaying windows side by side, so a textual list will be displayed instead." +#~ msgstr "O compositor não suporta exibir as janelas lado a lado, portanto as janelas serão exibidas atráves da lista de títulos" + +#~ msgid "Combine into single button" +#~ msgstr "Combine em um único botão" + +#~ msgid "Group only when the Task Manager is full" +#~ msgstr "Agrupe apenas quando o gerenciador de tarefas estiver cheio" + +#~ msgid "Sort:" +#~ msgstr "Organizar:" + +#~ msgid "Do not sort" +#~ msgstr "Não organize" + +#~ msgid "Manually" +#~ msgstr "Manualmente" + +#~ msgid "Alphabetically" +#~ msgstr "Alfabeticamente" + +#~ msgid "By desktop" +#~ msgstr "Por área de trabalho" + +#~ msgid "By activity" +#~ msgstr "Por Atividade" + +#~ msgid "Keep launchers separate" +#~ msgstr "Manter launchers separados " + +#~ msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +#~ msgid "Clicking active task:" +#~ msgstr "Clicando em tarefas abertas:" + +#~ msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +#~ msgid "Minimizes the task" +#~ msgstr "Minimize a tarefa" + +#~ msgid "Middle-clicking any task:" +#~ msgstr "Clicando no botão do scroll em qualquer tarefa:" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task does nothing'" +#~ msgid "Does nothing" +#~ msgstr "Não faz nada" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task closes window or group'" +#~ msgid "Closes window or group" +#~ msgstr "Fecha a janela ou o grupo de janelas" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task opens a new window'" +#~ msgid "Opens a new window" +#~ msgstr "Abre uma nova janela" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" +#~ msgid "Minimizes/Restores window or group" +#~ msgstr "Minimiza/restaura a janela ou grupo de janelas" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task toggles grouping'" +#~ msgid "Toggles grouping" +#~ msgstr "Agrupa/desagrupa janelas" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" +#~ msgid "Brings it to the current virtual desktop" +#~ msgstr "Traz para a área de trabalho virtual atual" + +#~ msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +#~ msgid "Mouse wheel:" +#~ msgstr "Scroll do mouse" + +#~ msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +#~ msgid "Cycles through tasks" +#~ msgstr "Percorre entre as tarefas" + +#~ msgid "Skip minimized tasks" +#~ msgstr "Ignorar tarefas minimizadas" + +#~ msgid "Show only tasks:" +#~ msgstr "Exibir apenas tarefas:" + +#~ msgid "From current screen" +#~ msgstr "No monitor atual" + +#~ msgid "From current desktop" +#~ msgstr "Na área de trabalho atual" + +#~ msgid "From current activity" +#~ msgstr "Na atividade atual" + +#~ msgid "That are minimized" +#~ msgstr "Que estão minimizadas" + +#~ msgid "When panel is hidden:" +#~ msgstr "Quando o painel está ocultado:" + +#~ msgid "Unhide when a window wants attention" +#~ msgstr "Desocultar quando uma janela necessita de atenção" + +#~ msgid "New tasks appear:" +#~ msgstr "Novas tarefas aparecem:" + +#~ msgid "To the right" +#~ msgstr "Na direita" + +#~ msgid "To the left" +#~ msgstr "Na esquerda" + +#~ msgctxt "1 = number of desktop, 2 = desktop name" +#~ msgid "&%1 %2" +#~ msgstr "&%1 %2" diff --git a/package/translate/ru_RU.po b/package/translate/ru_RU.po new file mode 100644 index 00000000..9a063570 --- /dev/null +++ b/package/translate/ru_RU.po @@ -0,0 +1,978 @@ +# Translation of Fancy Tasks in Russian +# Copyright (C) 2025 +# +msgid "" +msgstr "" +"Project-Id-Version: Fancy Tasks\n" +"Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" +"POT-Creation-Date: 2025-12-22 13:42+0200\n" +"PO-Revision-Date: 2025-12-22 13:00+0300\n" +"Last-Translator: Vitaliy Elin \n" +"Language-Team: Russian\n" +"Language: ru_RU\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%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: ../contents/config/config.qml +msgid "Appearance" +msgstr "Внешний вид" + +#: ../contents/config/config.qml +msgid "Behavior" +msgstr "Поведение" + +#: ../contents/config/config.qml +msgid "Indicators" +msgstr "Индикаторы" + +#: ../contents/config/config.qml +msgid "Pinned Applications" +msgstr "Закрепленные приложения" + +#: ../contents/ui/AudioStream.qml +msgctxt "@action:button" +msgid "Unmute" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@action:button" +msgid "Mute" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@info:tooltip %1 is the window title" +msgid "Unmute %1" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@info:tooltip %1 is the window title" +msgid "Mute %1" +msgstr "" + +#: ../contents/ui/Badge.qml +msgctxt "Invalid number of new messages, overlay, keep short" +msgid "—" +msgstr "—" + +#: ../contents/ui/Badge.qml +msgctxt "Over 9999 new messages, overlay, keep short" +msgid "9,999+" +msgstr "9,999+" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Use plasma borders" +msgstr "Использовать рамки Plasma" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Icon Scale" +msgstr "Масштаб значков" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Icon Hover Effects" +msgstr "Эффекты наведения" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Icon zoom factor (px):" +msgstr "Увеличение значка (px):" + +#: ../contents/ui/ConfigAppearance.qml +msgid "How much the icon should grow when hovered (in pixels)" +msgstr "На сколько пикселей увеличится значок при наведении" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Zoom animation duration (ms):" +msgstr "Длительность анимации (мс):" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Duration of the zoom animation in milliseconds" +msgstr "Длительность анимации увеличения в миллисекундах" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Icon Size (px):" +msgstr "Размер значков (px):" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Set icon size instead of scaling" +msgstr "Задать размер значков вместо масштабирования" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Button Colors:" +msgstr "Цвета кнопок:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Using Plasma Style/Accent" +msgstr "Использовать стиль Plasma/Акцент" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Using Color Overlay" +msgstr "Использовать наложение цвета" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Use dominant icon color" +msgstr "Использовать основной цвет значка" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Custom Color:" +msgstr "Свой цвет:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Colorize inactive buttons" +msgstr "Окрашивать неактивные кнопки" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Plasma Button Decorations:" +msgstr "Декорации кнопок Plasma:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Disable All" +msgstr "Отключить все" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Disable Inactive Buttons" +msgstr "Отключить неактивные кнопки" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Plasma Button Direction:" +msgstr "Направление кнопок Plasma:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Override" +msgstr "Переопределить" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Be sure to use this when using as a floating widget" +msgstr "Используйте это, если виджет плавающий" + +#: ../contents/ui/ConfigAppearance.qml +msgid "North" +msgstr "Север" + +#: ../contents/ui/ConfigAppearance.qml +msgid "South" +msgstr "Юг" + +#: ../contents/ui/ConfigAppearance.qml +msgid "West" +msgstr "Запад" + +#: ../contents/ui/ConfigAppearance.qml +msgid "East" +msgstr "Восток" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Maximum button length (px):" +msgstr "Макс. длина кнопки (px):" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Space between taskbar items (px):" +msgstr "Расстояние между элементами (px):" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label for several checkboxes" +msgid "General:" +msgstr "Общие:" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:check section General" +msgid "Show small window previews when hovering over tasks" +msgstr "Показывать миниатюры окон при наведении" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:check section General" +msgid "Hide other windows when hovering over previews" +msgstr "Скрывать остальные окна при наведении на миниатюру" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:check section General" +msgid "Mark applications that play audio" +msgstr "Помечать приложения, воспроизводящие звук" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:check section General" +msgid "Fill free space on panel" +msgstr "Заполнять свободное место панели" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:listbox" +msgid "Maximum task width:" +msgstr "Макс. ширина задачи:" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Narrow" +msgstr "Узкая" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Medium" +msgstr "Средняя" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Wide" +msgstr "Широкая" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label for radio button group, completes sentence: … when panel is low on space etc." +msgid "Use multi-column view:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label for radio button group, completes sentence: … when panel is low on space etc." +msgid "Use multi-row view:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio Never use multi-column view for Task Manager" +msgid "Never" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio completes sentence: Use multi-column/row view" +msgid "When panel is low on space and thick enough" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio completes sentence: Use multi-column/row view" +msgid "Always when panel is thick enough" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:spinbox maximum number of columns for tasks" +msgid "Maximum columns:" +msgstr "Макс. столбцов:" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:spinbox maximum number of rows for tasks" +msgid "Maximum rows:" +msgstr "Макс. строк:" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:listbox" +msgid "Spacing between icons:" +msgstr "Интервал между значками:" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Small" +msgstr "Маленький" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Normal" +msgstr "Обычный" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Large" +msgstr "Большой" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" +msgid "Automatically set to Large when in Touch mode" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Display:" +msgstr "Отображение:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Show task names" +msgstr "Показывать названия задач" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Show icons only" +msgstr "Только значки" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox how to group tasks" +msgid "Group:" +msgstr "Группировка:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox how to group tasks" +msgid "Do not group" +msgstr "Не группировать" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox how to group tasks" +msgid "By program name" +msgstr "По имени программы" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox completes sentence like: … cycles through tasks" +msgid "Clicking grouped task:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task cycles through tasks' " +msgid "Cycles through tasks" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows small window previews' " +msgid "Shows small window previews" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows large window previews' " +msgid "Shows large window previews" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows textual list' " +msgid "Shows textual list" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@info displayed as InlineMessage" +msgid "The compositor does not support displaying windows side by side, so a textual list will be displayed instead." +msgstr "Композитор не поддерживает показ окон рядом, будет показан текстовый список." + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check grouped task" +msgid "Combine into single button" +msgstr "Объединять в одну кнопку" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check grouped task" +msgid "Group only when the Task Manager is full" +msgstr "Группировать только при заполнении панели" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox sort tasks in grouped task" +msgid "Sort:" +msgstr "Сортировка:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" +msgid "Do not sort" +msgstr "Не сортировать" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" +msgid "Manually" +msgstr "Вручную" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" +msgid "Alphabetically" +msgstr "По алфавиту" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" +msgid "By desktop" +msgstr "По рабочим столам" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" +msgid "By activity" +msgstr "По комнатам" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check configure task sorting" +msgid "Keep launchers separate" +msgstr "Держать значки запуска отдельно" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check for icons-and-text task manager" +msgid "Hide launchers after application startup" +msgstr "Скрывать значки запуска после старта приложения" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for checkbox Part of a sentence: 'Clicking active task minimizes the task'" +msgid "Clicking active task:" +msgstr "Нажатие на активную задачу:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check Part of a sentence: 'Clicking active task minimizes the task'" +msgid "Minimizes the task" +msgstr "Сворачивает задачу" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox completes sentence like: … does nothing" +msgid "Middle-clicking any task:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task does nothing'" +msgid "Does nothing" +msgstr "Ничего не делает" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task closes window or group'" +msgid "Closes window or group" +msgstr "Закрывает окно или группу" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task opens a new window'" +msgid "Opens a new window" +msgstr "Открывает новое окно" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" +msgid "Minimizes/Restores window or group" +msgstr "Сворачивает/Восстанавливает окно или группу" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task toggles grouping'" +msgid "Toggles grouping" +msgstr "Переключает группировку" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" +msgid "Brings it to the current virtual desktop" +msgstr "Переносит на текущий рабочий стол" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for checkbox Part of a sentence: 'Mouse wheel cycles through tasks'" +msgid "Mouse wheel:" +msgstr "Колесо мыши:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check Part of a sentence: 'Mouse wheel cycles through tasks'" +msgid "Cycles through tasks" +msgstr "Переключает задачи" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check mouse wheel task cycling" +msgid "Skip minimized tasks" +msgstr "Пропускать свернутые" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for checkbox group, completes sentence like: … from current screen" +msgid "Show only tasks:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" +msgid "From current screen" +msgstr "С текущего экрана" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" +msgid "From current desktop" +msgstr "С текущего рабочего стола" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" +msgid "From current activity" +msgstr "Из текущей комнаты" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" +msgid "That are minimized" +msgstr "Которые свернуты" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for checkbox, completes sentence: … unhide if window wants attention" +msgid "When panel is hidden:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: When panel is hidden" +msgid "Unhide when a window wants attention" +msgstr "Показывать, если окно требует внимания" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for radiobutton group completes sentence like: … on the bottom" +msgid "New tasks appear:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" +msgid "On the bottom" +msgstr "Снизу" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" +msgid "To the right" +msgstr "Справа" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" +msgid "To the left" +msgstr "Слева" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" +msgid "On the top" +msgstr "Сверху" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicators:" +msgstr "Индикаторы:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Disabled" +msgstr "Отключены" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Enabled" +msgstr "Включены" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Display Progress on Indicator" +msgstr "Показывать прогресс на индикаторе" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Progress Color:" +msgstr "Цвет прогресса:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Disable for Inactive Windows" +msgstr "Отключить для неактивных окон" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Group Overlay:" +msgstr "Наложение группы:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Takes effect on next time plasma groups tasks." +msgstr "Применится при следующей группировке задач." + +#: ../contents/ui/ConfigIndicators.qml +msgid "Animate Indicators:" +msgstr "Анимация индикаторов:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Location:" +msgstr "Расположение индикатора:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Reverse shown side" +msgstr "Инвертировать сторону" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Override location" +msgstr "Переопределить положение" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Bottom" +msgstr "Снизу" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Left" +msgstr "Слева" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Right" +msgstr "Справа" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Top" +msgstr "Сверху" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Edge Offset (px):" +msgstr "Отступ от края (px):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Style:" +msgstr "Стиль индикатора:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Metro" +msgstr "Metro" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Ciliora" +msgstr "Ciliora" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Dashes" +msgstr "Тире" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Min Limit:" +msgstr "Мин. предел индикатора:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Max Limit:" +msgstr "Макс. предел индикатора:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Minimize Options:" +msgstr "Параметры сворачивания:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Desaturate" +msgstr "Обесцветить" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Shrink when minimized" +msgstr "Уменьшать при сворачивании" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Growth/Shrink factor:" +msgstr "Коэффициент роста/уменьшения:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator size (px):" +msgstr "Размер индикатора (px):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator length (px):" +msgstr "Длина индикатора (px):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Radius (%):" +msgstr "Радиус индикатора (%):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator margin (px):" +msgstr "Отступ индикатора (px):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Color:" +msgstr "Цвет индикатора:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Use plasma accent color" +msgstr "Использовать цвет акцента Plasma" + +# --- ConfigPinnedApps.qml --- +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Application" +msgstr "Добавить приложение" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Search applications..." +msgstr "Поиск приложений..." + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add" +msgstr "Добавить" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Web Browser" +msgstr "Браузер по умолчанию" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default File Manager" +msgstr "Файловый менеджер" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Mail Client" +msgstr "Почтовый клиент" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Application" +msgstr "Приложение по умолчанию" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add applications to pin to the taskbar. Drag items to reorder them." +msgstr "Добавьте приложения для закрепления. Перетаскивайте элементы для изменения порядка." + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Remove" +msgstr "Удалить" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Application..." +msgstr "Добавить приложение..." + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Special Launcher..." +msgstr "Добавить спец. запуск..." + +# --- ContextMenu.qml --- +#: ../contents/ui/ContextMenu.qml +msgid "Places" +msgstr "Точки входа" + +#: ../contents/ui/ContextMenu.qml +msgid "Recent Files" +msgstr "Недавние файлы" + +#: ../contents/ui/ContextMenu.qml +msgid "Actions" +msgstr "Действия" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Play previous track" +msgid "Previous Track" +msgstr "Предыдущий трек" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Pause playback" +msgid "Pause" +msgstr "Пауза" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Start playback" +msgid "Play" +msgstr "Воспроизвести" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Play next track" +msgid "Next Track" +msgstr "Следующий трек" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Stop playback" +msgid "Stop" +msgstr "Стоп" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Quit media player app" +msgid "Quit" +msgstr "Выйти" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Open or bring to the front window of media player app" +msgid "Restore" +msgstr "Восстановить" + +#: ../contents/ui/ContextMenu.qml +msgid "Mute" +msgstr "Выключить звук" + +#: ../contents/ui/ContextMenu.qml +msgid "Open New Window" +msgstr "Открыть новое окно" + +#: ../contents/ui/ContextMenu.qml +msgid "Move to &Desktop" +msgstr "Переместить на &рабочий стол" + +#: ../contents/ui/ContextMenu.qml +msgid "Move &To Current Desktop" +msgstr "Переместить на &текущий рабочий стол" + +#: ../contents/ui/ContextMenu.qml +msgid "&All Desktops" +msgstr "&Все рабочие столы" + +#: ../contents/ui/ContextMenu.qml +msgid "&New Desktop" +msgstr "&Новый рабочий стол" + +#: ../contents/ui/ContextMenu.qml +msgid "Show in &Activities" +msgstr "Показать в &комнатах" + +#: ../contents/ui/ContextMenu.qml +msgid "Add To Current Activity" +msgstr "Добавить в текущую комнату" + +#: ../contents/ui/ContextMenu.qml +msgid "All Activities" +msgstr "Все комнаты" + +#: ../contents/ui/ContextMenu.qml +msgid "Move to %1" +msgstr "Переместить в %1" + +#: ../contents/ui/ContextMenu.qml +msgid "&Pin to Task Manager" +msgstr "&Закрепить в панели задач" + +#: ../contents/ui/ContextMenu.qml +msgid "On All Activities" +msgstr "Во всех комнатах" + +#: ../contents/ui/ContextMenu.qml +msgid "On The Current Activity" +msgstr "В текущей комнате" + +#: ../contents/ui/ContextMenu.qml +msgid "Unpin from Task Manager" +msgstr "Открепить от панели задач" + +#: ../contents/ui/ContextMenu.qml +msgid "More" +msgstr "Еще" + +#: ../contents/ui/ContextMenu.qml +msgid "&Move" +msgstr "&Переместить" + +#: ../contents/ui/ContextMenu.qml +msgid "Re&size" +msgstr "И&зменить размер" + +#: ../contents/ui/ContextMenu.qml +msgid "Ma&ximize" +msgstr "&Распахнуть" + +#: ../contents/ui/ContextMenu.qml +msgid "Mi&nimize" +msgstr "&Свернуть" + +#: ../contents/ui/ContextMenu.qml +msgid "Keep &Above Others" +msgstr "Поверх &других окон" + +#: ../contents/ui/ContextMenu.qml +msgid "Keep &Below Others" +msgstr "На &заднем плане" + +#: ../contents/ui/ContextMenu.qml +msgid "&Fullscreen" +msgstr "&Полноэкранный режим" + +#: ../contents/ui/ContextMenu.qml +msgid "&Shade" +msgstr "&Свернуть в заголовок" + +#: ../contents/ui/ContextMenu.qml +msgid "Allow this program to be grouped" +msgstr "Разрешить группировку этой программы" + +#: ../contents/ui/ContextMenu.qml +msgctxt "@item:inmenu" +msgid "&Close All" +msgstr "&Закрыть все" + +#: ../contents/ui/ContextMenu.qml +msgid "&Close" +msgstr "&Закрыть" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 application name" +msgid "Launch %1" +msgstr "Запустить %1" + +#: ../contents/ui/Task.qml +msgctxt "@info:tooltip" +msgid "There is %1 new message." +msgid_plural "There are %1 new messages." +msgstr[0] "Новых сообщений: %1." +msgstr[1] "Новых сообщений: %1." +msgstr[2] "Новых сообщений: %1." + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Show Task tooltip for %1" +msgstr "Показать подсказку для %1" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Show windows side by side for %1" +msgstr "Показать окна рядом для %1" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Open textual list of windows for %1" +msgstr "Открыть список окон для %1" + +#: ../contents/ui/Task.qml +msgid "Activate %1" +msgstr "Активировать %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "button to unmute app" +msgid "Unmute %1" +msgstr "Включить звук %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "button to mute app" +msgid "Mute %1" +msgstr "Выключить звук %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Accessibility data on volume slider" +msgid "Adjust volume for %1" +msgstr "Регулировка громкости для %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "volume percentage" +msgid "%1%" +msgstr "%1%" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "only used for sizing, should be widest possible string" +msgid "100%" +msgstr "100%" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Comma-separated list of desktops" +msgid "On %1" +msgstr "На %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Comma-separated list of desktops" +msgid "Pinned to all desktops" +msgstr "Закреплено на всех рабочих столах" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Which virtual desktop a window is currently on" +msgid "Available on all activities" +msgstr "Доступно во всех комнатах" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Activities a window is currently on (apart from the current one)" +msgid "Also available on %1" +msgstr "Также доступно в %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Which activities a window is currently on" +msgid "Available on %1" +msgstr "Доступно в %1" + +#~ msgctxt "@label for radio button group" +#~ msgid "Use multi-column view:" +#~ msgstr "Многоколоночный вид:" + +#~ msgctxt "@label for radio button group" +#~ msgid "Use multi-row view:" +#~ msgstr "Многострочный вид:" + +#~ msgctxt "@option:radio Never use multi-column view" +#~ msgid "Never" +#~ msgstr "Никогда" + +#~ msgctxt "@option:radio" +#~ msgid "When panel is low on space and thick enough" +#~ msgstr "Когда мало места и панель широкая" + +#~ msgctxt "@option:radio" +#~ msgid "Always when panel is thick enough" +#~ msgstr "Всегда, если панель достаточно широкая" + +#~ msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" +#~ msgid "Automatically set to Large when in Touch Mode" +#~ msgstr "Автоматически «Большой» в сенсорном режиме" + +#~ msgctxt "@label:listbox" +#~ msgid "Clicking grouped task:" +#~ msgstr "Нажатие на сгруппированную задачу:" + +#~ msgctxt "Completes the sentence 'Clicking grouped task cycles through tasks' " +#~ msgid "Cycles through tasks" +#~ msgstr "Переключает задачи" + +#~ msgctxt "Completes the sentence 'Clicking grouped task shows tooltip window thumbnails' " +#~ msgid "Shows small window previews" +#~ msgstr "Показывает миниатюры окон" + +#~ msgctxt "Completes the sentence 'Clicking grouped task shows large window previews' " +#~ msgid "Shows large window previews" +#~ msgstr "Показывает большие превью" + +#~ msgctxt "Completes the sentence 'Clicking grouped task shows textual list' " +#~ msgid "Shows textual list" +#~ msgstr "Показывает текстовый список" + +#~ msgctxt "@label:listbox" +#~ msgid "Middle-clicking any task:" +#~ msgstr "Средняя кнопка мыши:" + +#~ msgctxt "@label for checkbox group" +#~ msgid "Show only tasks:" +#~ msgstr "Показывать только задачи:" + +#~ msgctxt "@label for checkbox" +#~ msgid "When panel is hidden:" +#~ msgstr "Когда панель скрыта:" + +#~ msgctxt "@label for radiobutton group" +#~ msgid "New tasks appear:" +#~ msgstr "Новые задачи появляются:" + +#~ msgctxt "1 = number of desktop, 2 = desktop name" +#~ msgid "&%1 %2" +#~ msgstr "&%1 %2" diff --git a/package/translate/template.pot b/package/translate/template.pot index c07803f3..60b81319 100644 --- a/package/translate/template.pot +++ b/package/translate/template.pot @@ -1,14 +1,14 @@ -# Translation of Fancy Tasks in LANGUAGE -# Copyright (C) 2023 -# This file is distributed under the same license as the Fancy Tasks package. +# Translation of fancytasks in LANGUAGE +# Copyright (C) 2025 +# This file is distributed under the same license as the fancytasks package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Fancy Tasks\n" +"Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-13 22:51-0600\n" +"POT-Creation-Date: 2025-12-22 13:42+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,6 +16,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #: ../contents/config/config.qml msgid "Appearance" @@ -29,6 +30,30 @@ msgstr "" msgid "Indicators" msgstr "" +#: ../contents/config/config.qml +msgid "Pinned Applications" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@action:button" +msgid "Unmute" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@action:button" +msgid "Mute" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@info:tooltip %1 is the window title" +msgid "Unmute %1" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@info:tooltip %1 is the window title" +msgid "Mute %1" +msgstr "" + #: ../contents/ui/Badge.qml msgctxt "Invalid number of new messages, overlay, keep short" msgid "—" @@ -40,27 +65,31 @@ msgid "9,999+" msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "General:" +msgid "Use plasma borders" msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Show tooltips" +msgid "Icon Scale" msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Highlight windows when hovering over task tooltips" +msgid "Icon Hover Effects" msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Mark applications that play audio" +msgid "Icon zoom factor (px):" msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Use plasma borders" +msgid "How much the icon should grow when hovered (in pixels)" msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Icon Scale" +msgid "Zoom animation duration (ms):" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Duration of the zoom animation in milliseconds" msgstr "" #: ../contents/ui/ConfigAppearance.qml @@ -136,30 +165,95 @@ msgid "East" msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Maximum columns:" +msgid "Maximum button length (px):" msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Maximum rows:" +msgid "Space between taskbar items (px):" msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Always arrange tasks in rows of as many columns" +msgctxt "@label for several checkboxes" +msgid "General:" msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Always arrange tasks in columns of as many rows" +msgctxt "@option:check section General" +msgid "Show small window previews when hovering over tasks" msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Maximum button length (px):" +msgctxt "@option:check section General" +msgid "Hide other windows when hovering over previews" msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Space between taskbar items (px):" +msgctxt "@option:check section General" +msgid "Mark applications that play audio" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:check section General" +msgid "Fill free space on panel" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:listbox" +msgid "Maximum task width:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Narrow" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Medium" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Wide" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label for radio button group, completes sentence: … when panel is low on space etc." +msgid "Use multi-column view:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label for radio button group, completes sentence: … when panel is low on space etc." +msgid "Use multi-row view:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio Never use multi-column view for Task Manager" +msgid "Never" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio completes sentence: Use multi-column/row view" +msgid "When panel is low on space and thick enough" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio completes sentence: Use multi-column/row view" +msgid "Always when panel is thick enough" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:spinbox maximum number of columns for tasks" +msgid "Maximum columns:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:spinbox maximum number of rows for tasks" +msgid "Maximum rows:" msgstr "" #: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:listbox" msgid "Spacing between icons:" msgstr "" @@ -180,7 +274,7 @@ msgstr "" #: ../contents/ui/ConfigAppearance.qml msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" -msgid "Automatically set to Large when in Touch Mode" +msgid "Automatically set to Large when in Touch mode" msgstr "" #: ../contents/ui/ConfigBehavior.qml @@ -196,187 +290,220 @@ msgid "Show icons only" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox how to group tasks" msgid "Group:" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox how to group tasks" msgid "Do not group" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox how to group tasks" msgid "By program name" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox completes sentence like: … cycles through tasks" msgid "Clicking grouped task:" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Completes the sentence 'Clicking grouped task cycles through tasks' " +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task cycles through tasks' " msgid "Cycles through tasks" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Completes the sentence 'Clicking grouped task shows tooltip window thumbnails' " -msgid "Shows tooltip window thumbnails" +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows small window previews' " +msgid "Shows small window previews" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Completes the sentence 'Clicking grouped task shows windows side by side' " -msgid "Shows windows side by side" +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows large window previews' " +msgid "Shows large window previews" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Completes the sentence 'Clicking grouped task shows textual list' " +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows textual list' " msgid "Shows textual list" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgid "Tooltips are disabled, so the windows will be displayed side by side instead." -msgstr "" - -#: ../contents/ui/ConfigBehavior.qml -msgid "Tooltips are disabled, and the compositor does not support displaying windows side by side, so a textual list will be displayed instead" -msgstr "" - -#: ../contents/ui/ConfigBehavior.qml +msgctxt "@info displayed as InlineMessage" msgid "The compositor does not support displaying windows side by side, so a textual list will be displayed instead." msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check grouped task" msgid "Combine into single button" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check grouped task" msgid "Group only when the Task Manager is full" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox sort tasks in grouped task" msgid "Sort:" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Do not sort" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Manually" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Alphabetically" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "By desktop" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "By activity" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check configure task sorting" msgid "Keep launchers separate" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgctxt "@option:check for icons-and-text task manager" +msgid "Hide launchers after application startup" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for checkbox Part of a sentence: 'Clicking active task minimizes the task'" msgid "Clicking active task:" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgctxt "@option:check Part of a sentence: 'Clicking active task minimizes the task'" msgid "Minimizes the task" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox completes sentence like: … does nothing" msgid "Middle-clicking any task:" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task does nothing'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task does nothing'" msgid "Does nothing" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task closes window or group'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task closes window or group'" msgid "Closes window or group" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task opens a new window'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task opens a new window'" msgid "Opens a new window" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" msgid "Minimizes/Restores window or group" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task toggles grouping'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task toggles grouping'" msgid "Toggles grouping" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" msgid "Brings it to the current virtual desktop" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgctxt "@label for checkbox Part of a sentence: 'Mouse wheel cycles through tasks'" msgid "Mouse wheel:" msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgctxt "@option:check Part of a sentence: 'Mouse wheel cycles through tasks'" msgid "Cycles through tasks" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check mouse wheel task cycling" msgid "Skip minimized tasks" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for checkbox group, completes sentence like: … from current screen" msgid "Show only tasks:" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "From current screen" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "From current desktop" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "From current activity" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "That are minimized" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for checkbox, completes sentence: … unhide if window wants attention" msgid "When panel is hidden:" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: When panel is hidden" msgid "Unhide when a window wants attention" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for radiobutton group completes sentence like: … on the bottom" msgid "New tasks appear:" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" +msgid "On the bottom" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" msgid "To the right" msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" msgid "To the left" msgstr "" +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" +msgid "On the top" +msgstr "" + #: ../contents/ui/ConfigIndicators.qml msgid "Indicators:" msgstr "" @@ -509,6 +636,50 @@ msgstr "" msgid "Use plasma accent color" msgstr "" +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Application" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Search applications..." +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Web Browser" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default File Manager" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Mail Client" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Application" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add applications to pin to the taskbar. Drag items to reorder them." +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Remove" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Application..." +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Special Launcher..." +msgstr "" + #: ../contents/ui/ContextMenu.qml msgid "Places" msgstr "" @@ -576,11 +747,6 @@ msgstr "" msgid "&All Desktops" msgstr "" -#: ../contents/ui/ContextMenu.qml -msgctxt "1 = number of desktop, 2 = desktop name" -msgid "&%1 %2" -msgstr "" - #: ../contents/ui/ContextMenu.qml msgid "&New Desktop" msgstr "" @@ -657,10 +823,42 @@ msgstr "" msgid "Allow this program to be grouped" msgstr "" +#: ../contents/ui/ContextMenu.qml +msgctxt "@item:inmenu" +msgid "&Close All" +msgstr "" + #: ../contents/ui/ContextMenu.qml msgid "&Close" msgstr "" +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 application name" +msgid "Launch %1" +msgstr "" + +#: ../contents/ui/Task.qml +msgctxt "@info:tooltip" +msgid "There is %1 new message." +msgid_plural "There are %1 new messages." +msgstr[0] "" +msgstr[1] "" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Show Task tooltip for %1" +msgstr "" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Show windows side by side for %1" +msgstr "" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Open textual list of windows for %1" +msgstr "" + #: ../contents/ui/Task.qml msgid "Activate %1" msgstr "" diff --git a/package/translate/zh_CN.po b/package/translate/zh_CN.po index cae2834b..43a74aa8 100644 --- a/package/translate/zh_CN.po +++ b/package/translate/zh_CN.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-13 22:51-0600\n" +"POT-Creation-Date: 2025-12-22 13:42+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -29,6 +29,30 @@ msgstr "行为" msgid "Indicators" msgstr "指示器" +#: ../contents/config/config.qml +msgid "Pinned Applications" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@action:button" +msgid "Unmute" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@action:button" +msgid "Mute" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@info:tooltip %1 is the window title" +msgid "Unmute %1" +msgstr "" + +#: ../contents/ui/AudioStream.qml +msgctxt "@info:tooltip %1 is the window title" +msgid "Mute %1" +msgstr "" + #: ../contents/ui/Badge.qml msgctxt "Invalid number of new messages, overlay, keep short" msgid "—" @@ -40,27 +64,31 @@ msgid "9,999+" msgstr "9,999+" #: ../contents/ui/ConfigAppearance.qml -msgid "General:" -msgstr "通用:" +msgid "Use plasma borders" +msgstr "使用plasma边框" #: ../contents/ui/ConfigAppearance.qml -msgid "Show tooltips" -msgstr "显示窗口预览" +msgid "Icon Scale" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Highlight windows when hovering over task tooltips" -msgstr "悬浮在预览上时高亮对应窗口" +msgid "Icon Hover Effects" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Mark applications that play audio" -msgstr "标记正在播放音频的应用" +msgid "Icon zoom factor (px):" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Use plasma borders" -msgstr "使用plasma边框" +msgid "How much the icon should grow when hovered (in pixels)" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Icon Scale" +msgid "Zoom animation duration (ms):" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Duration of the zoom animation in milliseconds" msgstr "" #: ../contents/ui/ConfigAppearance.qml @@ -136,32 +164,97 @@ msgid "East" msgstr "东" #: ../contents/ui/ConfigAppearance.qml -msgid "Maximum columns:" -msgstr "最大列数" +msgid "Maximum button length (px):" +msgstr "最大按钮长度(px)" #: ../contents/ui/ConfigAppearance.qml -msgid "Maximum rows:" -msgstr "最大行数" +msgid "Space between taskbar items (px):" +msgstr "任务栏组件间距(px)" #: ../contents/ui/ConfigAppearance.qml -msgid "Always arrange tasks in rows of as many columns" -msgstr "始终将任务排列成多列" +msgctxt "@label for several checkboxes" +msgid "General:" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Always arrange tasks in columns of as many rows" -msgstr "始终将任务排列成多行" +msgctxt "@option:check section General" +msgid "Show small window previews when hovering over tasks" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Maximum button length (px):" -msgstr "最大按钮长度(px)" +msgctxt "@option:check section General" +msgid "Hide other windows when hovering over previews" +msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Space between taskbar items (px):" -msgstr "任务栏组件间距(px)" +msgctxt "@option:check section General" +msgid "Mark applications that play audio" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:check section General" +msgid "Fill free space on panel" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:listbox" +msgid "Maximum task width:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Narrow" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Medium" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox how wide a task item should be" +msgid "Wide" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label for radio button group, completes sentence: … when panel is low on space etc." +msgid "Use multi-column view:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label for radio button group, completes sentence: … when panel is low on space etc." +msgid "Use multi-row view:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio Never use multi-column view for Task Manager" +msgid "Never" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio completes sentence: Use multi-column/row view" +msgid "When panel is low on space and thick enough" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@option:radio completes sentence: Use multi-column/row view" +msgid "Always when panel is thick enough" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:spinbox maximum number of columns for tasks" +msgid "Maximum columns:" +msgstr "" #: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:spinbox maximum number of rows for tasks" +msgid "Maximum rows:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@label:listbox" msgid "Spacing between icons:" -msgstr "图标间距:" +msgstr "" #: ../contents/ui/ConfigAppearance.qml msgctxt "@item:inlistbox Icon spacing" @@ -180,8 +273,8 @@ msgstr "大" #: ../contents/ui/ConfigAppearance.qml msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" -msgid "Automatically set to Large when in Touch Mode" -msgstr "触摸模式下自动设置为大" +msgid "Automatically set to Large when in Touch mode" +msgstr "" #: ../contents/ui/ConfigBehavior.qml msgid "Display:" @@ -196,186 +289,219 @@ msgid "Show icons only" msgstr "只显示图标" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox how to group tasks" msgid "Group:" -msgstr "分组:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox how to group tasks" msgid "Do not group" -msgstr "不分组:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox how to group tasks" msgid "By program name" -msgstr "以程序名分组" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox completes sentence like: … cycles through tasks" msgid "Clicking grouped task:" -msgstr "点击已分组任务时:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Completes the sentence 'Clicking grouped task cycles through tasks' " +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task cycles through tasks' " msgid "Cycles through tasks" -msgstr "在任务中循环" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Completes the sentence 'Clicking grouped task shows tooltip window thumbnails' " -msgid "Shows tooltip window thumbnails" -msgstr "展示窗口预览" +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows small window previews' " +msgid "Shows small window previews" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Completes the sentence 'Clicking grouped task shows windows side by side' " -msgid "Shows windows side by side" -msgstr "并列显示窗口" +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows large window previews' " +msgid "Shows large window previews" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Completes the sentence 'Clicking grouped task shows textual list' " +msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows textual list' " msgid "Shows textual list" -msgstr "展示文字列表" - -#: ../contents/ui/ConfigBehavior.qml -msgid "Tooltips are disabled, so the windows will be displayed side by side instead." -msgstr "窗口预览已关闭,所有窗口会被并列显示" - -#: ../contents/ui/ConfigBehavior.qml -msgid "Tooltips are disabled, and the compositor does not support displaying windows side by side, so a textual list will be displayed instead" -msgstr "窗口预览已关闭,混成器不支持并列显示窗口,展示文字列表" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@info displayed as InlineMessage" msgid "The compositor does not support displaying windows side by side, so a textual list will be displayed instead." -msgstr "混成器不支持并列显示窗口,展示文字列表" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check grouped task" msgid "Combine into single button" -msgstr "组合到一个按钮中" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check grouped task" msgid "Group only when the Task Manager is full" -msgstr "仅在任务栏已满时组合" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox sort tasks in grouped task" msgid "Sort:" -msgstr "排序:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Do not sort" -msgstr "不排序" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Manually" -msgstr "手动" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Alphabetically" -msgstr "按字母" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "By desktop" -msgstr "按桌面" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@item:inlistbox sort tasks in grouped task" msgid "By activity" -msgstr "按活动" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check configure task sorting" msgid "Keep launchers separate" -msgstr "与启动器分开" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgctxt "@option:check for icons-and-text task manager" +msgid "Hide launchers after application startup" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for checkbox Part of a sentence: 'Clicking active task minimizes the task'" msgid "Clicking active task:" -msgstr "点击活动任务时:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgctxt "@option:check Part of a sentence: 'Clicking active task minimizes the task'" msgid "Minimizes the task" -msgstr "最小化" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label:listbox completes sentence like: … does nothing" msgid "Middle-clicking any task:" -msgstr "鼠标中键点击活动任务时:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task does nothing'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task does nothing'" msgid "Does nothing" -msgstr "什么都不做" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task closes window or group'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task closes window or group'" msgid "Closes window or group" -msgstr "关闭窗口或组" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task opens a new window'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task opens a new window'" msgid "Opens a new window" -msgstr "打开新窗口" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" msgid "Minimizes/Restores window or group" -msgstr "最小化/最大化窗口或组" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task toggles grouping'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task toggles grouping'" msgid "Toggles grouping" -msgstr "切换组" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" +msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" msgid "Brings it to the current virtual desktop" -msgstr "带到当前虚拟桌面" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgctxt "@label for checkbox Part of a sentence: 'Mouse wheel cycles through tasks'" msgid "Mouse wheel:" -msgstr "鼠标滚轮:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml -msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgctxt "@option:check Part of a sentence: 'Mouse wheel cycles through tasks'" msgid "Cycles through tasks" -msgstr "在任务间切换" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check mouse wheel task cycling" msgid "Skip minimized tasks" -msgstr "跳过最小化的任务" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for checkbox group, completes sentence like: … from current screen" msgid "Show only tasks:" -msgstr "只展示任务" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "From current screen" -msgstr "从当前屏幕" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "From current desktop" -msgstr "从当前桌面" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "From current activity" -msgstr "从当前活动" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: show only tasks" msgid "That are minimized" -msgstr "最小化的任务" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for checkbox, completes sentence: … unhide if window wants attention" msgid "When panel is hidden:" -msgstr "面板隐藏时:" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: When panel is hidden" msgid "Unhide when a window wants attention" -msgstr "当窗口提示时取消隐藏" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@label for radiobutton group completes sentence like: … on the bottom" msgid "New tasks appear:" -msgstr "新任务出现在:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" +msgid "On the bottom" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" msgid "To the right" -msgstr "右边" +msgstr "" #: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" msgid "To the left" -msgstr "左边" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "@option:check completes sentence: New tasks appear" +msgid "On the top" +msgstr "" #: ../contents/ui/ConfigIndicators.qml msgid "Indicators:" @@ -509,6 +635,50 @@ msgstr "指示器颜色:" msgid "Use plasma accent color" msgstr "使用plasma预设" +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Application" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Search applications..." +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Web Browser" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default File Manager" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Mail Client" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Default Application" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add applications to pin to the taskbar. Drag items to reorder them." +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Remove" +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Application..." +msgstr "" + +#: ../contents/ui/ConfigPinnedApps.qml +msgid "Add Special Launcher..." +msgstr "" + #: ../contents/ui/ContextMenu.qml msgid "Places" msgstr "位置" @@ -576,11 +746,6 @@ msgstr "移动到当前桌面" msgid "&All Desktops" msgstr "所有桌面" -#: ../contents/ui/ContextMenu.qml -msgctxt "1 = number of desktop, 2 = desktop name" -msgid "&%1 %2" -msgstr "&%1 %2" - #: ../contents/ui/ContextMenu.qml msgid "&New Desktop" msgstr "新建桌面" @@ -657,10 +822,42 @@ msgstr "折叠" msgid "Allow this program to be grouped" msgstr "允许这个程序被分组" +#: ../contents/ui/ContextMenu.qml +msgctxt "@item:inmenu" +msgid "&Close All" +msgstr "" + #: ../contents/ui/ContextMenu.qml msgid "&Close" msgstr "关闭" +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 application name" +msgid "Launch %1" +msgstr "" + +#: ../contents/ui/Task.qml +msgctxt "@info:tooltip" +msgid "There is %1 new message." +msgid_plural "There are %1 new messages." +msgstr[0] "" +msgstr[1] "" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Show Task tooltip for %1" +msgstr "" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Show windows side by side for %1" +msgstr "" + +#: ../contents/ui/Task.qml +msgctxt "@info:usagetip %1 task name" +msgid "Open textual list of windows for %1" +msgstr "" + #: ../contents/ui/Task.qml msgid "Activate %1" msgstr "活动 %1" @@ -715,6 +912,181 @@ msgctxt "Which activities a window is currently on" msgid "Available on %1" msgstr "在 %1 上可用" +#~ msgid "General:" +#~ msgstr "通用:" + +#~ msgid "Show tooltips" +#~ msgstr "显示窗口预览" + +#~ msgid "Highlight windows when hovering over task tooltips" +#~ msgstr "悬浮在预览上时高亮对应窗口" + +#~ msgid "Mark applications that play audio" +#~ msgstr "标记正在播放音频的应用" + +#~ msgid "Maximum columns:" +#~ msgstr "最大列数" + +#~ msgid "Maximum rows:" +#~ msgstr "最大行数" + +#~ msgid "Always arrange tasks in rows of as many columns" +#~ msgstr "始终将任务排列成多列" + +#~ msgid "Always arrange tasks in columns of as many rows" +#~ msgstr "始终将任务排列成多行" + +#~ msgid "Spacing between icons:" +#~ msgstr "图标间距:" + +#~ msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" +#~ msgid "Automatically set to Large when in Touch Mode" +#~ msgstr "触摸模式下自动设置为大" + +#~ msgid "Group:" +#~ msgstr "分组:" + +#~ msgid "Do not group" +#~ msgstr "不分组:" + +#~ msgid "By program name" +#~ msgstr "以程序名分组" + +#~ msgid "Clicking grouped task:" +#~ msgstr "点击已分组任务时:" + +#~ msgctxt "Completes the sentence 'Clicking grouped task cycles through tasks' " +#~ msgid "Cycles through tasks" +#~ msgstr "在任务中循环" + +#~ msgctxt "Completes the sentence 'Clicking grouped task shows tooltip window thumbnails' " +#~ msgid "Shows tooltip window thumbnails" +#~ msgstr "展示窗口预览" + +#~ msgctxt "Completes the sentence 'Clicking grouped task shows windows side by side' " +#~ msgid "Shows windows side by side" +#~ msgstr "并列显示窗口" + +#~ msgctxt "Completes the sentence 'Clicking grouped task shows textual list' " +#~ msgid "Shows textual list" +#~ msgstr "展示文字列表" + +#~ msgid "Tooltips are disabled, so the windows will be displayed side by side instead." +#~ msgstr "窗口预览已关闭,所有窗口会被并列显示" + +#~ msgid "Tooltips are disabled, and the compositor does not support displaying windows side by side, so a textual list will be displayed instead" +#~ msgstr "窗口预览已关闭,混成器不支持并列显示窗口,展示文字列表" + +#~ msgid "The compositor does not support displaying windows side by side, so a textual list will be displayed instead." +#~ msgstr "混成器不支持并列显示窗口,展示文字列表" + +#~ msgid "Combine into single button" +#~ msgstr "组合到一个按钮中" + +#~ msgid "Group only when the Task Manager is full" +#~ msgstr "仅在任务栏已满时组合" + +#~ msgid "Sort:" +#~ msgstr "排序:" + +#~ msgid "Do not sort" +#~ msgstr "不排序" + +#~ msgid "Manually" +#~ msgstr "手动" + +#~ msgid "Alphabetically" +#~ msgstr "按字母" + +#~ msgid "By desktop" +#~ msgstr "按桌面" + +#~ msgid "By activity" +#~ msgstr "按活动" + +#~ msgid "Keep launchers separate" +#~ msgstr "与启动器分开" + +#~ msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +#~ msgid "Clicking active task:" +#~ msgstr "点击活动任务时:" + +#~ msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +#~ msgid "Minimizes the task" +#~ msgstr "最小化" + +#~ msgid "Middle-clicking any task:" +#~ msgstr "鼠标中键点击活动任务时:" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task does nothing'" +#~ msgid "Does nothing" +#~ msgstr "什么都不做" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task closes window or group'" +#~ msgid "Closes window or group" +#~ msgstr "关闭窗口或组" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task opens a new window'" +#~ msgid "Opens a new window" +#~ msgstr "打开新窗口" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" +#~ msgid "Minimizes/Restores window or group" +#~ msgstr "最小化/最大化窗口或组" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task toggles grouping'" +#~ msgid "Toggles grouping" +#~ msgstr "切换组" + +#~ msgctxt "Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" +#~ msgid "Brings it to the current virtual desktop" +#~ msgstr "带到当前虚拟桌面" + +#~ msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +#~ msgid "Mouse wheel:" +#~ msgstr "鼠标滚轮:" + +#~ msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +#~ msgid "Cycles through tasks" +#~ msgstr "在任务间切换" + +#~ msgid "Skip minimized tasks" +#~ msgstr "跳过最小化的任务" + +#~ msgid "Show only tasks:" +#~ msgstr "只展示任务" + +#~ msgid "From current screen" +#~ msgstr "从当前屏幕" + +#~ msgid "From current desktop" +#~ msgstr "从当前桌面" + +#~ msgid "From current activity" +#~ msgstr "从当前活动" + +#~ msgid "That are minimized" +#~ msgstr "最小化的任务" + +#~ msgid "When panel is hidden:" +#~ msgstr "面板隐藏时:" + +#~ msgid "Unhide when a window wants attention" +#~ msgstr "当窗口提示时取消隐藏" + +#~ msgid "New tasks appear:" +#~ msgstr "新任务出现在:" + +#~ msgid "To the right" +#~ msgstr "右边" + +#~ msgid "To the left" +#~ msgstr "左边" + +#~ msgctxt "1 = number of desktop, 2 = desktop name" +#~ msgid "&%1 %2" +#~ msgstr "&%1 %2" + #~ msgid "Press OK to fix layout issues." #~ msgstr "按OK键来修复布局问题。" diff --git a/update.sh b/update.sh index a6808410..b4c5bbbd 100755 --- a/update.sh +++ b/update.sh @@ -1,14 +1,19 @@ -#!/bin/sh -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -sh $SCRIPT_DIR/build.sh -kpackagetool6 -u $SCRIPT_DIR/release/FancyTasks.tar.gz +#!/bin/bash +SCRIPT_DIR=$(dirname $(readlink -f "$0")) -# Restart plasmashell +echo "Compiling translations..." +bash "$SCRIPT_DIR/package/translate/build" + +echo "Updating plasmoid ..." +kpackagetool6 -t Plasma/Applet --upgrade "$SCRIPT_DIR/package" + +echo "Restarting Plasma..." if systemctl --user is-active --quiet plasma-plasmashell.service; then - systemctl --user restart plasma-plasmashell.service + systemctl --user restart plasma-plasmashell.service else - killall plasmashell - plasmashell > /dev/null 2>&1 & + plasmashell --replace > /dev/null 2>&1 & + disown fi -sh ./iconinstall.sh +bash "$SCRIPT_DIR/iconinstall.sh" +echo "Update complete." From 6d39f52f8cc5d297bb7f53692361fb0f27d39c83 Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Mon, 22 Dec 2025 18:49:52 +0200 Subject: [PATCH 129/141] Fix indicator radius and icons scaling options --- package/contents/ui/ConfigAppearance.qml | 3 +- package/contents/ui/Indicators.qml | 7 +- package/contents/ui/Task.qml | 250 +---------------------- 3 files changed, 19 insertions(+), 241 deletions(-) diff --git a/package/contents/ui/ConfigAppearance.qml b/package/contents/ui/ConfigAppearance.qml index ff77b408..7355e31a 100644 --- a/package/contents/ui/ConfigAppearance.qml +++ b/package/contents/ui/ConfigAppearance.qml @@ -71,9 +71,10 @@ KCMUtils.SimpleKCM { Slider { id: iconScale + Layout.fillWidth: true from: 0 to: 300 - stepSize: 25.0 + stepSize: 1.0 Kirigami.FormData.label: i18n("Icon Scale") + " " + iconScale.valueAt(iconScale.position) + "%" visible: !iconSizeOverride.checked } diff --git a/package/contents/ui/Indicators.qml b/package/contents/ui/Indicators.qml index f95df0bb..ea361c03 100644 --- a/package/contents/ui/Indicators.qml +++ b/package/contents/ui/Indicators.qml @@ -66,6 +66,7 @@ Flow { colorEval = plasmoid.configuration.indicatorCustomColor } if(isFirst){//compute the size + var growFactor = plasmoid.configuration.indicatorGrowFactor / 100 if(plasmoid.configuration.indicatorGrow && task.state === "minimized") { var mainSize = indicatorLength * growFactor; @@ -86,6 +87,7 @@ Flow { default: break } + } else { indicatorComputedSize = indicatorLength @@ -97,6 +99,7 @@ Flow { else{ width = plasmoid.configuration.indicatorSize height = indicatorComputedSize + } if(plasmoid.configuration.indicatorDesaturate && task.state === "minimized") { var colorHSL = hexToHSL(colorEval) @@ -113,7 +116,8 @@ Flow { width: computedVar.width height: computedVar.height color: computedVar.colorCalc - radius: (Math.max(width, height) / Math.min(width, height)) * (plasmoid.configuration.indicatorRadius / 100) + radius: Math.min(width, height) * (plasmoid.configuration.indicatorRadius / 200) + Rectangle{ Behavior on height { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } Behavior on width { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } @@ -158,6 +162,7 @@ Flow { target: indicator width: undefined height: plasmoid.configuration.indicatorSize + anchors.topMargin: 0; anchors.bottomMargin: plasmoid.configuration.indicatorEdgeOffset; anchors.leftMargin: 0; diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 77a712db..8ea019b6 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -235,7 +235,6 @@ PlasmaCore.ToolTipArea { onIndexChanged: { hideToolTip(); - if (!inPopup && !tasksRoot.vertical && !Plasmoid.configuration.separateLaunchers) { tasksRoot.requestLayout(); } @@ -350,7 +349,8 @@ PlasmaCore.ToolTipArea { return; } - mainItem.blockingUpdates = (mainItem.isGroup !== model.IsGroupParent); // BUG 464597 Force unload the previous component + mainItem.blockingUpdates = (mainItem.isGroup !== model.IsGroupParent); + // BUG 464597 Force unload the previous component mainItem.parentTask = this; mainItem.rootIndex = tasksModel.makeModelIndex(index, -1); @@ -395,7 +395,8 @@ PlasmaCore.ToolTipArea { var max = Math.max(r, g, b), min = Math.min(r, g, b); var h, s, l = (max + min) / 2; if (max == min) { - h = s = 0; // achromatic + h = s = 0; + // achromatic } else { var d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); @@ -436,239 +437,6 @@ PlasmaCore.ToolTipArea { clip: true } - // Flow { - // id: indicator - // visible: plasmoid.configuration.indicatorsEnabled ? true : false - // flow: Flow.LeftToRight - // spacing: Kirigami.Units.smallSpacing - // clip: true - // Repeater { - - // model: { - - // if(!plasmoid.configuration.indicatorsEnabled) - // return 0; - // if(task.childCount < plasmoid.configuration.indicatorMinLimit) - // return 0; - // if(task.isSubTask)//Target only the main task items. - // return 0; - // if(task.state === 'launcher') { - // return 0; - // } - // return Math.min((task.childCount === 0) ? 1 : task.childCount, maxStates); - // } - // readonly property int maxStates: plasmoid.configuration.indicatorMaxLimit - - // Rectangle{ - // id: stateRect - // Behavior on height { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } - // Behavior on width { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } - // Behavior on color { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } - // Behavior on radius { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } - // readonly property color decoColor: index === 0 ? "red" : frame.indicatorColor - // readonly property int maxStates: plasmoid.configuration.indicatorMaxLimit - // readonly property bool isFirst: index === 0 - // readonly property int adjust: plasmoid.configuration.indicatorShrink - // readonly property int indicatorLength: plasmoid.configuration.indicatorLength - // readonly property int spacing: Kirigami.Units.smallSpacing - // readonly property bool isVertical: { - // if(plasmoid.formFactor === PlasmaCore.Types.Vertical && !plasmoid.configuration.indicatorOverride) - // return true; - // if(plasmoid.formFactor == PlasmaCore.Types.Floating && plasmoid.configuration.indicatorOverride && (plasmoid.configuration.indicatorLocation === 1 || plasmoid.configuration.indicatorLocation === 2)) - // return true; - // if(plasmoid.configuration.indicatorOverride && (plasmoid.configuration.indicatorLocation === 1 || plasmoid.configuration.indicatorLocation === 2)) - // return true; - // else{ - // return false; - // } - // } - // readonly property var computedVar: { - // var height; - // var width; - // var colorCalc; - // var colorEval = '#FFFFFF'; - // var parentSize = !isVertical ? frame.width : frame.height; - // var indicatorComputedSize; - // var adjustment = isFirst ? adjust : 0 - // var parentSpacingAdjust = task.childCount >= 1 && maxStates >= 2 ? (spacing * 2.5) : 0 //Spacing fix for multiple items - // if(plasmoid.configuration.indicatorDominantColor){ - // colorEval = decoColor - // } - // if(plasmoid.configuration.indicatorAccentColor){ - // colorEval = PlasmaCore.Theme.highlightColor - // } - // else if(!plasmoid.configuration.indicatorDominantColor && !plasmoid.configuration.indicatorAccentColor){ - // colorEval = plasmoid.configuration.indicatorCustomColor - // } - // if(isFirst){//compute the size - // var growFactor = plasmoid.configuration.indicatorGrowFactor / 100 - // if(plasmoid.configuration.indicatorGrow && task.state === "minimized") { - // var mainSize = indicatorLength * growFactor; - // } - // else{ - // var mainSize = (parentSize + parentSpacingAdjust); - // } - // switch(plasmoid.configuration.indicatorStyle){ - // case 0: - // indicatorComputedSize = mainSize - (Math.min(task.childCount, maxStates === 1 ? 0 : maxStates) * (spacing + indicatorLength)) - adjust - // break - // case 1: - // indicatorComputedSize = mainSize - (Math.min(task.childCount, maxStates === 1 ? 0 : maxStates) * (spacing + indicatorLength)) - adjust - // break - // case 2: - // indicatorComputedSize = plasmoid.configuration.indicatorGrow && task.state !== "minimized" ? indicatorLength * growFactor : indicatorLength - // break - // default: - // break - // } - // } - // else { - // indicatorComputedSize = indicatorLength - // } - // if(!isVertical){ - // width = indicatorComputedSize; - // height = plasmoid.configuration.indicatorSize - // } - // else{ - // width = plasmoid.configuration.indicatorSize - // height = indicatorComputedSize - // } - // if(plasmoid.configuration.indicatorDesaturate && task.state === "minimized") { - // var colorHSL = hexToHSL(colorEval) - // colorCalc = Qt.hsla(colorHSL.h, colorHSL.s*0.5, colorHSL.l*.8, 1) - // } - // else if(!isFirst && plasmoid.configuration.indicatorStyle === 0 && task.state !== "minimized") {//Metro specific handling - // colorCalc = Qt.darker(colorEval, 1.2) - // } - // else { - // colorCalc = colorEval - // } - // return {height: height, width: width, colorCalc: colorCalc} - // } - // width: computedVar.width - // height: computedVar.height - // color: computedVar.colorCalc - // radius: (Math.max(width, height) / Math.min(width, height)) * (plasmoid.configuration.indicatorRadius / 100) - // Rectangle{ - // Behavior on height { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } - // Behavior on width { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } - // Behavior on color { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } - // Behavior on radius { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } - // visible: task.isWindow && task.smartLauncherItem && task.smartLauncherItem.progressVisible && isFirst && plasmoid.configuration.indicatorProgress - // anchors{ - // top: isVertical ? undefined : parent.top - // bottom: isVertical ? undefined : parent.bottom - // left: isVertical ? parent.left : undefined - // right: isVertical ? parent.right : undefined - // } - // readonly property var progress: { - // if(task.smartLauncherItem && task.smartLauncherItem.progressVisible && task.smartLauncherItem.progress){ - // return task.smartLauncherItem.progress / 100 - // } - // return 0 - // } - // width: isVertical ? parent.width : parent.width * progress - // height: isVertical ? parent.height * progress : parent.height - // radius: parent.radius - // color: plasmoid.configuration.indicatorProgressColor - // } - // } - // } - - // states:[ - // State { - // name: "bottom" - // when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 0) - // || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.BottomEdge && !plasmoid.configuration.indicatorReverse) - // || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.TopEdge && plasmoid.configuration.indicatorReverse) - // || (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) - // || (plasmoid.location === PlasmaCore.Types.Floating && !plasmoid.configuration.indicatorOverride && !plasmoid.configuration.indicatorReverse) - - // AnchorChanges { - // target: indicator - // anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; - // horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} - // } - // PropertyChanges { - // target: indicator - // width: undefined - // height: plasmoid.configuration.indicatorSize - // anchors.topMargin: 0; - // anchors.bottomMargin: plasmoid.configuration.indicatorEdgeOffset; - // anchors.leftMargin: 0; - // anchors.rightMargin: 0; - // } - // }, - // State { - // name: "left" - // when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 1) - // || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.LeftEdge && !plasmoid.configuration.indicatorReverse) - // || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.RightEdge && plasmoid.configuration.indicatorReverse) - // || (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 1 && plasmoid.configuration.indicatorOverride) - - // AnchorChanges { - // target: indicator - // anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; - // horizontalCenter:undefined; verticalCenter:parent.verticalCenter} - // } - // PropertyChanges { - // target: indicator - // height: undefined - // width: plasmoid.configuration.indicatorSize - // anchors.topMargin: 0; - // anchors.bottomMargin: 0; - // anchors.leftMargin: plasmoid.configuration.indicatorEdgeOffset; - // anchors.rightMargin: 0; - // } - // }, - // State { - // name: "right" - // when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 2) - // || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.RightEdge && !plasmoid.configuration.indicatorReverse) - // || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.LeftEdge && plasmoid.configuration.indicatorReverse) - // || (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 2 && plasmoid.configuration.indicatorOverride) - - // AnchorChanges { - // target: indicator - // anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; - // horizontalCenter:undefined; verticalCenter:parent.verticalCenter} - // } - // PropertyChanges { - // target: indicator - // height: undefined - // width: plasmoid.configuration.indicatorSize - // anchors.topMargin: 0; - // anchors.bottomMargin: 0; - // anchors.leftMargin: 0; - // anchors.rightMargin: plasmoid.configuration.indicatorEdgeOffset; - // } - // }, - // State { - // name: "top" - // when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 3) - // || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.TopEdge && !plasmoid.configuration.indicatorReverse) - // || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.BottomEdge && plasmoid.configuration.indicatorReverse) - // || (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 3 && plasmoid.configuration.indicatorOverride) - // || (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorReverse && !plasmoid.configuration.indicatorOverride) - - // AnchorChanges { - // target: indicator - // anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; - // horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} - // } - // PropertyChanges { - // target: indicator - // width: undefined - // height: plasmoid.configuration.indicatorSize - // anchors.topMargin: plasmoid.configuration.indicatorEdgeOffset; - // anchors.bottomMargin: 0; - // anchors.leftMargin: 0; - // anchors.rightMargin: 0; - // } - // } - // ] - // } - TapHandler { id: menuTapHandler acceptedButtons: Qt.LeftButton @@ -849,7 +617,6 @@ PlasmaCore.ToolTipArea { } var margins = isVertical ? LayoutMetrics.horizontalMargins() : LayoutMetrics.verticalMargins(); - if ((size - margins) < Kirigami.Units.iconSizes.small) { return Math.ceil((margin * (Kirigami.Units.iconSizes.small / size)) / 2); } @@ -860,8 +627,13 @@ PlasmaCore.ToolTipArea { Kirigami.Icon { id: icon property int growSize: active ? plasmoid.configuration.iconZoomFactor : 0 - width: parent.width + growSize - height: parent.height + growSize + + // Fix: Use iconScale + property real iconScale: plasmoid.configuration.iconScale / 100 + + width: (parent.width * iconScale) + growSize + height: (parent.height * iconScale) + growSize + anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter Behavior on growSize { From 24e4007299809efad5cee70d872c3edf33996187 Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Mon, 22 Dec 2025 18:57:15 +0200 Subject: [PATCH 130/141] Fix scaled icons position --- package/contents/ui/Task.qml | 172 +++++++++++++++++++++++------------ 1 file changed, 115 insertions(+), 57 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 8ea019b6..1ca4df64 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -30,19 +30,24 @@ PlasmaCore.ToolTipArea { readonly property bool isCiliora: plasmoid.configuration.indicatorStyle === 1 readonly property bool isDashes: plasmoid.configuration.indicatorStyle === 2 - property string tintColor: Kirigami.ColorUtils.brightnessForColor(Kirigami.Theme.backgroundColor) === Kirigami.ColorUtils.Dark ? "#ffffff" : "#000000" + property string tintColor: Kirigami.ColorUtils.brightnessForColor(Kirigami.Theme.backgroundColor) === Kirigami.ColorUtils.Dark ? + "#ffffff" : "#000000" // To achieve a bottom to top layout, the task manager is rotated by 180 degrees(see main.qml). // This makes the tasks mirrored, so we mirror them again to fix that. rotation: Plasmoid.configuration.reverseMode && Plasmoid.formFactor === PlasmaCore.Types.Vertical ? 180 : 0 - implicitHeight: inPopup ? LayoutMetrics.preferredHeightInPopup() : Math.max(tasksRoot.height / tasksRoot.plasmoid.configuration.maxStripes, LayoutMetrics.preferredMinHeight()) - implicitWidth: tasksRoot.vertical ? Math.max(LayoutMetrics.preferredMinWidth(), Math.min(LayoutMetrics.preferredMaxWidth(), tasksRoot.width / tasksRoot.plasmoid.configuration.maxStripes)) : 0 + implicitHeight: inPopup ? + LayoutMetrics.preferredHeightInPopup() : Math.max(tasksRoot.height / tasksRoot.plasmoid.configuration.maxStripes, LayoutMetrics.preferredMinHeight()) + implicitWidth: tasksRoot.vertical ? + Math.max(LayoutMetrics.preferredMinWidth(), Math.min(LayoutMetrics.preferredMaxWidth(), tasksRoot.width / tasksRoot.plasmoid.configuration.maxStripes)) : 0 Layout.fillWidth: true Layout.fillHeight: !inPopup - Layout.maximumWidth: tasksRoot.vertical ? -1 : ((model.IsLauncher && !tasks.iconsOnly) ? tasksRoot.height / taskList.rows : LayoutMetrics.preferredMaxWidth()) - Layout.maximumHeight: tasksRoot.vertical ? LayoutMetrics.preferredMaxHeight() : -1 + Layout.maximumWidth: tasksRoot.vertical ? + -1 : ((model.IsLauncher && !tasks.iconsOnly) ? tasksRoot.height / taskList.rows : LayoutMetrics.preferredMaxWidth()) + Layout.maximumHeight: tasksRoot.vertical ? + LayoutMetrics.preferredMaxHeight() : -1 required property var model required property int index @@ -51,7 +56,8 @@ PlasmaCore.ToolTipArea { readonly property int pid: model.AppPid readonly property string appName: model.AppName readonly property string appId: model.AppId.replace(/\.desktop/, '') - readonly property bool isIcon: tasksRoot.iconsOnly || model.IsLauncher + readonly property bool isIcon: tasksRoot.iconsOnly || + model.IsLauncher property bool toolTipOpen: false property bool inPopup: false property bool isWindow: model.IsWindow @@ -66,19 +72,24 @@ PlasmaCore.ToolTipArea { property var audioStreams: [] property bool delayAudioStreamIndicator: false property bool completed: false - readonly property bool audioIndicatorsEnabled: Plasmoid.configuration.indicateAudioStreams + readonly property + bool audioIndicatorsEnabled: Plasmoid.configuration.indicateAudioStreams readonly property bool hasAudioStream: audioStreams.length > 0 readonly property bool playingAudio: hasAudioStream && audioStreams.some(item => !item.corked) readonly property bool muted: hasAudioStream && audioStreams.every(item => item.muted) - readonly property bool highlighted: (inPopup && activeFocus) || (!inPopup && containsMouse) || (task.contextMenu && task.contextMenu.status === PlasmaExtras.Menu.Open) || (!!tasksRoot.groupDialog && tasksRoot.groupDialog.visualParent === task) + readonly property bool highlighted: (inPopup && activeFocus) || + (!inPopup && containsMouse) || (task.contextMenu && task.contextMenu.status === PlasmaExtras.Menu.Open) || + (!!tasksRoot.groupDialog && tasksRoot.groupDialog.visualParent === task) property int itemIndex: index // fancytasks active: (Plasmoid.configuration.showToolTips || tasksRoot.toolTipOpenedByClick === task) && !inPopup && !tasksRoot.groupDialog - interactive: model.IsWindow || mainItem.playerData + interactive: model.IsWindow || + mainItem.playerData location: Plasmoid.location - mainItem: model.IsWindow ? openWindowToolTipDelegate : pinnedAppToolTipDelegate + mainItem: model.IsWindow ? + openWindowToolTipDelegate : pinnedAppToolTipDelegate onXChanged: { if (!completed) { @@ -161,27 +172,32 @@ PlasmaCore.ToolTipArea { if (model.IsGroupParent) { switch (Plasmoid.configuration.groupedTaskVisualization) { case 0: - break; // Use the default description + break; + // Use the default description case 1: { if (Plasmoid.configuration.showToolTips) { - return `${i18nc("@info:usagetip %1 task name", "Show Task tooltip for %1", model.display)}; ${smartLauncherDescription}`; + return `${i18nc("@info:usagetip %1 task name", "Show Task tooltip for %1", model.display)}; +${smartLauncherDescription}`; } // fallthrough } case 2: { if (effectWatcher.registered) { - return `${i18nc("@info:usagetip %1 task name", "Show windows side by side for %1", model.display)}; ${smartLauncherDescription}`; + return `${i18nc("@info:usagetip %1 task name", "Show windows side by side for %1", model.display)}; +${smartLauncherDescription}`; } // fallthrough } default: - return `${i18nc("@info:usagetip %1 task name", "Open textual list of windows for %1", model.display)}; ${smartLauncherDescription}`; + return `${i18nc("@info:usagetip %1 task name", "Open textual list of windows for %1", model.display)}; +${smartLauncherDescription}`; } } - return `${i18n("Activate %1", model.display)}; ${smartLauncherDescription}`; + return `${i18n("Activate %1", model.display)}; +${smartLauncherDescription}`; } Accessible.role: Accessible.Button Accessible.onPressAction: leftTapHandler.leftClick() @@ -291,7 +307,8 @@ PlasmaCore.ToolTipArea { } function modelIndex(): /*QModelIndex*/ var { - return inPopup ? tasksModel.makeModelIndex(groupDialog.visualParent.index, index) : tasksModel.makeModelIndex(index); + return inPopup ? + tasksModel.makeModelIndex(groupDialog.visualParent.index, index) : tasksModel.makeModelIndex(index); } function showContextMenu(args: var): void { @@ -303,7 +320,8 @@ PlasmaCore.ToolTipArea { function updateAudioStreams(args: var): void { if (args) { // When the task just appeared (e.g. virtual desktop switch), show the audio indicator - // right away. Only when audio streams change during the lifetime of this task, delay + // right away. + // Only when audio streams change during the lifetime of this task, delay // showing that to avoid distraction. delayAudioStreamIndicator = !!args.delay; } @@ -323,7 +341,8 @@ PlasmaCore.ToolTipArea { pa.registerPidMatch(model.AppName); } else { // We only want to fall back to appName matching if we never managed to map - // a PID to an audio stream window. Otherwise if you have two instances of + // a PID to an audio stream window. + // Otherwise if you have two instances of // an application, one playing and the other not, it will look up appName // for the non-playing instance and erroneously show an indicator on both. if (!pa.hasPidMatch(model.AppName)) { @@ -424,14 +443,17 @@ PlasmaCore.ToolTipArea { id: colorOverride anchors.fill: frame source: frame - color: plasmoid.configuration.buttonColorizeDominant ? frame.indicatorColor : plasmoid.configuration.buttonColorizeCustom - visible: plasmoid.configuration.buttonColorize ? true : false + color: plasmoid.configuration.buttonColorizeDominant ? + frame.indicatorColor : plasmoid.configuration.buttonColorizeCustom + visible: plasmoid.configuration.buttonColorize ? + true : false } Indicators { id: indicator taskCount: task.childCount - visible: plasmoid.configuration.indicatorsEnabled ? true : false + visible: plasmoid.configuration.indicatorsEnabled ? + true : false flow: Flow.LeftToRight spacing: Kirigami.Units.smallSpacing clip: true @@ -440,7 +462,8 @@ PlasmaCore.ToolTipArea { TapHandler { id: menuTapHandler acceptedButtons: Qt.LeftButton - acceptedDevices: PointerDevice.TouchScreen | PointerDevice.Stylus + acceptedDevices: PointerDevice.TouchScreen | + PointerDevice.Stylus gesturePolicy: TapHandler.ReleaseWithinBounds onLongPressed: { // When we're a launcher, there's no window controls, so we can show all @@ -457,7 +480,8 @@ PlasmaCore.ToolTipArea { TapHandler { acceptedButtons: Qt.RightButton - acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus + acceptedDevices: PointerDevice.Mouse | + PointerDevice.TouchPad | PointerDevice.Stylus gesturePolicy: TapHandler.WithinBounds // Release grab when menu appears onPressedChanged: if (pressed) contextMenuTimer.start() @@ -483,7 +507,8 @@ PlasmaCore.ToolTipArea { } TapHandler { - acceptedButtons: Qt.MiddleButton | Qt.BackButton | Qt.ForwardButton + acceptedButtons: Qt.MiddleButton | + Qt.BackButton | Qt.ForwardButton onTapped: (eventPoint, button) => { if (button === Qt.MiddleButton) { if (Plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.NewInstance) { @@ -528,17 +553,24 @@ PlasmaCore.ToolTipArea { anchors { fill: parent - topMargin: (!tasksRoot.vertical && taskList.rows > 1) ? LayoutMetrics.iconMargin : 0 - bottomMargin: (!tasksRoot.vertical && taskList.rows > 1) ? LayoutMetrics.iconMargin : 0 - leftMargin: ((inPopup || tasksRoot.vertical) && taskList.columns > 1) ? LayoutMetrics.iconMargin : 0 - rightMargin: ((inPopup || tasksRoot.vertical) && taskList.columns > 1) ? LayoutMetrics.iconMargin : 0 + topMargin: (!tasksRoot.vertical && taskList.rows > 1) ? + LayoutMetrics.iconMargin : 0 + bottomMargin: (!tasksRoot.vertical && taskList.rows > 1) ? + LayoutMetrics.iconMargin : 0 + leftMargin: ((inPopup || tasksRoot.vertical) && taskList.columns > 1) ? + LayoutMetrics.iconMargin : 0 + rightMargin: ((inPopup || tasksRoot.vertical) && taskList.columns > 1) ? + LayoutMetrics.iconMargin : 0 } - imagePath: plasmoid.configuration.disableButtonSvg ? "" : "widgets/tasks" - enabledBorders: plasmoid.configuration.useBorders ? 1 | 2 | 4 | 8 : 0 + imagePath: plasmoid.configuration.disableButtonSvg ? + "" : "widgets/tasks" + enabledBorders: plasmoid.configuration.useBorders ? 1 | 2 | 4 | + 8 : 0 property bool isHovered: task.highlighted && Plasmoid.configuration.taskHoverEffect property string basePrefix: "normal" - prefix: isHovered ? TaskTools.taskPrefixHovered(basePrefix, Plasmoid.location) : TaskTools.taskPrefix(basePrefix, Plasmoid.location) + prefix: isHovered ? + TaskTools.taskPrefixHovered(basePrefix, Plasmoid.location) : TaskTools.taskPrefix(basePrefix, Plasmoid.location) // Avoid repositioning delegate item after dragFinished DragHandler { @@ -568,6 +600,7 @@ PlasmaCore.ToolTipArea { setRequestedInhibitDnd(true); tasksRoot.dragSource = task; dragHelper.Drag.imageSource = result.url; + dragHelper.Drag.mimeData = { "text/x-orgkdeplasmataskmanager_taskurl": backend.tryDecodeApplicationsUrl(model.LauncherUrlWithoutIcon).toString(), [model.MimeType]: model.MimeData, @@ -604,8 +637,10 @@ PlasmaCore.ToolTipArea { topMargin: adjustMargin(false, parent.height, taskFrame.margins.top) } - width: task.inPopup ? Math.max(Kirigami.Units.iconSizes.sizeForLabels, Kirigami.Units.iconSizes.medium) : Math.min(task.parent?.minimumWidth ?? 0, task.height) - height: task.inPopup ? width : (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - adjustMargin(false, parent.height, taskFrame.margins.bottom)) + width: task.inPopup ? + Math.max(Kirigami.Units.iconSizes.sizeForLabels, Kirigami.Units.iconSizes.medium) : Math.min(task.parent?.minimumWidth ?? 0, task.height) + height: task.inPopup ? + width : (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - adjustMargin(false, parent.height, taskFrame.margins.bottom)) asynchronous: true active: height >= Kirigami.Units.iconSizes.small && task.smartLauncherItem && task.smartLauncherItem.countVisible @@ -626,16 +661,18 @@ PlasmaCore.ToolTipArea { Kirigami.Icon { id: icon - property int growSize: active ? plasmoid.configuration.iconZoomFactor : 0 + property int growSize: active ? + plasmoid.configuration.iconZoomFactor : 0 // Fix: Use iconScale property real iconScale: plasmoid.configuration.iconScale / 100 width: (parent.width * iconScale) + growSize height: (parent.height * iconScale) + growSize + - anchors.bottom: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter + anchors.centerIn: parent + Behavior on growSize { NumberAnimation { duration: plasmoid.configuration.iconZoomDuration @@ -688,15 +725,18 @@ PlasmaCore.ToolTipArea { fill: parent leftMargin: taskFrame.margins.left + iconBox.width + LayoutMetrics.labelMargin topMargin: taskFrame.margins.top - rightMargin: taskFrame.margins.right + (audioStreamIcon !== null && audioStreamIcon.visible ? (audioStreamIcon.width + LayoutMetrics.labelMargin) : 0) + rightMargin: taskFrame.margins.right + (audioStreamIcon !== null && audioStreamIcon.visible ? + (audioStreamIcon.width + LayoutMetrics.labelMargin) : 0) bottomMargin: taskFrame.margins.bottom } - wrapMode: (maximumLineCount === 1) ? Text.NoWrap : Text.Wrap + wrapMode: (maximumLineCount === 1) ? + Text.NoWrap : Text.Wrap elide: Text.ElideRight textFormat: Text.PlainText verticalAlignment: Text.AlignVCenter - maximumLineCount: Plasmoid.configuration.maxTextLines || undefined + maximumLineCount: Plasmoid.configuration.maxTextLines || + undefined Accessible.ignored: true @@ -728,12 +768,14 @@ PlasmaCore.ToolTipArea { }, State { name: "attention" - when: model.IsDemandingAttention === true || (task.smartLauncherItem && task.smartLauncherItem.urgent) + when: model.IsDemandingAttention === true || + (task.smartLauncherItem && task.smartLauncherItem.urgent) PropertyChanges { target: frame basePrefix: "attention" - visible: (plasmoid.configuration.buttonColorize && !frame.isHovered) || !plasmoid.configuration.buttonColorize + visible: (plasmoid.configuration.buttonColorize && !frame.isHovered) || + !plasmoid.configuration.buttonColorize } PropertyChanges { target: colorOverride @@ -747,15 +789,18 @@ PlasmaCore.ToolTipArea { PropertyChanges { target: frame basePrefix: "minimized" - visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? false : true + visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? + false : true } PropertyChanges { target: colorOverride - visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? true : false + visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? + true : false } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? false : true + visible: plasmoid.configuration.disableInactiveIndicators ? + false : true } }, State { @@ -765,15 +810,18 @@ PlasmaCore.ToolTipArea { PropertyChanges { target: frame basePrefix: "minimized" - visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true + visible: plasmoid.configuration.disableButtonInactiveSvg ? + false : true } PropertyChanges { target: colorOverride - visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true + visible: plasmoid.configuration.disableButtonInactiveSvg ? + false : true } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? false : true + visible: plasmoid.configuration.disableInactiveIndicators ? + false : true } }, State { @@ -786,11 +834,13 @@ PlasmaCore.ToolTipArea { } PropertyChanges { target: colorOverride - visible: plasmoid.configuration.buttonColorize ? true : false + visible: plasmoid.configuration.buttonColorize ? + true : false } PropertyChanges { target: indicator - visible: plasmoid.configuration.indicatorsEnabled ? true : false + visible: plasmoid.configuration.indicatorsEnabled ? + true : false } }, State { @@ -798,15 +848,18 @@ PlasmaCore.ToolTipArea { when: model.IsActive === false && !frame.isHovered && !plasmoid.configuration.disableButtonInactiveSvg PropertyChanges { target: colorOverride - visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? true : false + visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? + true : false } PropertyChanges { target: frame - visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? false : true + visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? + false : true } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? false : true + visible: plasmoid.configuration.disableInactiveIndicators ? + false : true } }, State { @@ -814,15 +867,18 @@ PlasmaCore.ToolTipArea { when: (model.IsActive === false && !frame.isHovered) && plasmoid.configuration.disableButtonInactiveSvg PropertyChanges { target: colorOverride - visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true + visible: plasmoid.configuration.disableButtonInactiveSvg ? + false : true } PropertyChanges { target: frame - visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true + visible: plasmoid.configuration.disableButtonInactiveSvg ? + false : true } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? false : true + visible: plasmoid.configuration.disableInactiveIndicators ? + false : true } }, State { @@ -834,11 +890,13 @@ PlasmaCore.ToolTipArea { } PropertyChanges { target: frame - visible: plasmoid.configuration.buttonColorize ? false : true + visible: plasmoid.configuration.buttonColorize ? + false : true } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? false : true + visible: plasmoid.configuration.disableInactiveIndicators ? + false : true } } ] From 5772726d3d0bae09a9e58d98fcf2c0612c23b4a3 Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Mon, 22 Dec 2025 19:14:26 +0200 Subject: [PATCH 131/141] Fix scaled icons position (with badges) --- package/contents/ui/Task.qml | 2 -- package/contents/ui/TaskBadgeOverlay.qml | 6 +++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 1ca4df64..1c5d13fb 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -664,13 +664,11 @@ ${smartLauncherDescription}`; property int growSize: active ? plasmoid.configuration.iconZoomFactor : 0 - // Fix: Use iconScale property real iconScale: plasmoid.configuration.iconScale / 100 width: (parent.width * iconScale) + growSize height: (parent.height * iconScale) + growSize - anchors.centerIn: parent Behavior on growSize { diff --git a/package/contents/ui/TaskBadgeOverlay.qml b/package/contents/ui/TaskBadgeOverlay.qml index d3ec176a..68749c97 100644 --- a/package/contents/ui/TaskBadgeOverlay.qml +++ b/package/contents/ui/TaskBadgeOverlay.qml @@ -12,6 +12,9 @@ import org.kde.plasma.plasmoid Item { id: root + // Fix: Anchor directly to the icon to sync scaling and position automatically + anchors.fill: icon + readonly property int iconWidthDelta: (icon.width - icon.paintedWidth) / 2 readonly property bool shiftBadgeDown: (Plasmoid.pluginName === "org.kde.plasma.icontasks") && task.audioStreamIcon !== null @@ -24,7 +27,8 @@ Item { anchors.right: parent.right anchors.rightMargin: -offset - y: root.shiftBadgeDown ? (icon.height / 2) : 0 + y: root.shiftBadgeDown ? + (icon.height / 2) : 0 Behavior on y { NumberAnimation { duration: Kirigami.Units.longDuration } From d9cb242a3e073e27c391768b574afc8af239e37c Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Mon, 22 Dec 2025 19:49:23 +0200 Subject: [PATCH 132/141] Fix spam warnings in journal --- package/contents/ui/ConfigAppearance.qml | 137 +++++- package/contents/ui/ConfigBehavior.qml | 133 +++++- package/contents/ui/ConfigIndicators.qml | 524 ++++++++++++++--------- package/contents/ui/ConfigPinnedApps.qml | 368 +++++++++++----- 4 files changed, 829 insertions(+), 333 deletions(-) diff --git a/package/contents/ui/ConfigAppearance.qml b/package/contents/ui/ConfigAppearance.qml index 7355e31a..8073fd24 100644 --- a/package/contents/ui/ConfigAppearance.qml +++ b/package/contents/ui/ConfigAppearance.qml @@ -8,13 +8,12 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts -import org.kde.kcmutils as KCMUtils import org.kde.kirigami as Kirigami import org.kde.plasma.core as PlasmaCore import org.kde.plasma.plasmoid import org.kde.kquickcontrols as KQuickAddons -KCMUtils.SimpleKCM { +Kirigami.ScrollablePage { readonly property bool plasmaPaAvailable: Qt.createComponent("PulseAudio.qml").status === Component.Ready readonly property bool plasmoidVertical: Plasmoid.formFactor === PlasmaCore.Types.Vertical readonly property bool iconOnly: plasmoid.configuration.iconOnly @@ -28,6 +27,7 @@ KCMUtils.SimpleKCM { property alias cfg_iconSizePx: iconSizePx.value property alias cfg_iconSizeOverride: iconSizeOverride.checked property alias cfg_forceStripes: forceStripes.checked + property alias cfg_maxStripes: maxStripes.value property alias cfg_taskMaxWidth: taskMaxWidth.currentIndex property alias cfg_maxButtonLength: maxButtonLength.value property int cfg_iconSpacing: 0 @@ -46,11 +46,129 @@ KCMUtils.SimpleKCM { property alias cfg_overridePlasmaButtonDirection: overridePlasmaButtonDirection.checked property alias cfg_plasmaButtonDirection: plasmaButtonDirection.currentIndex + // --- Properties to silence KCM errors --- + // Defaults for existing aliases + property var cfg_iconZoomFactorDefault + property var cfg_iconZoomDurationDefault + property var cfg_showToolTipsDefault + property var cfg_highlightWindowsDefault + property var cfg_indicateAudioStreamsDefault + property var cfg_iconScaleDefault + property var cfg_iconSizePxDefault + property var cfg_iconSizeOverrideDefault + property var cfg_forceStripesDefault + property var cfg_maxStripesDefault + property var cfg_taskMaxWidthDefault + property var cfg_maxButtonLengthDefault + property var cfg_iconSpacingDefault + property var cfg_fillDefault + property var cfg_useBordersDefault + property var cfg_taskSpacingSizeDefault + property var cfg_buttonColorizeDefault + property var cfg_buttonColorizeInactiveDefault + property var cfg_buttonColorizeDominantDefault + property var cfg_buttonColorizeCustomDefault + property var cfg_disableButtonSvgDefault + property var cfg_disableButtonInactiveSvgDefault + property var cfg_overridePlasmaButtonDirectionDefault + property var cfg_plasmaButtonDirectionDefault + + // Missing properties from main.xml not used in this tab + property var cfg_showOnlyCurrentScreen + property var cfg_showOnlyCurrentScreenDefault + property var cfg_showOnlyCurrentDesktop + property var cfg_showOnlyCurrentDesktopDefault + property var cfg_showOnlyCurrentActivity + property var cfg_showOnlyCurrentActivityDefault + property var cfg_showOnlyMinimized + property var cfg_showOnlyMinimizedDefault + property var cfg_unhideOnAttention + property var cfg_unhideOnAttentionDefault + property var cfg_groupingStrategy + property var cfg_groupingStrategyDefault + property var cfg_iconOnly // Read via plasmoid.configuration + property var cfg_iconOnlyDefault + property var cfg_groupedTaskVisualization + property var cfg_groupedTaskVisualizationDefault + property var cfg_groupPopups + property var cfg_groupPopupsDefault + property var cfg_onlyGroupWhenFull + property var cfg_onlyGroupWhenFullDefault + property var cfg_groupingAppIdBlacklist + property var cfg_groupingAppIdBlacklistDefault + property var cfg_groupingLauncherUrlBlacklist + property var cfg_groupingLauncherUrlBlacklistDefault + property var cfg_sortingStrategy + property var cfg_sortingStrategyDefault + property var cfg_separateLaunchers + property var cfg_separateLaunchersDefault + property var cfg_hideLauncherOnStart + property var cfg_hideLauncherOnStartDefault + property var cfg_wheelEnabled + property var cfg_wheelEnabledDefault + property var cfg_wheelSkipMinimized + property var cfg_wheelSkipMinimizedDefault + property var cfg_launchers + property var cfg_launchersDefault + property var cfg_middleClickAction + property var cfg_middleClickActionDefault + property var cfg_taskHoverEffect + property var cfg_taskHoverEffectDefault + property var cfg_maxTextLines + property var cfg_maxTextLinesDefault + property var cfg_minimizeActiveTaskOnClick + property var cfg_minimizeActiveTaskOnClickDefault + property var cfg_reverseMode + property var cfg_reverseModeDefault + property var cfg_indicatorsEnabled + property var cfg_indicatorsEnabledDefault + property var cfg_indicatorProgress + property var cfg_indicatorProgressDefault + property var cfg_indicatorProgressColor + property var cfg_indicatorProgressColorDefault + property var cfg_disableInactiveIndicators + property var cfg_disableInactiveIndicatorsDefault + property var cfg_indicatorsAnimated + property var cfg_indicatorsAnimatedDefault + property var cfg_groupIconEnabled + property var cfg_groupIconEnabledDefault + property var cfg_indicatorLocation + property var cfg_indicatorLocationDefault + property var cfg_indicatorStyle + property var cfg_indicatorStyleDefault + property var cfg_indicatorMinLimit + property var cfg_indicatorMinLimitDefault + property var cfg_indicatorMaxLimit + property var cfg_indicatorMaxLimitDefault + property var cfg_indicatorDesaturate + property var cfg_indicatorDesaturateDefault + property var cfg_indicatorGrow + property var cfg_indicatorGrowDefault + property var cfg_indicatorGrowFactor + property var cfg_indicatorGrowFactorDefault + property var cfg_indicatorEdgeOffset + property var cfg_indicatorEdgeOffsetDefault + property var cfg_indicatorSize + property var cfg_indicatorSizeDefault + property var cfg_indicatorLength + property var cfg_indicatorLengthDefault + property var cfg_indicatorRadius + property var cfg_indicatorRadiusDefault + property var cfg_indicatorShrink + property var cfg_indicatorShrinkDefault + property var cfg_indicatorDominantColor + property var cfg_indicatorDominantColorDefault + property var cfg_indicatorAccentColor + property var cfg_indicatorAccentColorDefault + property var cfg_indicatorCustomColor + property var cfg_indicatorCustomColorDefault + property var cfg_indicatorReverse + property var cfg_indicatorReverseDefault + property var cfg_indicatorOverride + property var cfg_indicatorOverrideDefault + // ------------------------------------------------------------------- + Component.onCompleted: { - /* Don't rely on bindings for checking the radiobuttons - When checking forceStripes, the condition for the checked value for the allow stripes button - became true and that one got checked instead, stealing the checked state for the just clicked checkbox - */ if (maxStripes.value === 1) { forbidStripes.checked = true; } else if (!Plasmoid.configuration.forceStripes && maxStripes.value > 1) { @@ -59,6 +177,7 @@ KCMUtils.SimpleKCM { forceStripes.checked = true; } } + Kirigami.FormLayout { CheckBox { id: useBorders @@ -263,7 +382,8 @@ KCMUtils.SimpleKCM { RadioButton { id: forbidStripes - Kirigami.FormData.label: plasmoidVertical ? i18nc("@label for radio button group, completes sentence: … when panel is low on space etc.", "Use multi-column view:") : i18nc("@label for radio button group, completes sentence: … when panel is low on space etc.", "Use multi-row view:") + Kirigami.FormData.label: plasmoidVertical ? +i18nc("@label for radio button group, completes sentence: … when panel is low on space etc.", "Use multi-column view:") : i18nc("@label for radio button group, completes sentence: … when panel is low on space etc.", "Use multi-row view:") onToggled: { if (checked) { maxStripes.value = 1; @@ -295,7 +415,8 @@ KCMUtils.SimpleKCM { SpinBox { id: maxStripes enabled: maxStripes.value > 1 - Kirigami.FormData.label: plasmoidVertical ? i18nc("@label:spinbox maximum number of columns for tasks", "Maximum columns:") : i18nc("@label:spinbox maximum number of rows for tasks", "Maximum rows:") + Kirigami.FormData.label: plasmoidVertical ? +i18nc("@label:spinbox maximum number of columns for tasks", "Maximum columns:") : i18nc("@label:spinbox maximum number of rows for tasks", "Maximum rows:") from: 1 } diff --git a/package/contents/ui/ConfigBehavior.qml b/package/contents/ui/ConfigBehavior.qml index d1988cf3..70d2e23d 100644 --- a/package/contents/ui/ConfigBehavior.qml +++ b/package/contents/ui/ConfigBehavior.qml @@ -8,14 +8,13 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts -import org.kde.kcmutils as KCMUtils import org.kde.kirigami as Kirigami import org.kde.plasma.core as PlasmaCore import org.kde.plasma.plasmoid import org.kde.plasma.workspace.dbus as DBus -KCMUtils.SimpleKCM { +Kirigami.ScrollablePage { property alias cfg_groupingStrategy: groupingStrategy.currentIndex property alias cfg_groupedTaskVisualization: groupedTaskVisualization.currentIndex property alias cfg_groupPopups: groupPopups.checked @@ -35,6 +34,133 @@ KCMUtils.SimpleKCM { property alias cfg_reverseMode: reverseMode.checked property alias cfg_iconOnly: iconOnly.currentIndex + // --- Properties to silence KCM errors --- + property var cfg_groupingStrategyDefault + property var cfg_groupedTaskVisualizationDefault + property var cfg_groupPopupsDefault + property var cfg_onlyGroupWhenFullDefault + property var cfg_sortingStrategyDefault + property var cfg_separateLaunchersDefault + property var cfg_hideLauncherOnStartDefault + property var cfg_middleClickActionDefault + property var cfg_wheelEnabledDefault + property var cfg_wheelSkipMinimizedDefault + property var cfg_showOnlyCurrentScreenDefault + property var cfg_showOnlyCurrentDesktopDefault + property var cfg_showOnlyCurrentActivityDefault + property var cfg_showOnlyMinimizedDefault + property var cfg_minimizeActiveTaskOnClickDefault + property var cfg_unhideOnAttentionDefault + property var cfg_reverseModeDefault + property var cfg_iconOnlyDefault + + // Missing properties from main.xml not used in this tab + property var cfg_groupingAppIdBlacklist + property var cfg_groupingAppIdBlacklistDefault + property var cfg_groupingLauncherUrlBlacklist + property var cfg_groupingLauncherUrlBlacklistDefault + property var cfg_maxStripes + property var cfg_maxStripesDefault + property var cfg_maxButtonLength + property var cfg_maxButtonLengthDefault + property var cfg_forceStripes + property var cfg_forceStripesDefault + property var cfg_showToolTips + property var cfg_showToolTipsDefault + property var cfg_taskMaxWidth + property var cfg_taskMaxWidthDefault + property var cfg_highlightWindows + property var cfg_highlightWindowsDefault + property var cfg_launchers + property var cfg_launchersDefault + property var cfg_indicateAudioStreams + property var cfg_indicateAudioStreamsDefault + property var cfg_iconScale + property var cfg_iconScaleDefault + property var cfg_iconSizePx + property var cfg_iconSizePxDefault + property var cfg_iconSizeOverride + property var cfg_iconSizeOverrideDefault + property var cfg_fill + property var cfg_fillDefault + property var cfg_taskHoverEffect + property var cfg_taskHoverEffectDefault + property var cfg_maxTextLines + property var cfg_maxTextLinesDefault + property var cfg_iconSpacing + property var cfg_iconSpacingDefault + property var cfg_indicatorsEnabled + property var cfg_indicatorsEnabledDefault + property var cfg_indicatorProgress + property var cfg_indicatorProgressDefault + property var cfg_indicatorProgressColor + property var cfg_indicatorProgressColorDefault + property var cfg_disableInactiveIndicators + property var cfg_disableInactiveIndicatorsDefault + property var cfg_indicatorsAnimated + property var cfg_indicatorsAnimatedDefault + property var cfg_groupIconEnabled + property var cfg_groupIconEnabledDefault + property var cfg_indicatorLocation + property var cfg_indicatorLocationDefault + property var cfg_indicatorStyle + property var cfg_indicatorStyleDefault + property var cfg_indicatorMinLimit + property var cfg_indicatorMinLimitDefault + property var cfg_indicatorMaxLimit + property var cfg_indicatorMaxLimitDefault + property var cfg_indicatorDesaturate + property var cfg_indicatorDesaturateDefault + property var cfg_indicatorGrow + property var cfg_indicatorGrowDefault + property var cfg_indicatorGrowFactor + property var cfg_indicatorGrowFactorDefault + property var cfg_indicatorEdgeOffset + property var cfg_indicatorEdgeOffsetDefault + property var cfg_indicatorSize + property var cfg_indicatorSizeDefault + property var cfg_indicatorLength + property var cfg_indicatorLengthDefault + property var cfg_indicatorRadius + property var cfg_indicatorRadiusDefault + property var cfg_indicatorShrink + property var cfg_indicatorShrinkDefault + property var cfg_indicatorDominantColor + property var cfg_indicatorDominantColorDefault + property var cfg_indicatorAccentColor + property var cfg_indicatorAccentColorDefault + property var cfg_indicatorCustomColor + property var cfg_indicatorCustomColorDefault + property var cfg_useBorders + property var cfg_useBordersDefault + property var cfg_taskSpacingSize + property var cfg_taskSpacingSizeDefault + property var cfg_buttonColorize + property var cfg_buttonColorizeDefault + property var cfg_buttonColorizeInactive + property var cfg_buttonColorizeInactiveDefault + property var cfg_buttonColorizeDominant + property var cfg_buttonColorizeDominantDefault + property var cfg_buttonColorizeCustom + property var cfg_buttonColorizeCustomDefault + property var cfg_disableButtonSvg + property var cfg_disableButtonSvgDefault + property var cfg_disableButtonInactiveSvg + property var cfg_disableButtonInactiveSvgDefault + property var cfg_overridePlasmaButtonDirection + property var cfg_overridePlasmaButtonDirectionDefault + property var cfg_plasmaButtonDirection + property var cfg_plasmaButtonDirectionDefault + property var cfg_indicatorReverse + property var cfg_indicatorReverseDefault + property var cfg_indicatorOverride + property var cfg_indicatorOverrideDefault + property var cfg_iconZoomFactor + property var cfg_iconZoomFactorDefault + property var cfg_iconZoomDuration + property var cfg_iconZoomDurationDefault + // ----------------------------------------------------------- + DBus.DBusServiceWatcher { id: effectWatcher busType: DBus.BusType.Session @@ -42,9 +168,6 @@ KCMUtils.SimpleKCM { } Kirigami.FormLayout { - anchors.left: parent.left - anchors.right: parent.right - ComboBox { id: iconOnly Kirigami.FormData.label: i18n("Display:") diff --git a/package/contents/ui/ConfigIndicators.qml b/package/contents/ui/ConfigIndicators.qml index 98f833d1..1066a43c 100644 --- a/package/contents/ui/ConfigIndicators.qml +++ b/package/contents/ui/ConfigIndicators.qml @@ -2,15 +2,14 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts -import org.kde.kcmutils as KCMUtils import org.kde.kirigami as Kirigami import org.kde.plasma.core as PlasmaCore import org.kde.kquickcontrols as KQControls -KCMUtils.SimpleKCM { +Kirigami.ScrollablePage { property alias cfg_indicatorsEnabled: indicatorsEnabled.currentIndex property alias cfg_groupIconEnabled: groupIconEnabled.currentIndex - property alias cfg_indicatorProgress: indicatorProgress.checked + property alias cfg_indicatorProgress: indicatorProgress.checked property alias cfg_indicatorProgressColor: indicatorProgressColor.color property alias cfg_disableInactiveIndicators: disableInactiveIndicators.checked property alias cfg_indicatorsAnimated: indicatorsAnimated.checked @@ -30,237 +29,360 @@ KCMUtils.SimpleKCM { property alias cfg_indicatorShrink: indicatorShrink.value property alias cfg_indicatorDominantColor: indicatorDominantColor.checked property alias cfg_indicatorAccentColor: indicatorAccentColor.checked - property alias cfg_indicatorCustomColor: indicatorCustomColor.color - -Kirigami.FormLayout { - - ComboBox { - id: indicatorsEnabled - Kirigami.FormData.label: i18n("Indicators:") - model: [i18n("Disabled"), i18n("Enabled")] - } - - CheckBox { - id: indicatorProgress - enabled: indicatorsEnabled.currentIndex - visible: indicatorsEnabled.currentIndex - text: i18n("Display Progress on Indicator") - } - - KQControls.ColorButton { - enabled: indicatorsEnabled.currentIndex - visible: indicatorProgress.checked - id: indicatorProgressColor - Kirigami.FormData.label: i18n("Progress Color:") - showAlphaChannel: true - } + property alias cfg_indicatorCustomColor: indicatorCustomColor.color + + // --- Properties to silence KCM errors --- + // Defaults for existing aliases + property var cfg_indicatorsEnabledDefault + property var cfg_groupIconEnabledDefault + property var cfg_indicatorProgressDefault + property var cfg_indicatorProgressColorDefault + property var cfg_disableInactiveIndicatorsDefault + property var cfg_indicatorsAnimatedDefault + property var cfg_indicatorLocationDefault + property var cfg_indicatorReverseDefault + property var cfg_indicatorOverrideDefault + property var cfg_indicatorEdgeOffsetDefault + property var cfg_indicatorStyleDefault + property var cfg_indicatorMinLimitDefault + property var cfg_indicatorMaxLimitDefault + property var cfg_indicatorDesaturateDefault + property var cfg_indicatorGrowDefault + property var cfg_indicatorGrowFactorDefault + property var cfg_indicatorSizeDefault + property var cfg_indicatorLengthDefault + property var cfg_indicatorRadiusDefault + property var cfg_indicatorShrinkDefault + property var cfg_indicatorDominantColorDefault + property var cfg_indicatorAccentColorDefault + property var cfg_indicatorCustomColorDefault + + // Missing properties from main.xml not used in this tab + property var cfg_showOnlyCurrentScreen + property var cfg_showOnlyCurrentScreenDefault + property var cfg_showOnlyCurrentDesktop + property var cfg_showOnlyCurrentDesktopDefault + property var cfg_showOnlyCurrentActivity + property var cfg_showOnlyCurrentActivityDefault + property var cfg_showOnlyMinimized + property var cfg_showOnlyMinimizedDefault + property var cfg_unhideOnAttention + property var cfg_unhideOnAttentionDefault + property var cfg_groupingStrategy + property var cfg_groupingStrategyDefault + property var cfg_iconOnly + property var cfg_iconOnlyDefault + property var cfg_groupedTaskVisualization + property var cfg_groupedTaskVisualizationDefault + property var cfg_groupPopups + property var cfg_groupPopupsDefault + property var cfg_onlyGroupWhenFull + property var cfg_onlyGroupWhenFullDefault + property var cfg_groupingAppIdBlacklist + property var cfg_groupingAppIdBlacklistDefault + property var cfg_groupingLauncherUrlBlacklist + property var cfg_groupingLauncherUrlBlacklistDefault + property var cfg_sortingStrategy + property var cfg_sortingStrategyDefault + property var cfg_separateLaunchers + property var cfg_separateLaunchersDefault + property var cfg_hideLauncherOnStart + property var cfg_hideLauncherOnStartDefault + property var cfg_maxStripes + property var cfg_maxStripesDefault + property var cfg_maxButtonLength + property var cfg_maxButtonLengthDefault + property var cfg_forceStripes + property var cfg_forceStripesDefault + property var cfg_showToolTips + property var cfg_showToolTipsDefault + property var cfg_taskMaxWidth + property var cfg_taskMaxWidthDefault + property var cfg_wheelEnabled + property var cfg_wheelEnabledDefault + property var cfg_wheelSkipMinimized + property var cfg_wheelSkipMinimizedDefault + property var cfg_highlightWindows + property var cfg_highlightWindowsDefault + property var cfg_launchers + property var cfg_launchersDefault + property var cfg_middleClickAction + property var cfg_middleClickActionDefault + property var cfg_indicateAudioStreams + property var cfg_indicateAudioStreamsDefault + property var cfg_iconScale + property var cfg_iconScaleDefault + property var cfg_iconSizePx + property var cfg_iconSizePxDefault + property var cfg_iconSizeOverride + property var cfg_iconSizeOverrideDefault + property var cfg_fill + property var cfg_fillDefault + property var cfg_taskHoverEffect + property var cfg_taskHoverEffectDefault + property var cfg_maxTextLines + property var cfg_maxTextLinesDefault + property var cfg_minimizeActiveTaskOnClick + property var cfg_minimizeActiveTaskOnClickDefault + property var cfg_reverseMode + property var cfg_reverseModeDefault + property var cfg_iconSpacing + property var cfg_iconSpacingDefault + property var cfg_useBorders + property var cfg_useBordersDefault + property var cfg_taskSpacingSize + property var cfg_taskSpacingSizeDefault + property var cfg_buttonColorize + property var cfg_buttonColorizeDefault + property var cfg_buttonColorizeInactive + property var cfg_buttonColorizeInactiveDefault + property var cfg_buttonColorizeDominant + property var cfg_buttonColorizeDominantDefault + property var cfg_buttonColorizeCustom + property var cfg_buttonColorizeCustomDefault + property var cfg_disableButtonSvg + property var cfg_disableButtonSvgDefault + property var cfg_disableButtonInactiveSvg + property var cfg_disableButtonInactiveSvgDefault + property var cfg_overridePlasmaButtonDirection + property var cfg_overridePlasmaButtonDirectionDefault + property var cfg_plasmaButtonDirection + property var cfg_plasmaButtonDirectionDefault + property var cfg_iconZoomFactor + property var cfg_iconZoomFactorDefault + property var cfg_iconZoomDuration + property var cfg_iconZoomDurationDefault + // ----------------------------------------------------------------- + + Kirigami.FormLayout { + + ComboBox { + id: indicatorsEnabled + Kirigami.FormData.label: i18n("Indicators:") + model: [i18n("Disabled"), i18n("Enabled")] + } - CheckBox { - enabled: indicatorsEnabled.currentIndex - visible: indicatorsEnabled.currentIndex - id: disableInactiveIndicators - text: i18n("Disable for Inactive Windows") - } + CheckBox { + id: indicatorProgress + enabled: indicatorsEnabled.currentIndex + visible: indicatorsEnabled.currentIndex + text: i18n("Display Progress on Indicator") + } - ComboBox { - id: groupIconEnabled - Kirigami.FormData.label: i18n("Group Overlay:") - model: [i18n("Disabled"), i18n("Enabled")] - } - Label { - text: i18n("Takes effect on next time plasma groups tasks.") - font: Kirigami.Theme.smallFont - } + KQControls.ColorButton { + enabled: indicatorsEnabled.currentIndex + visible: indicatorProgress.checked + id: indicatorProgressColor + Kirigami.FormData.label: i18n("Progress Color:") + showAlphaChannel: true + } - Item { - Kirigami.FormData.isSection: true - } + CheckBox { + enabled: indicatorsEnabled.currentIndex + visible: indicatorsEnabled.currentIndex + id: disableInactiveIndicators + text: i18n("Disable for Inactive Windows") + } - CheckBox { - enabled: indicatorsEnabled.currentIndex - id: indicatorsAnimated - Kirigami.FormData.label: i18n("Animate Indicators:") - text: i18n("Enabled") - } + ComboBox { + id: groupIconEnabled + Kirigami.FormData.label: i18n("Group Overlay:") + model: [i18n("Disabled"), i18n("Enabled")] + } + Label { + text: i18n("Takes effect on next time plasma groups tasks.") + font: Kirigami.Theme.smallFont + } + Item { + Kirigami.FormData.isSection: true + } - Item { - Kirigami.FormData.isSection: true - } + CheckBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorsAnimated + Kirigami.FormData.label: i18n("Animate Indicators:") + text: i18n("Enabled") + } - CheckBox { - enabled: indicatorsEnabled.currentIndex && !indicatorOverride.checked - id: indicatorReverse - Kirigami.FormData.label: i18n("Indicator Location:") - text: i18n("Reverse shown side") - } - CheckBox { - enabled: indicatorsEnabled.currentIndex - id: indicatorOverride - text: i18n("Override location") - } + Item { + Kirigami.FormData.isSection: true + } - ComboBox { - enabled: indicatorsEnabled.currentIndex - visible: indicatorOverride.checked - id: indicatorLocation - model: [ - i18n("Bottom"), - i18n("Left"), - i18n("Right"), - i18n("Top") - ] - } + CheckBox { + enabled: indicatorsEnabled.currentIndex && !indicatorOverride.checked + id: indicatorReverse + Kirigami.FormData.label: i18n("Indicator Location:") + text: i18n("Reverse shown side") + } - Label { - text: i18n("Be sure to use this when using as a floating widget") - font: Kirigami.Theme.smallFont - } + CheckBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorOverride + text: i18n("Override location") + } - SpinBox { - enabled: indicatorsEnabled.currentIndex - id: indicatorEdgeOffset - Kirigami.FormData.label: i18n("Indicator Edge Offset (px):") - from: 0 - to: 999 - } + ComboBox { + enabled: indicatorsEnabled.currentIndex + visible: indicatorOverride.checked + id: indicatorLocation + model: [ + i18n("Bottom"), + i18n("Left"), + i18n("Right"), + i18n("Top") + ] + } - Item { - Kirigami.FormData.isSection: true - } + Label { + text: i18n("Be sure to use this when using as a floating widget") + font: Kirigami.Theme.smallFont + } - ComboBox { - enabled: indicatorsEnabled.currentIndex - id: indicatorStyle - Kirigami.FormData.label: i18n("Indicator Style:") - Layout.fillWidth: true - Layout.minimumWidth: Kirigami.Units.gridUnit * 14 - model: [ - i18n("Metro"), - i18n("Ciliora"), - i18n("Dashes") - ] - } + SpinBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorEdgeOffset + Kirigami.FormData.label: i18n("Indicator Edge Offset (px):") + from: 0 + to: 999 + } - SpinBox { - enabled: indicatorsEnabled.currentIndex - id: indicatorMinLimit - Kirigami.FormData.label: i18n("Indicator Min Limit:") - from: 0 - to: 10 - } + Item { + Kirigami.FormData.isSection: true + } - SpinBox { - enabled: indicatorsEnabled.currentIndex - id: indicatorMaxLimit - Kirigami.FormData.label: i18n("Indicator Max Limit:") - from: 1 - to: 10 - } + ComboBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorStyle + Kirigami.FormData.label: i18n("Indicator Style:") + Layout.fillWidth: true + Layout.minimumWidth: Kirigami.Units.gridUnit * 14 + model: [ + i18n("Metro"), + i18n("Ciliora"), + i18n("Dashes") + ] + } - CheckBox { - enabled: indicatorsEnabled.currentIndex - id: indicatorDesaturate - Kirigami.FormData.label: i18n("Minimize Options:") - text: i18n("Desaturate") - } + SpinBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorMinLimit + Kirigami.FormData.label: i18n("Indicator Min Limit:") + from: 0 + to: 10 + } - CheckBox { - enabled: indicatorsEnabled.currentIndex - id: indicatorGrow - text: i18n("Shrink when minimized") - } + SpinBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorMaxLimit + Kirigami.FormData.label: i18n("Indicator Max Limit:") + from: 1 + to: 10 + } - SpinBox { - id: indicatorGrowFactor - enabled: indicatorsEnabled.currentIndex - visible: indicatorGrow.checked - from: 100 - to: 10 * 100 - stepSize: 25 - Kirigami.FormData.label: i18n("Growth/Shrink factor:") - - property int decimals: 2 - property real realValue: value / 100 - - validator: DoubleValidator { - bottom: Math.min(indicatorGrowFactor.from, indicatorGrowFactor.to) - top: Math.max(indicatorGrowFactor.from, indicatorGrowFactor.to) + CheckBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorDesaturate + Kirigami.FormData.label: i18n("Minimize Options:") + text: i18n("Desaturate") } - textFromValue: function(value, locale) { - return Number(value / 100).toLocaleString(locale, 'f', indicatorGrowFactor.decimals) + CheckBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorGrow + text: i18n("Shrink when minimized") } - valueFromText: function(text, locale) { - return Number.fromLocaleString(locale, text) * 100 + SpinBox { + id: indicatorGrowFactor + enabled: indicatorsEnabled.currentIndex + visible: indicatorGrow.checked + from: 100 + to: 10 * 100 + stepSize: 25 + Kirigami.FormData.label: i18n("Growth/Shrink factor:") + + property int decimals: 2 + property real realValue: value / 100 + + validator: DoubleValidator { + bottom: Math.min(indicatorGrowFactor.from, indicatorGrowFactor.to) + top: Math.max(indicatorGrowFactor.from, indicatorGrowFactor.to) + } + + textFromValue: function(value, locale) { + return Number(value / 100).toLocaleString(locale, 'f', indicatorGrowFactor.decimals) + } + + valueFromText: function(text, locale) { + return Number.fromLocaleString(locale, text) * 100 + } } - } - Item { - Kirigami.FormData.isSection: true - } + Item { + Kirigami.FormData.isSection: true + } - SpinBox { - enabled: indicatorsEnabled.currentIndex - id: indicatorSize - Kirigami.FormData.label: i18n("Indicator size (px):") - from: 1 - to: 999 - } + SpinBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorSize + Kirigami.FormData.label: i18n("Indicator size (px):") + from: 1 + to: 999 + } - SpinBox { - enabled: indicatorsEnabled.currentIndex - id: indicatorLength - Kirigami.FormData.label: i18n("Indicator length (px):") - from: 1 - to: 999 - } + SpinBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorLength + Kirigami.FormData.label: i18n("Indicator length (px):") + from: 1 + to: 999 + } - SpinBox { - enabled: indicatorsEnabled.currentIndex - id: indicatorRadius - Kirigami.FormData.label: i18n("Indicator Radius (%):") - from: 0 - to: 100 - } + SpinBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorRadius + Kirigami.FormData.label: i18n("Indicator Radius (%):") + from: 0 + to: 100 + } - SpinBox { - enabled: indicatorsEnabled.currentIndex - id: indicatorShrink - Kirigami.FormData.label: i18n("Indicator margin (px):") - from: 0 - to: 999 - } + SpinBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorShrink + Kirigami.FormData.label: i18n("Indicator margin (px):") + from: 0 + to: 999 + } - Item { - Kirigami.FormData.isSection: true - } + Item { + Kirigami.FormData.isSection: true + } - CheckBox { - enabled: indicatorsEnabled.currentIndex & !indicatorAccentColor.checked - id: indicatorDominantColor - Kirigami.FormData.label: i18n("Indicator Color:") - text: i18n("Use dominant icon color") - } + CheckBox { + enabled: indicatorsEnabled.currentIndex & !indicatorAccentColor.checked + id: indicatorDominantColor + Kirigami.FormData.label: i18n("Indicator Color:") + text: i18n("Use dominant icon color") + } - CheckBox { - enabled: indicatorsEnabled.currentIndex & !indicatorDominantColor.checked - id: indicatorAccentColor - text: i18n("Use plasma accent color") - } + CheckBox { + enabled: indicatorsEnabled.currentIndex & !indicatorDominantColor.checked + id: indicatorAccentColor + text: i18n("Use plasma accent color") + } - KQControls.ColorButton { - enabled: indicatorsEnabled.currentIndex & !indicatorDominantColor.checked & !indicatorAccentColor.checked - id: indicatorCustomColor - Kirigami.FormData.label: i18n("Custom Color:") - showAlphaChannel: true - } + KQControls.ColorButton { + enabled: indicatorsEnabled.currentIndex & !indicatorDominantColor.checked & !indicatorAccentColor.checked + id: indicatorCustomColor + Kirigami.FormData.label: i18n("Custom Color:") + showAlphaChannel: true + } - Item { - Kirigami.FormData.isSection: true + Item { + Kirigami.FormData.isSection: true + } } } -} diff --git a/package/contents/ui/ConfigPinnedApps.qml b/package/contents/ui/ConfigPinnedApps.qml index f714ec15..e3ec8957 100644 --- a/package/contents/ui/ConfigPinnedApps.qml +++ b/package/contents/ui/ConfigPinnedApps.qml @@ -2,7 +2,6 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts -import org.kde.kcmutils as KCMUtils import org.kde.kirigami as Kirigami import org.kde.plasma.core as PlasmaCore import org.kde.plasma.components as PlasmaComponents @@ -10,7 +9,7 @@ import org.kde.plasma.extras as PlasmaExtras import org.kde.plasma.plasmoid import org.kde.plasma.plasma5support as P5Support -KCMUtils.SimpleKCM { +Kirigami.ScrollablePage { id: pinnedAppsDialog property var pinnedLaunchers: plasmoid.configuration.launchers @@ -19,101 +18,151 @@ KCMUtils.SimpleKCM { property bool isLoadingApps: false property int appsBatchSize: 15 - // App picker dialog - Dialog { - id: appPickerDialog - title: i18n("Add Application") - modal: true - standardButtons: Dialog.Close - - width: Math.min(800, parent.width - Kirigami.Units.gridUnit * 4) - height: Math.min(600, parent.height - Kirigami.Units.gridUnit * 4) - - anchors.centerIn: parent - - onOpened: { - if (!initialLoadDone) { - initialLoadDone = true; - initialLoadTimer.start(); - } - } - - ColumnLayout { - anchors.fill: parent - spacing: Kirigami.Units.smallSpacing - - PlasmaExtras.SearchField { - id: searchField - Layout.fillWidth: true - placeholderText: i18n("Search applications...") - onTextChanged: searchTimer.restart() - } - - Timer { - id: searchTimer - interval: 300 - onTriggered: filterAppsModel() - } - - ScrollView { - Layout.fillWidth: true - Layout.fillHeight: true - - ListView { - id: appsListView - model: filteredAppsModel - - onContentYChanged: { - if (contentY + height >= contentHeight - 200 && !isLoadingApps) { - loadMoreApps(); - } - } - - delegate: ItemDelegate { - width: appsListView.width - - contentItem: RowLayout { - spacing: Kirigami.Units.smallSpacing - - Kirigami.Icon { - source: model.icon || "application-x-executable" - Layout.preferredWidth: Kirigami.Units.iconSizes.medium - Layout.preferredHeight: Kirigami.Units.iconSizes.medium - } - - Label { - text: model.name || model.url - elide: Text.ElideRight - Layout.fillWidth: true - font.bold: true - } - - Button { - icon.name: "list-add" - text: i18n("Add") - onClicked: { - addLauncher(model.url); - appPickerDialog.close(); - } - } - } - } - } - } - - // Loading indicator - Item { - visible: isLoadingApps && filteredAppsModel.count === 0 - Layout.fillWidth: true - Layout.fillHeight: true - - BusyIndicator { - anchors.centerIn: parent - running: isLoadingApps - } - } - } - } + // --- Properties to silence KCM errors --- + // Defaults for existing aliases + property var cfg_launchersDefault + + // Missing properties from main.xml not used in this tab + property var cfg_showOnlyCurrentScreen + property var cfg_showOnlyCurrentScreenDefault + property var cfg_showOnlyCurrentDesktop + property var cfg_showOnlyCurrentDesktopDefault + property var cfg_showOnlyCurrentActivity + property var cfg_showOnlyCurrentActivityDefault + property var cfg_showOnlyMinimized + property var cfg_showOnlyMinimizedDefault + property var cfg_unhideOnAttention + property var cfg_unhideOnAttentionDefault + property var cfg_groupingStrategy + property var cfg_groupingStrategyDefault + property var cfg_iconOnly + property var cfg_iconOnlyDefault + property var cfg_groupedTaskVisualization + property var cfg_groupedTaskVisualizationDefault + property var cfg_groupPopups + property var cfg_groupPopupsDefault + property var cfg_onlyGroupWhenFull + property var cfg_onlyGroupWhenFullDefault + property var cfg_groupingAppIdBlacklist + property var cfg_groupingAppIdBlacklistDefault + property var cfg_groupingLauncherUrlBlacklist + property var cfg_groupingLauncherUrlBlacklistDefault + property var cfg_sortingStrategy + property var cfg_sortingStrategyDefault + property var cfg_separateLaunchers + property var cfg_separateLaunchersDefault + property var cfg_hideLauncherOnStart + property var cfg_hideLauncherOnStartDefault + property var cfg_maxStripes + property var cfg_maxStripesDefault + property var cfg_maxButtonLength + property var cfg_maxButtonLengthDefault + property var cfg_forceStripes + property var cfg_forceStripesDefault + property var cfg_showToolTips + property var cfg_showToolTipsDefault + property var cfg_taskMaxWidth + property var cfg_taskMaxWidthDefault + property var cfg_wheelEnabled + property var cfg_wheelEnabledDefault + property var cfg_wheelSkipMinimized + property var cfg_wheelSkipMinimizedDefault + property var cfg_highlightWindows + property var cfg_highlightWindowsDefault + property var cfg_launchers // Used manually via plasmoid.configuration + property var cfg_middleClickAction + property var cfg_middleClickActionDefault + property var cfg_indicateAudioStreams + property var cfg_indicateAudioStreamsDefault + property var cfg_iconScale + property var cfg_iconScaleDefault + property var cfg_iconSizePx + property var cfg_iconSizePxDefault + property var cfg_iconSizeOverride + property var cfg_iconSizeOverrideDefault + property var cfg_fill + property var cfg_fillDefault + property var cfg_taskHoverEffect + property var cfg_taskHoverEffectDefault + property var cfg_maxTextLines + property var cfg_maxTextLinesDefault + property var cfg_minimizeActiveTaskOnClick + property var cfg_minimizeActiveTaskOnClickDefault + property var cfg_reverseMode + property var cfg_reverseModeDefault + property var cfg_iconSpacing + property var cfg_iconSpacingDefault + property var cfg_indicatorsEnabled + property var cfg_indicatorsEnabledDefault + property var cfg_indicatorProgress + property var cfg_indicatorProgressDefault + property var cfg_indicatorProgressColor + property var cfg_indicatorProgressColorDefault + property var cfg_disableInactiveIndicators + property var cfg_disableInactiveIndicatorsDefault + property var cfg_indicatorsAnimated + property var cfg_indicatorsAnimatedDefault + property var cfg_groupIconEnabled + property var cfg_groupIconEnabledDefault + property var cfg_indicatorLocation + property var cfg_indicatorLocationDefault + property var cfg_indicatorStyle + property var cfg_indicatorStyleDefault + property var cfg_indicatorMinLimit + property var cfg_indicatorMinLimitDefault + property var cfg_indicatorMaxLimit + property var cfg_indicatorMaxLimitDefault + property var cfg_indicatorDesaturate + property var cfg_indicatorDesaturateDefault + property var cfg_indicatorGrow + property var cfg_indicatorGrowDefault + property var cfg_indicatorGrowFactor + property var cfg_indicatorGrowFactorDefault + property var cfg_indicatorEdgeOffset + property var cfg_indicatorEdgeOffsetDefault + property var cfg_indicatorSize + property var cfg_indicatorSizeDefault + property var cfg_indicatorLength + property var cfg_indicatorLengthDefault + property var cfg_indicatorRadius + property var cfg_indicatorRadiusDefault + property var cfg_indicatorShrink + property var cfg_indicatorShrinkDefault + property var cfg_indicatorDominantColor + property var cfg_indicatorDominantColorDefault + property var cfg_indicatorAccentColor + property var cfg_indicatorAccentColorDefault + property var cfg_indicatorCustomColor + property var cfg_indicatorCustomColorDefault + property var cfg_useBorders + property var cfg_useBordersDefault + property var cfg_taskSpacingSize + property var cfg_taskSpacingSizeDefault + property var cfg_buttonColorize + property var cfg_buttonColorizeDefault + property var cfg_buttonColorizeInactive + property var cfg_buttonColorizeInactiveDefault + property var cfg_buttonColorizeDominant + property var cfg_buttonColorizeDominantDefault + property var cfg_buttonColorizeCustom + property var cfg_buttonColorizeCustomDefault + property var cfg_disableButtonSvg + property var cfg_disableButtonSvgDefault + property var cfg_disableButtonInactiveSvg + property var cfg_disableButtonInactiveSvgDefault + property var cfg_overridePlasmaButtonDirection + property var cfg_overridePlasmaButtonDirectionDefault + property var cfg_plasmaButtonDirection + property var cfg_plasmaButtonDirectionDefault + property var cfg_indicatorReverse + property var cfg_indicatorReverseDefault + property var cfg_indicatorOverride + property var cfg_indicatorOverrideDefault + property var cfg_iconZoomFactor + property var cfg_iconZoomFactorDefault + property var cfg_iconZoomDuration + property var cfg_iconZoomDurationDefault + // --------------------------------------- // Initial app loading timer Timer { @@ -135,7 +184,7 @@ KCMUtils.SimpleKCM { property var requestedSources: ({}) - onSourceConnected: { + onSourceConnected: (source) => { processAppSource(source); } } @@ -157,14 +206,12 @@ KCMUtils.SimpleKCM { url: "preferred://browser", keywords: "web browser internet" }); - installedAppsModel.append({ name: i18n("Default File Manager"), icon: "system-file-manager", url: "preferred://filemanager", keywords: "files folder" }); - installedAppsModel.append({ name: i18n("Default Mail Client"), icon: "internet-mail", @@ -181,7 +228,6 @@ KCMUtils.SimpleKCM { // Create a prioritized list of desktop files const desktopFiles = []; const commonPrefixes = ["firefox", "chromium", "chrome", "brave", "dolphin", "konsole", "kate", "gnome-terminal", "org.kde"]; - // Pre-sort desktop files with common ones first for (let i = 0; i < appsSource.sources.length; i++) { const source = appsSource.sources[i]; @@ -206,17 +252,14 @@ KCMUtils.SimpleKCM { // Sort by priority desktopFiles.sort((a, b) => a.priority - b.priority); - // Process in batches let processedCount = 0; - function processBatch() { const batchSize = 15; const end = Math.min(processedCount + batchSize, desktopFiles.length); for (let i = processedCount; i < end; i++) { const source = desktopFiles[i].source; - if (!appsSource.requestedSources[source]) { appsSource.connectSource(source); appsSource.requestedSources[source] = true; @@ -224,7 +267,6 @@ KCMUtils.SimpleKCM { } processedCount = end; - if (processedCount < desktopFiles.length) { // Schedule next batch Qt.callLater(processBatch); @@ -252,7 +294,6 @@ KCMUtils.SimpleKCM { appName = appName.substring(lastSlash + 1); } appName = appName.split(/[-_.]/).map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" "); - // Check for duplicates for (let j = 0; j < installedAppsModel.count; j++) { if (installedAppsModel.get(j).url === "applications:" + source) { @@ -266,7 +307,6 @@ KCMUtils.SimpleKCM { url: "applications:" + source, keywords: "" }); - // Update filtered model if needed if (searchField.text.length === 0 && filteredAppsModel.count < 100) { filteredAppsModel.append({ @@ -283,7 +323,6 @@ KCMUtils.SimpleKCM { function filterAppsModel() { const searchText = searchField.text.toLowerCase(); - // Optimization for empty search with already filled model if (searchText.length === 0 && filteredAppsModel.count > 0 && filteredAppsModel.count === Math.min(installedAppsModel.count, 100)) { return; @@ -293,7 +332,6 @@ KCMUtils.SimpleKCM { for (let i = 0; i < installedAppsModel.count; i++) { const app = installedAppsModel.get(i); - // Apply search filter if (searchText && searchText.length > 0) { if (app.name.toLowerCase().includes(searchText) || app.url.toLowerCase().includes(searchText) || (app.keywords && app.keywords.toLowerCase().includes(searchText))) { @@ -301,7 +339,6 @@ KCMUtils.SimpleKCM { } } else { filteredAppsModel.append(app); - // Limit initial load for better performance if (filteredAppsModel.count >= 100) { break; @@ -313,7 +350,6 @@ KCMUtils.SimpleKCM { function loadMoreApps() { if (isLoadingApps) return; - if (filteredAppsModel.count < installedAppsModel.count) { const startIndex = filteredAppsModel.count; const endIndex = Math.min(startIndex + 30, installedAppsModel.count); @@ -344,7 +380,6 @@ KCMUtils.SimpleKCM { function getNameForUrl(url) { let appName = url; - if (appName.indexOf("preferred://") === 0) { if (appName === "preferred://browser") return i18n("Default Web Browser"); @@ -379,7 +414,6 @@ KCMUtils.SimpleKCM { function getIconForUrl(url) { let appId = url; - // Check installed apps model first for (let i = 0; i < installedAppsModel.count; i++) { const app = installedAppsModel.get(i); @@ -422,6 +456,104 @@ KCMUtils.SimpleKCM { anchors.fill: parent spacing: Kirigami.Units.largeSpacing + resources: [ + // App picker dialog moved here + Dialog { + id: appPickerDialog + title: i18n("Add Application") + modal: true + standardButtons: Dialog.Close + + width: Math.min(800, parent.width - Kirigami.Units.gridUnit * 4) + height: Math.min(600, parent.height - Kirigami.Units.gridUnit * 4) + + anchors.centerIn: parent + + onOpened: { + if (!initialLoadDone) { + initialLoadDone = true; + initialLoadTimer.start(); + } + } + + ColumnLayout { + anchors.fill: parent + spacing: Kirigami.Units.smallSpacing + + PlasmaExtras.SearchField { + id: searchField + Layout.fillWidth: true + placeholderText: i18n("Search applications...") + onTextChanged: searchTimer.restart() + } + + Timer { + id: searchTimer + interval: 300 + onTriggered: filterAppsModel() + } + + ScrollView { + Layout.fillWidth: true + Layout.fillHeight: true + + ListView { + id: appsListView + model: filteredAppsModel + + onContentYChanged: { + if (contentY + height >= contentHeight - 200 && !isLoadingApps) { + loadMoreApps(); + } + } + + delegate: ItemDelegate { + width: appsListView.width + + contentItem: RowLayout { + spacing: Kirigami.Units.smallSpacing + + Kirigami.Icon { + source: model.icon || "application-x-executable" + Layout.preferredWidth: Kirigami.Units.iconSizes.medium + Layout.preferredHeight: Kirigami.Units.iconSizes.medium + } + + Label { + text: model.name || model.url + elide: Text.ElideRight + Layout.fillWidth: true + font.bold: true + } + + Button { + icon.name: "list-add" + text: i18n("Add") + onClicked: { + addLauncher(model.url); + appPickerDialog.close(); + } + } + } + } + } + } + + // Loading indicator + Item { + visible: isLoadingApps && filteredAppsModel.count === 0 + Layout.fillWidth: true + Layout.fillHeight: true + + BusyIndicator { + anchors.centerIn: parent + running: isLoadingApps + } + } + } + } + ] + Kirigami.InlineMessage { Layout.fillWidth: true type: Kirigami.MessageType.Information @@ -450,7 +582,8 @@ KCMUtils.SimpleKCM { onEntered: { if (isDragging) { // Calculate new index based on drop position - var newIndex = Math.floor((drag.y + pinnedAppsList.contentY) / 48); // Approximate item height + var newIndex = Math.floor((drag.y + pinnedAppsList.contentY) / 48); + // Approximate item height if (newIndex >= 0 && newIndex < pinnedAppsModel.count) { dropItemIndex = newIndex; } @@ -536,7 +669,8 @@ KCMUtils.SimpleKCM { Rectangle { id: itemHighlight anchors.fill: parent - color: dropItemIndex === index && isDragging ? Kirigami.Theme.highlightColor : mouseArea.containsMouse ? Kirigami.Theme.highlightColor.lighter(0.7) : "transparent" + color: dropItemIndex === index && isDragging ? +Kirigami.Theme.highlightColor : mouseArea.containsMouse ? Kirigami.Theme.highlightColor.lighter(0.7) : "transparent" opacity: 0.3 radius: 3 @@ -622,7 +756,6 @@ KCMUtils.SimpleKCM { onReleased: { // End dragging isDragging = false; - if (dropItemIndex !== -1 && dragItemIndex !== -1 && dropItemIndex !== dragItemIndex) { // Move the item moveItem(dragItemIndex, dropItemIndex); @@ -686,7 +819,6 @@ KCMUtils.SimpleKCM { function addLauncher(url) { let currentLaunchers = pinnedLaunchers; - // Don't add if already in the list if (currentLaunchers.indexOf(url) !== -1) { return; @@ -712,11 +844,9 @@ KCMUtils.SimpleKCM { console.log("Moving item from", fromIndex, "to", toIndex); console.log("New order:", currentLaunchers.join(", ")); - // Update the configuration plasmoid.configuration.launchers = currentLaunchers; pinnedLaunchers = currentLaunchers; - // Refresh model to ensure view is updated refreshPinnedAppsModel(); } From b4b36a22cc118475e74851f217194afcaf690969 Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Tue, 23 Dec 2025 23:54:05 +0200 Subject: [PATCH 133/141] Fix translation data --- .../plasma_applet_alexankitty.fancytasks.mo | Bin 17570 -> 16858 bytes package/contents/ui/ConfigAppearance.qml | 38 ++-- package/contents/ui/ConfigBehavior.qml | 90 +++++----- package/metadata.json | 2 + package/translate/ReadMe.md | 9 +- package/translate/ru_RU.po | 170 ++---------------- 6 files changed, 89 insertions(+), 220 deletions(-) diff --git a/package/contents/locale/ru_RU/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo b/package/contents/locale/ru_RU/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo index defaa7361afbba59c791ae7a1bb22ccbe499fd5e..0276148c681cbe74257f47bc0b96a8c13396fb45 100644 GIT binary patch delta 6843 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 diff --git a/package/contents/ui/ConfigAppearance.qml b/package/contents/ui/ConfigAppearance.qml index 8073fd24..9cb9f9ce 100644 --- a/package/contents/ui/ConfigAppearance.qml +++ b/package/contents/ui/ConfigAppearance.qml @@ -273,7 +273,7 @@ Kirigami.ScrollablePage { KQuickAddons.ColorButton { id: buttonColorizeCustom - Layout.leftMargin: Kirigami.Units.GridUnit + Layout.leftMargin: Kirigami.Units.gridUnit enabled: buttonColorize.checked & !buttonColorizeDominant.checked Kirigami.FormData.label: i18n("Custom Color:") showAlphaChannel: true @@ -340,18 +340,18 @@ Kirigami.ScrollablePage { CheckBox { id: showToolTips - Kirigami.FormData.label: i18nc("@label for several checkboxes", "General:") - text: i18nc("@option:check section General", "Show small window previews when hovering over tasks") + Kirigami.FormData.label: i18n("General:") + text: i18n("Show small window previews when hovering over tasks") } CheckBox { id: highlightWindows - text: i18nc("@option:check section General", "Hide other windows when hovering over previews") + text: i18n("Hide other windows when hovering over previews") } CheckBox { id: indicateAudioStreams - text: i18nc("@option:check section General", "Mark applications that play audio") + text: i18n("Mark applications that play audio") checked: cfg_indicateAudioStreams && plasmaPaAvailable onToggled: cfg_indicateAudioStreams = checked enabled: plasmaPaAvailable @@ -359,7 +359,7 @@ Kirigami.ScrollablePage { CheckBox { id: fill - text: i18nc("@option:check section General", "Fill free space on panel") + text: i18n("Fill free space on panel") } Item { @@ -371,9 +371,9 @@ Kirigami.ScrollablePage { id: taskMaxWidth visible: !iconOnly && !plasmoidVertical - Kirigami.FormData.label: i18nc("@label:listbox", "Maximum task width:") + Kirigami.FormData.label: i18n("Maximum task width:") - model: [i18nc("@item:inlistbox how wide a task item should be", "Narrow"), i18nc("@item:inlistbox how wide a task item should be", "Medium"), i18nc("@item:inlistbox how wide a task item should be", "Wide")] + model: [i18n("Narrow"), i18n("Medium"), i18n("Wide")] } Item { @@ -382,14 +382,13 @@ Kirigami.ScrollablePage { RadioButton { id: forbidStripes - Kirigami.FormData.label: plasmoidVertical ? -i18nc("@label for radio button group, completes sentence: … when panel is low on space etc.", "Use multi-column view:") : i18nc("@label for radio button group, completes sentence: … when panel is low on space etc.", "Use multi-row view:") + Kirigami.FormData.label: plasmoidVertical ? i18n("Use multi-column view:") : i18n("Use multi-row view:") onToggled: { if (checked) { maxStripes.value = 1; } } - text: i18nc("@option:radio Never use multi-column view for Task Manager", "Never") + text: i18n("Never") } RadioButton { @@ -399,7 +398,7 @@ i18nc("@label for radio button group, completes sentence: … when panel is low maxStripes.value = Math.max(2, maxStripes.value); } } - text: i18nc("@option:radio completes sentence: Use multi-column/row view", "When panel is low on space and thick enough") + text: i18n("When panel is low on space and thick enough") } RadioButton { @@ -409,14 +408,13 @@ i18nc("@label for radio button group, completes sentence: … when panel is low maxStripes.value = Math.max(2, maxStripes.value); } } - text: i18nc("@option:radio completes sentence: Use multi-column/row view", "Always when panel is thick enough") + text: i18n("Always when panel is thick enough") } SpinBox { id: maxStripes enabled: maxStripes.value > 1 - Kirigami.FormData.label: plasmoidVertical ? -i18nc("@label:spinbox maximum number of columns for tasks", "Maximum columns:") : i18nc("@label:spinbox maximum number of rows for tasks", "Maximum rows:") + Kirigami.FormData.label: plasmoidVertical ? i18n("Maximum columns:") : i18n("Maximum rows:") from: 1 } @@ -426,19 +424,19 @@ i18nc("@label:spinbox maximum number of columns for tasks", "Maximum columns:") ComboBox { visible: iconOnly - Kirigami.FormData.label: i18nc("@label:listbox", "Spacing between icons:") + Kirigami.FormData.label: i18n("Spacing between icons:") model: [ { - "label": i18nc("@item:inlistbox Icon spacing", "Small"), + "label": i18n("Small"), "spacing": 0 }, { - "label": i18nc("@item:inlistbox Icon spacing", "Normal"), + "label": i18n("Normal"), "spacing": 1 }, { - "label": i18nc("@item:inlistbox Icon spacing", "Large"), + "label": i18n("Large"), "spacing": 3 }, ] @@ -467,7 +465,7 @@ i18nc("@label:spinbox maximum number of columns for tasks", "Maximum columns:") Label { visible: Kirigami.Settings.tabletMode - text: i18nc("@info:usagetip under a set of radio buttons when Touch Mode is on", "Automatically set to Large when in Touch mode") + text: i18n("Automatically set to Large when in Touch mode") font: Kirigami.Theme.smallFont } } diff --git a/package/contents/ui/ConfigBehavior.qml b/package/contents/ui/ConfigBehavior.qml index 70d2e23d..9db8e817 100644 --- a/package/contents/ui/ConfigBehavior.qml +++ b/package/contents/ui/ConfigBehavior.qml @@ -178,28 +178,28 @@ Kirigami.ScrollablePage { ComboBox { id: groupingStrategy - Kirigami.FormData.label: i18nc("@label:listbox how to group tasks", "Group:") + Kirigami.FormData.label: i18n("Group:") Layout.fillWidth: true Layout.minimumWidth: Kirigami.Units.gridUnit * 14 model: [ - i18nc("@item:inlistbox how to group tasks", "Do not group"), - i18nc("@item:inlistbox how to group tasks", "By program name") + i18n("Do not group"), + i18n("By program name") ] } ComboBox { id: groupedTaskVisualization - Kirigami.FormData.label: i18nc("@label:listbox completes sentence like: … cycles through tasks", "Clicking grouped task:") + Kirigami.FormData.label: i18n("Clicking grouped task:") Layout.fillWidth: true Layout.minimumWidth: Kirigami.Units.gridUnit * 14 enabled: groupingStrategy.currentIndex !== 0 model: [ - i18nc("@item:inlistbox Completes the sentence 'Clicking grouped task cycles through tasks' ", "Cycles through tasks"), - i18nc("@item:inlistbox Completes the sentence 'Clicking grouped task shows small window previews' ", "Shows small window previews"), - i18nc("@item:inlistbox Completes the sentence 'Clicking grouped task shows large window previews' ", "Shows large window previews"), - i18nc("@item:inlistbox Completes the sentence 'Clicking grouped task shows textual list' ", "Shows textual list"), + i18n("Cycles through tasks"), + i18n("Shows small window previews"), + i18n("Shows large window previews"), + i18n("Shows textual list"), ] Accessible.name: currentText @@ -210,7 +210,7 @@ Kirigami.ScrollablePage { Layout.fillWidth: true visible: groupedTaskVisualization.currentIndex === 2 && !effectWatcher.registered type: Kirigami.MessageType.Warning - text: i18nc("@info displayed as InlineMessage", "The compositor does not support displaying windows side by side, so a textual list will be displayed instead.") + text: i18n("The compositor does not support displaying windows side by side, so a textual list will be displayed instead.") } Item { @@ -220,14 +220,14 @@ Kirigami.ScrollablePage { CheckBox { id: groupPopups visible: (!plasmoid.configuration.iconOnly) - text: i18nc("@option:check grouped task", "Combine into single button") + text: i18n("Combine into single button") enabled: groupingStrategy.currentIndex > 0 } CheckBox { id: onlyGroupWhenFull visible: (!plasmoid.configuration.iconOnly) - text: i18nc("@option:check grouped task","Group only when the Task Manager is full") + text: i18n("Group only when the Task Manager is full") enabled: groupingStrategy.currentIndex > 0 && groupPopups.checked Accessible.onPressAction: toggle() } @@ -239,29 +239,29 @@ Kirigami.ScrollablePage { ComboBox { id: sortingStrategy - Kirigami.FormData.label: i18nc("@label:listbox sort tasks in grouped task", "Sort:") + Kirigami.FormData.label: i18n("Sort:") Layout.fillWidth: true Layout.minimumWidth: Kirigami.Units.gridUnit * 14 model: [ - i18nc("@item:inlistbox sort tasks in grouped task", "Do not sort"), - i18nc("@item:inlistbox sort tasks in grouped task", "Manually"), - i18nc("@item:inlistbox sort tasks in grouped task", "Alphabetically"), - i18nc("@item:inlistbox sort tasks in grouped task", "By desktop"), - i18nc("@item:inlistbox sort tasks in grouped task", "By activity") + i18n("Do not sort"), + i18n("Manually"), + i18n("Alphabetically"), + i18n("By desktop"), + i18n("By activity") ] } CheckBox { id: separateLaunchers visible: (!plasmoid.configuration.iconOnly) - text: i18nc("@option:check configure task sorting", "Keep launchers separate") + text: i18n("Keep launchers separate") enabled: sortingStrategy.currentIndex === 1 } CheckBox { id: hideLauncherOnStart visible: (!plasmoid.configuration.iconOnly) - text: i18nc("@option:check for icons-and-text task manager", "Hide launchers after application startup") + text: i18n("Hide launchers after application startup") } Item { @@ -271,22 +271,22 @@ Kirigami.ScrollablePage { CheckBox { id: minimizeActive - Kirigami.FormData.label: i18nc("@label for checkbox Part of a sentence: 'Clicking active task minimizes the task'", "Clicking active task:") - text: i18nc("@option:check Part of a sentence: 'Clicking active task minimizes the task'", "Minimizes the task") + Kirigami.FormData.label: i18n("Clicking active task:") + text: i18n("Minimizes the task") } ComboBox { id: middleClickAction - Kirigami.FormData.label: i18nc("@label:listbox completes sentence like: … does nothing", "Middle-clicking any task:") + Kirigami.FormData.label: i18n("Middle-clicking any task:") Layout.fillWidth: true Layout.minimumWidth: Kirigami.Units.gridUnit * 14 model: [ - i18nc("@item:inlistbox Part of a sentence: 'Middle-clicking any task does nothing'", "Does nothing"), - i18nc("@item:inlistbox Part of a sentence: 'Middle-clicking any task closes window or group'", "Closes window or group"), - i18nc("@item:inlistbox Part of a sentence: 'Middle-clicking any task opens a new window'", "Opens a new window"), - i18nc("@item:inlistbox Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'", "Minimizes/Restores window or group"), - i18nc("@item:inlistbox Part of a sentence: 'Middle-clicking any task toggles grouping'", "Toggles grouping"), - i18nc("@item:inlistbox Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'", "Brings it to the current virtual desktop") + i18n("Does nothing"), + i18n("Closes window or group"), + i18n("Opens a new window"), + i18n("Minimizes/Restores window or group"), + i18n("Toggles grouping"), + i18n("Brings it to the current virtual desktop") ] } @@ -296,8 +296,8 @@ Kirigami.ScrollablePage { CheckBox { id: wheelEnabled - Kirigami.FormData.label: i18nc("@label for checkbox Part of a sentence: 'Mouse wheel cycles through tasks'", "Mouse wheel:") - text: i18nc("@option:check Part of a sentence: 'Mouse wheel cycles through tasks'", "Cycles through tasks") + Kirigami.FormData.label: i18n("Mouse wheel:") + text: i18n("Cycles through tasks") } RowLayout { @@ -306,7 +306,7 @@ Kirigami.ScrollablePage { Item { implicitWidth: Kirigami.Units.gridUnit } CheckBox { id: wheelSkipMinimized - text: i18nc("@option:check mouse wheel task cycling", "Skip minimized tasks") + text: i18n("Skip minimized tasks") enabled: wheelEnabled.checked } } @@ -317,23 +317,23 @@ Kirigami.ScrollablePage { CheckBox { id: showOnlyCurrentScreen - Kirigami.FormData.label: i18nc("@label for checkbox group, completes sentence like: … from current screen", "Show only tasks:") - text: i18nc("@option:check completes sentence: show only tasks", "From current screen") + Kirigami.FormData.label: i18n("Show only tasks:") + text: i18n("From current screen") } CheckBox { id: showOnlyCurrentDesktop - text: i18nc("@option:check completes sentence: show only tasks", "From current desktop") + text: i18n("From current desktop") } CheckBox { id: showOnlyCurrentActivity - text: i18nc("@option:check completes sentence: show only tasks", "From current activity") + text: i18n("From current activity") } CheckBox { id: showOnlyMinimized - text: i18nc("@option:check completes sentence: show only tasks", "That are minimized") + text: i18n("That are minimized") } Item { @@ -342,8 +342,8 @@ Kirigami.ScrollablePage { CheckBox { id: unhideOnAttention - Kirigami.FormData.label: i18nc("@label for checkbox, completes sentence: … unhide if window wants attention", "When panel is hidden:") - text: i18nc("@option:check completes sentence: When panel is hidden", "Unhide when a window wants attention") + Kirigami.FormData.label: i18n("When panel is hidden:") + text: i18n("Unhide when a window wants attention") } Item { @@ -355,17 +355,17 @@ Kirigami.ScrollablePage { } RadioButton { - Kirigami.FormData.label: i18nc("@label for radiobutton group completes sentence like: … on the bottom", "New tasks appear:") + Kirigami.FormData.label: i18n("New tasks appear:") checked: !reverseMode.checked text: { if (Plasmoid.formFactor === PlasmaCore.Types.Vertical) { - return i18nc("@option:check completes sentence: New tasks appear", "On the bottom") + return i18n("On the bottom") } // horizontal if (Qt.application.layoutDirection === Qt.LeftToRight) { - return i18nc("@option:check completes sentence: New tasks appear", "To the right"); + return i18n("To the right"); } else { - return i18nc("@option:check completes sentence: New tasks appear", "To the left") + return i18n("To the left") } } ButtonGroup.group: reverseModeRadioButtonGroup @@ -376,13 +376,13 @@ Kirigami.ScrollablePage { checked: Plasmoid.configuration.reverseMode === true text: { if (Plasmoid.formFactor === PlasmaCore.Types.Vertical) { - return i18nc("@option:check completes sentence: New tasks appear", "On the top") + return i18n("On the top") } // horizontal if (Qt.application.layoutDirection === Qt.LeftToRight) { - return i18nc("@option:check completes sentence: New tasks appear", "To the left"); + return i18n("To the left"); } else { - return i18nc("@option:check completes sentence: New tasks appear", "To the right"); + return i18n("To the right"); } } ButtonGroup.group: reverseModeRadioButtonGroup diff --git a/package/metadata.json b/package/metadata.json index 369c10d8..26071bf1 100644 --- a/package/metadata.json +++ b/package/metadata.json @@ -17,11 +17,13 @@ ], "Category": "Windows and Tasks", "Description": "More modern taskbar-style window switcher displaying icons and text, with some improvments and customization options", + "Description[ru]": "Современный переключатель окон в стиле панели задач с иконками, текстом и расширенными настройками", "EnabledByDefault": true, "Icon": "FancyTasks.png", "Id": "alexankitty.fancytasks", "License": "GPL-2.0+", "Name": "Fancy Tasks", + "Name[ru]": "Fancy Tasks", "ServiceTypes": [ "Plasma/Applet" ], diff --git a/package/translate/ReadMe.md b/package/translate/ReadMe.md index f4a4a149..d8a22b8e 100644 --- a/package/translate/ReadMe.md +++ b/package/translate/ReadMe.md @@ -35,7 +35,8 @@ Or if you know how to make a pull request ## Status | Locale | Lines | % Done| |----------|---------|-------| -| Template | 165 | | -| nl | 150/165 | 90% | -| pt_BR | 165/165 | 100% | -| zh_CN | 150/165 | 90% | +| Template | 207 | | +| nl | 171/207 | 83% | +| pt_BR | 185/207 | 89% | +| zh_CN | 166/207 | 80% | +| ru_RU | 207/207 | 100% | diff --git a/package/translate/ru_RU.po b/package/translate/ru_RU.po index 9a063570..2218f379 100644 --- a/package/translate/ru_RU.po +++ b/package/translate/ru_RU.po @@ -34,22 +34,22 @@ msgstr "Закрепленные приложения" #: ../contents/ui/AudioStream.qml msgctxt "@action:button" msgid "Unmute" -msgstr "" +msgstr "Включить звук" #: ../contents/ui/AudioStream.qml msgctxt "@action:button" msgid "Mute" -msgstr "" +msgstr "Выключить звук" #: ../contents/ui/AudioStream.qml msgctxt "@info:tooltip %1 is the window title" msgid "Unmute %1" -msgstr "" +msgstr "Включить звук %1" #: ../contents/ui/AudioStream.qml msgctxt "@info:tooltip %1 is the window title" msgid "Mute %1" -msgstr "" +msgstr "Выключить звук %1" #: ../contents/ui/Badge.qml msgctxt "Invalid number of new messages, overlay, keep short" @@ -170,109 +170,88 @@ msgid "Space between taskbar items (px):" msgstr "Расстояние между элементами (px):" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@label for several checkboxes" msgid "General:" msgstr "Общие:" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@option:check section General" msgid "Show small window previews when hovering over tasks" msgstr "Показывать миниатюры окон при наведении" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@option:check section General" msgid "Hide other windows when hovering over previews" msgstr "Скрывать остальные окна при наведении на миниатюру" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@option:check section General" msgid "Mark applications that play audio" msgstr "Помечать приложения, воспроизводящие звук" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@option:check section General" msgid "Fill free space on panel" msgstr "Заполнять свободное место панели" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@label:listbox" msgid "Maximum task width:" msgstr "Макс. ширина задачи:" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@item:inlistbox how wide a task item should be" msgid "Narrow" msgstr "Узкая" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@item:inlistbox how wide a task item should be" msgid "Medium" msgstr "Средняя" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@item:inlistbox how wide a task item should be" msgid "Wide" msgstr "Широкая" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@label for radio button group, completes sentence: … when panel is low on space etc." msgid "Use multi-column view:" -msgstr "" +msgstr "Многоколоночный вид:" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@label for radio button group, completes sentence: … when panel is low on space etc." msgid "Use multi-row view:" -msgstr "" +msgstr "Многострочный вид:" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@option:radio Never use multi-column view for Task Manager" msgid "Never" -msgstr "" +msgstr "Никогда" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@option:radio completes sentence: Use multi-column/row view" msgid "When panel is low on space and thick enough" -msgstr "" +msgstr "Когда мало места и панель широкая" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@option:radio completes sentence: Use multi-column/row view" msgid "Always when panel is thick enough" -msgstr "" +msgstr "Всегда, если панель достаточно широкая" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@label:spinbox maximum number of columns for tasks" msgid "Maximum columns:" msgstr "Макс. столбцов:" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@label:spinbox maximum number of rows for tasks" msgid "Maximum rows:" msgstr "Макс. строк:" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@label:listbox" msgid "Spacing between icons:" msgstr "Интервал между значками:" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@item:inlistbox Icon spacing" msgid "Small" msgstr "Маленький" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@item:inlistbox Icon spacing" msgid "Normal" msgstr "Обычный" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@item:inlistbox Icon spacing" msgid "Large" msgstr "Большой" #: ../contents/ui/ConfigAppearance.qml -msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" msgid "Automatically set to Large when in Touch mode" -msgstr "" +msgstr "Автоматически «Большой» в сенсорном режиме" #: ../contents/ui/ConfigBehavior.qml msgid "Display:" @@ -287,217 +266,170 @@ msgid "Show icons only" msgstr "Только значки" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@label:listbox how to group tasks" msgid "Group:" msgstr "Группировка:" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox how to group tasks" msgid "Do not group" msgstr "Не группировать" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox how to group tasks" msgid "By program name" msgstr "По имени программы" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@label:listbox completes sentence like: … cycles through tasks" msgid "Clicking grouped task:" -msgstr "" +msgstr "Нажатие на сгруппированную задачу:" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task cycles through tasks' " msgid "Cycles through tasks" -msgstr "" +msgstr "Переключает задачи" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows small window previews' " msgid "Shows small window previews" -msgstr "" +msgstr "Показывает миниатюры окон" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows large window previews' " msgid "Shows large window previews" -msgstr "" +msgstr "Показывает большие превью" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox Completes the sentence 'Clicking grouped task shows textual list' " msgid "Shows textual list" -msgstr "" +msgstr "Показывает текстовый список" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@info displayed as InlineMessage" msgid "The compositor does not support displaying windows side by side, so a textual list will be displayed instead." msgstr "Композитор не поддерживает показ окон рядом, будет показан текстовый список." #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check grouped task" msgid "Combine into single button" msgstr "Объединять в одну кнопку" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check grouped task" msgid "Group only when the Task Manager is full" msgstr "Группировать только при заполнении панели" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@label:listbox sort tasks in grouped task" msgid "Sort:" msgstr "Сортировка:" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Do not sort" msgstr "Не сортировать" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Manually" msgstr "Вручную" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox sort tasks in grouped task" msgid "Alphabetically" msgstr "По алфавиту" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox sort tasks in grouped task" msgid "By desktop" msgstr "По рабочим столам" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox sort tasks in grouped task" msgid "By activity" msgstr "По комнатам" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check configure task sorting" msgid "Keep launchers separate" msgstr "Держать значки запуска отдельно" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check for icons-and-text task manager" msgid "Hide launchers after application startup" msgstr "Скрывать значки запуска после старта приложения" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@label for checkbox Part of a sentence: 'Clicking active task minimizes the task'" msgid "Clicking active task:" msgstr "Нажатие на активную задачу:" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check Part of a sentence: 'Clicking active task minimizes the task'" msgid "Minimizes the task" msgstr "Сворачивает задачу" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@label:listbox completes sentence like: … does nothing" msgid "Middle-clicking any task:" -msgstr "" +msgstr "Средняя кнопка мыши:" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task does nothing'" msgid "Does nothing" msgstr "Ничего не делает" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task closes window or group'" msgid "Closes window or group" msgstr "Закрывает окно или группу" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task opens a new window'" msgid "Opens a new window" msgstr "Открывает новое окно" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" msgid "Minimizes/Restores window or group" msgstr "Сворачивает/Восстанавливает окно или группу" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task toggles grouping'" msgid "Toggles grouping" msgstr "Переключает группировку" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@item:inlistbox Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" msgid "Brings it to the current virtual desktop" msgstr "Переносит на текущий рабочий стол" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@label for checkbox Part of a sentence: 'Mouse wheel cycles through tasks'" msgid "Mouse wheel:" msgstr "Колесо мыши:" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check Part of a sentence: 'Mouse wheel cycles through tasks'" -msgid "Cycles through tasks" -msgstr "Переключает задачи" - -#: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check mouse wheel task cycling" msgid "Skip minimized tasks" msgstr "Пропускать свернутые" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@label for checkbox group, completes sentence like: … from current screen" msgid "Show only tasks:" -msgstr "" +msgstr "Показывать только задачи:" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check completes sentence: show only tasks" msgid "From current screen" msgstr "С текущего экрана" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check completes sentence: show only tasks" msgid "From current desktop" msgstr "С текущего рабочего стола" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check completes sentence: show only tasks" msgid "From current activity" msgstr "Из текущей комнаты" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check completes sentence: show only tasks" msgid "That are minimized" msgstr "Которые свернуты" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@label for checkbox, completes sentence: … unhide if window wants attention" msgid "When panel is hidden:" -msgstr "" +msgstr "Когда панель скрыта:" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check completes sentence: When panel is hidden" msgid "Unhide when a window wants attention" msgstr "Показывать, если окно требует внимания" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@label for radiobutton group completes sentence like: … on the bottom" msgid "New tasks appear:" -msgstr "" +msgstr "Новые задачи появляются:" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check completes sentence: New tasks appear" msgid "On the bottom" msgstr "Снизу" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check completes sentence: New tasks appear" msgid "To the right" msgstr "Справа" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check completes sentence: New tasks appear" msgid "To the left" msgstr "Слева" #: ../contents/ui/ConfigBehavior.qml -msgctxt "@option:check completes sentence: New tasks appear" msgid "On the top" msgstr "Сверху" @@ -912,67 +844,3 @@ msgstr "Также доступно в %1" msgctxt "Which activities a window is currently on" msgid "Available on %1" msgstr "Доступно в %1" - -#~ msgctxt "@label for radio button group" -#~ msgid "Use multi-column view:" -#~ msgstr "Многоколоночный вид:" - -#~ msgctxt "@label for radio button group" -#~ msgid "Use multi-row view:" -#~ msgstr "Многострочный вид:" - -#~ msgctxt "@option:radio Never use multi-column view" -#~ msgid "Never" -#~ msgstr "Никогда" - -#~ msgctxt "@option:radio" -#~ msgid "When panel is low on space and thick enough" -#~ msgstr "Когда мало места и панель широкая" - -#~ msgctxt "@option:radio" -#~ msgid "Always when panel is thick enough" -#~ msgstr "Всегда, если панель достаточно широкая" - -#~ msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" -#~ msgid "Automatically set to Large when in Touch Mode" -#~ msgstr "Автоматически «Большой» в сенсорном режиме" - -#~ msgctxt "@label:listbox" -#~ msgid "Clicking grouped task:" -#~ msgstr "Нажатие на сгруппированную задачу:" - -#~ msgctxt "Completes the sentence 'Clicking grouped task cycles through tasks' " -#~ msgid "Cycles through tasks" -#~ msgstr "Переключает задачи" - -#~ msgctxt "Completes the sentence 'Clicking grouped task shows tooltip window thumbnails' " -#~ msgid "Shows small window previews" -#~ msgstr "Показывает миниатюры окон" - -#~ msgctxt "Completes the sentence 'Clicking grouped task shows large window previews' " -#~ msgid "Shows large window previews" -#~ msgstr "Показывает большие превью" - -#~ msgctxt "Completes the sentence 'Clicking grouped task shows textual list' " -#~ msgid "Shows textual list" -#~ msgstr "Показывает текстовый список" - -#~ msgctxt "@label:listbox" -#~ msgid "Middle-clicking any task:" -#~ msgstr "Средняя кнопка мыши:" - -#~ msgctxt "@label for checkbox group" -#~ msgid "Show only tasks:" -#~ msgstr "Показывать только задачи:" - -#~ msgctxt "@label for checkbox" -#~ msgid "When panel is hidden:" -#~ msgstr "Когда панель скрыта:" - -#~ msgctxt "@label for radiobutton group" -#~ msgid "New tasks appear:" -#~ msgstr "Новые задачи появляются:" - -#~ msgctxt "1 = number of desktop, 2 = desktop name" -#~ msgid "&%1 %2" -#~ msgstr "&%1 %2" From 18236b64c3a9e72a82008fa2af4480161415015a Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Mon, 29 Dec 2025 10:41:37 +0200 Subject: [PATCH 134/141] Fix icons scale --- package/contents/ui/Task.qml | 157 ++++++++++++----------------------- 1 file changed, 55 insertions(+), 102 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 1c5d13fb..cd8fe68b 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -30,24 +30,19 @@ PlasmaCore.ToolTipArea { readonly property bool isCiliora: plasmoid.configuration.indicatorStyle === 1 readonly property bool isDashes: plasmoid.configuration.indicatorStyle === 2 - property string tintColor: Kirigami.ColorUtils.brightnessForColor(Kirigami.Theme.backgroundColor) === Kirigami.ColorUtils.Dark ? - "#ffffff" : "#000000" + property string tintColor: Kirigami.ColorUtils.brightnessForColor(Kirigami.Theme.backgroundColor) === Kirigami.ColorUtils.Dark ? "#ffffff" : "#000000" // To achieve a bottom to top layout, the task manager is rotated by 180 degrees(see main.qml). // This makes the tasks mirrored, so we mirror them again to fix that. rotation: Plasmoid.configuration.reverseMode && Plasmoid.formFactor === PlasmaCore.Types.Vertical ? 180 : 0 - implicitHeight: inPopup ? - LayoutMetrics.preferredHeightInPopup() : Math.max(tasksRoot.height / tasksRoot.plasmoid.configuration.maxStripes, LayoutMetrics.preferredMinHeight()) - implicitWidth: tasksRoot.vertical ? - Math.max(LayoutMetrics.preferredMinWidth(), Math.min(LayoutMetrics.preferredMaxWidth(), tasksRoot.width / tasksRoot.plasmoid.configuration.maxStripes)) : 0 + implicitHeight: inPopup ? LayoutMetrics.preferredHeightInPopup() : Math.max(tasksRoot.height / tasksRoot.plasmoid.configuration.maxStripes, LayoutMetrics.preferredMinHeight()) + implicitWidth: tasksRoot.vertical ? Math.max(LayoutMetrics.preferredMinWidth(), Math.min(LayoutMetrics.preferredMaxWidth(), tasksRoot.width / tasksRoot.plasmoid.configuration.maxStripes)) : 0 Layout.fillWidth: true Layout.fillHeight: !inPopup - Layout.maximumWidth: tasksRoot.vertical ? - -1 : ((model.IsLauncher && !tasks.iconsOnly) ? tasksRoot.height / taskList.rows : LayoutMetrics.preferredMaxWidth()) - Layout.maximumHeight: tasksRoot.vertical ? - LayoutMetrics.preferredMaxHeight() : -1 + Layout.maximumWidth: tasksRoot.vertical ? -1 : ((model.IsLauncher && !tasks.iconsOnly) ? tasksRoot.height / taskList.rows : LayoutMetrics.preferredMaxWidth()) + Layout.maximumHeight: tasksRoot.vertical ? LayoutMetrics.preferredMaxHeight() : -1 required property var model required property int index @@ -56,8 +51,7 @@ PlasmaCore.ToolTipArea { readonly property int pid: model.AppPid readonly property string appName: model.AppName readonly property string appId: model.AppId.replace(/\.desktop/, '') - readonly property bool isIcon: tasksRoot.iconsOnly || - model.IsLauncher + readonly property bool isIcon: tasksRoot.iconsOnly || model.IsLauncher property bool toolTipOpen: false property bool inPopup: false property bool isWindow: model.IsWindow @@ -72,24 +66,19 @@ PlasmaCore.ToolTipArea { property var audioStreams: [] property bool delayAudioStreamIndicator: false property bool completed: false - readonly property - bool audioIndicatorsEnabled: Plasmoid.configuration.indicateAudioStreams + readonly property bool audioIndicatorsEnabled: Plasmoid.configuration.indicateAudioStreams readonly property bool hasAudioStream: audioStreams.length > 0 readonly property bool playingAudio: hasAudioStream && audioStreams.some(item => !item.corked) readonly property bool muted: hasAudioStream && audioStreams.every(item => item.muted) - readonly property bool highlighted: (inPopup && activeFocus) || - (!inPopup && containsMouse) || (task.contextMenu && task.contextMenu.status === PlasmaExtras.Menu.Open) || - (!!tasksRoot.groupDialog && tasksRoot.groupDialog.visualParent === task) + readonly property bool highlighted: (inPopup && activeFocus) || (!inPopup && containsMouse) || (task.contextMenu && task.contextMenu.status === PlasmaExtras.Menu.Open) || (!!tasksRoot.groupDialog && tasksRoot.groupDialog.visualParent === task) property int itemIndex: index // fancytasks active: (Plasmoid.configuration.showToolTips || tasksRoot.toolTipOpenedByClick === task) && !inPopup && !tasksRoot.groupDialog - interactive: model.IsWindow || - mainItem.playerData + interactive: model.IsWindow || mainItem.playerData location: Plasmoid.location - mainItem: model.IsWindow ? - openWindowToolTipDelegate : pinnedAppToolTipDelegate + mainItem: model.IsWindow ? openWindowToolTipDelegate : pinnedAppToolTipDelegate onXChanged: { if (!completed) { @@ -307,8 +296,7 @@ ${smartLauncherDescription}`; } function modelIndex(): /*QModelIndex*/ var { - return inPopup ? - tasksModel.makeModelIndex(groupDialog.visualParent.index, index) : tasksModel.makeModelIndex(index); + return inPopup ? tasksModel.makeModelIndex(groupDialog.visualParent.index, index) : tasksModel.makeModelIndex(index); } function showContextMenu(args: var): void { @@ -443,17 +431,14 @@ ${smartLauncherDescription}`; id: colorOverride anchors.fill: frame source: frame - color: plasmoid.configuration.buttonColorizeDominant ? - frame.indicatorColor : plasmoid.configuration.buttonColorizeCustom - visible: plasmoid.configuration.buttonColorize ? - true : false + color: plasmoid.configuration.buttonColorizeDominant ? frame.indicatorColor : plasmoid.configuration.buttonColorizeCustom + visible: plasmoid.configuration.buttonColorize ? true : false } Indicators { id: indicator taskCount: task.childCount - visible: plasmoid.configuration.indicatorsEnabled ? - true : false + visible: plasmoid.configuration.indicatorsEnabled ? true : false flow: Flow.LeftToRight spacing: Kirigami.Units.smallSpacing clip: true @@ -462,8 +447,7 @@ ${smartLauncherDescription}`; TapHandler { id: menuTapHandler acceptedButtons: Qt.LeftButton - acceptedDevices: PointerDevice.TouchScreen | - PointerDevice.Stylus + acceptedDevices: PointerDevice.TouchScreen | PointerDevice.Stylus gesturePolicy: TapHandler.ReleaseWithinBounds onLongPressed: { // When we're a launcher, there's no window controls, so we can show all @@ -480,8 +464,7 @@ ${smartLauncherDescription}`; TapHandler { acceptedButtons: Qt.RightButton - acceptedDevices: PointerDevice.Mouse | - PointerDevice.TouchPad | PointerDevice.Stylus + acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus gesturePolicy: TapHandler.WithinBounds // Release grab when menu appears onPressedChanged: if (pressed) contextMenuTimer.start() @@ -507,8 +490,7 @@ ${smartLauncherDescription}`; } TapHandler { - acceptedButtons: Qt.MiddleButton | - Qt.BackButton | Qt.ForwardButton + acceptedButtons: Qt.MiddleButton | Qt.BackButton | Qt.ForwardButton onTapped: (eventPoint, button) => { if (button === Qt.MiddleButton) { if (Plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.NewInstance) { @@ -553,24 +535,17 @@ ${smartLauncherDescription}`; anchors { fill: parent - topMargin: (!tasksRoot.vertical && taskList.rows > 1) ? - LayoutMetrics.iconMargin : 0 - bottomMargin: (!tasksRoot.vertical && taskList.rows > 1) ? - LayoutMetrics.iconMargin : 0 - leftMargin: ((inPopup || tasksRoot.vertical) && taskList.columns > 1) ? - LayoutMetrics.iconMargin : 0 - rightMargin: ((inPopup || tasksRoot.vertical) && taskList.columns > 1) ? - LayoutMetrics.iconMargin : 0 + topMargin: (!tasksRoot.vertical && taskList.rows > 1) ? LayoutMetrics.iconMargin : 0 + bottomMargin: (!tasksRoot.vertical && taskList.rows > 1) ? LayoutMetrics.iconMargin : 0 + leftMargin: ((inPopup || tasksRoot.vertical) && taskList.columns > 1) ? LayoutMetrics.iconMargin : 0 + rightMargin: ((inPopup || tasksRoot.vertical) && taskList.columns > 1) ? LayoutMetrics.iconMargin : 0 } - imagePath: plasmoid.configuration.disableButtonSvg ? - "" : "widgets/tasks" - enabledBorders: plasmoid.configuration.useBorders ? 1 | 2 | 4 | - 8 : 0 + imagePath: plasmoid.configuration.disableButtonSvg ? "" : "widgets/tasks" + enabledBorders: plasmoid.configuration.useBorders ? 1 | 2 | 4 | 8 : 0 property bool isHovered: task.highlighted && Plasmoid.configuration.taskHoverEffect property string basePrefix: "normal" - prefix: isHovered ? - TaskTools.taskPrefixHovered(basePrefix, Plasmoid.location) : TaskTools.taskPrefix(basePrefix, Plasmoid.location) + prefix: isHovered ? TaskTools.taskPrefixHovered(basePrefix, Plasmoid.location) : TaskTools.taskPrefix(basePrefix, Plasmoid.location) // Avoid repositioning delegate item after dragFinished DragHandler { @@ -637,10 +612,8 @@ ${smartLauncherDescription}`; topMargin: adjustMargin(false, parent.height, taskFrame.margins.top) } - width: task.inPopup ? - Math.max(Kirigami.Units.iconSizes.sizeForLabels, Kirigami.Units.iconSizes.medium) : Math.min(task.parent?.minimumWidth ?? 0, task.height) - height: task.inPopup ? - width : (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - adjustMargin(false, parent.height, taskFrame.margins.bottom)) + width: task.inPopup ? Math.max(Kirigami.Units.iconSizes.sizeForLabels, Kirigami.Units.iconSizes.medium) : Math.min(task.parent?.minimumWidth ?? 0, task.height) + height: task.inPopup ? width : (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - adjustMargin(false, parent.height, taskFrame.margins.bottom)) asynchronous: true active: height >= Kirigami.Units.iconSizes.small && task.smartLauncherItem && task.smartLauncherItem.countVisible @@ -661,14 +634,15 @@ ${smartLauncherDescription}`; Kirigami.Icon { id: icon - property int growSize: active ? - plasmoid.configuration.iconZoomFactor : 0 - + property int growSize: active ? plasmoid.configuration.iconZoomFactor : 0 + + property bool sizeOverride: plasmoid.configuration.iconSizeOverride + property int fixedSize: plasmoid.configuration.iconSizePx property real iconScale: plasmoid.configuration.iconScale / 100 - - width: (parent.width * iconScale) + growSize - height: (parent.height * iconScale) + growSize - + + width: (sizeOverride ? fixedSize : (parent.width * iconScale)) + growSize + height: (sizeOverride ? fixedSize : (parent.height * iconScale)) + growSize + anchors.centerIn: parent Behavior on growSize { @@ -723,18 +697,15 @@ ${smartLauncherDescription}`; fill: parent leftMargin: taskFrame.margins.left + iconBox.width + LayoutMetrics.labelMargin topMargin: taskFrame.margins.top - rightMargin: taskFrame.margins.right + (audioStreamIcon !== null && audioStreamIcon.visible ? - (audioStreamIcon.width + LayoutMetrics.labelMargin) : 0) + rightMargin: taskFrame.margins.right + (audioStreamIcon !== null && audioStreamIcon.visible ? (audioStreamIcon.width + LayoutMetrics.labelMargin) : 0) bottomMargin: taskFrame.margins.bottom } - wrapMode: (maximumLineCount === 1) ? - Text.NoWrap : Text.Wrap + wrapMode: (maximumLineCount === 1) ? Text.NoWrap : Text.Wrap elide: Text.ElideRight textFormat: Text.PlainText verticalAlignment: Text.AlignVCenter - maximumLineCount: Plasmoid.configuration.maxTextLines || - undefined + maximumLineCount: Plasmoid.configuration.maxTextLines || undefined Accessible.ignored: true @@ -766,14 +737,12 @@ ${smartLauncherDescription}`; }, State { name: "attention" - when: model.IsDemandingAttention === true || - (task.smartLauncherItem && task.smartLauncherItem.urgent) + when: model.IsDemandingAttention === true || (task.smartLauncherItem && task.smartLauncherItem.urgent) PropertyChanges { target: frame basePrefix: "attention" - visible: (plasmoid.configuration.buttonColorize && !frame.isHovered) || - !plasmoid.configuration.buttonColorize + visible: (plasmoid.configuration.buttonColorize && !frame.isHovered) || !plasmoid.configuration.buttonColorize } PropertyChanges { target: colorOverride @@ -787,18 +756,15 @@ ${smartLauncherDescription}`; PropertyChanges { target: frame basePrefix: "minimized" - visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? - false : true + visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? false : true } PropertyChanges { target: colorOverride - visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? - true : false + visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? true : false } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? - false : true + visible: plasmoid.configuration.disableInactiveIndicators ? false : true } }, State { @@ -808,18 +774,15 @@ ${smartLauncherDescription}`; PropertyChanges { target: frame basePrefix: "minimized" - visible: plasmoid.configuration.disableButtonInactiveSvg ? - false : true + visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true } PropertyChanges { target: colorOverride - visible: plasmoid.configuration.disableButtonInactiveSvg ? - false : true + visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? - false : true + visible: plasmoid.configuration.disableInactiveIndicators ? false : true } }, State { @@ -832,13 +795,11 @@ ${smartLauncherDescription}`; } PropertyChanges { target: colorOverride - visible: plasmoid.configuration.buttonColorize ? - true : false + visible: plasmoid.configuration.buttonColorize ? true : false } PropertyChanges { target: indicator - visible: plasmoid.configuration.indicatorsEnabled ? - true : false + visible: plasmoid.configuration.indicatorsEnabled ? true : false } }, State { @@ -846,18 +807,15 @@ ${smartLauncherDescription}`; when: model.IsActive === false && !frame.isHovered && !plasmoid.configuration.disableButtonInactiveSvg PropertyChanges { target: colorOverride - visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? - true : false + visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? true : false } PropertyChanges { target: frame - visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? - false : true + visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? false : true } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? - false : true + visible: plasmoid.configuration.disableInactiveIndicators ? false : true } }, State { @@ -865,18 +823,15 @@ ${smartLauncherDescription}`; when: (model.IsActive === false && !frame.isHovered) && plasmoid.configuration.disableButtonInactiveSvg PropertyChanges { target: colorOverride - visible: plasmoid.configuration.disableButtonInactiveSvg ? - false : true + visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true } PropertyChanges { target: frame - visible: plasmoid.configuration.disableButtonInactiveSvg ? - false : true + visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? - false : true + visible: plasmoid.configuration.disableInactiveIndicators ? false : true } }, State { @@ -888,13 +843,11 @@ ${smartLauncherDescription}`; } PropertyChanges { target: frame - visible: plasmoid.configuration.buttonColorize ? - false : true + visible: plasmoid.configuration.buttonColorize ? false : true } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? - false : true + visible: plasmoid.configuration.disableInactiveIndicators ? false : true } } ] From 739aeef35e465857c2d04339238dab5c000258e2 Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Mon, 29 Dec 2025 14:25:46 +0200 Subject: [PATCH 135/141] Change windows thumbs --- package/contents/ui/Task.qml | 496 +++++++++++++++++++++++++++-------- 1 file changed, 392 insertions(+), 104 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index cd8fe68b..84da85db 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -30,19 +30,22 @@ PlasmaCore.ToolTipArea { readonly property bool isCiliora: plasmoid.configuration.indicatorStyle === 1 readonly property bool isDashes: plasmoid.configuration.indicatorStyle === 2 - property string tintColor: Kirigami.ColorUtils.brightnessForColor(Kirigami.Theme.backgroundColor) === Kirigami.ColorUtils.Dark ? "#ffffff" : "#000000" + property string tintColor: Kirigami.ColorUtils.brightnessForColor(Kirigami.Theme.backgroundColor) === Kirigami.ColorUtils.Dark ? + "#ffffff" : "#000000" - // To achieve a bottom to top layout, the task manager is rotated by 180 degrees(see main.qml). - // This makes the tasks mirrored, so we mirror them again to fix that. rotation: Plasmoid.configuration.reverseMode && Plasmoid.formFactor === PlasmaCore.Types.Vertical ? 180 : 0 - implicitHeight: inPopup ? LayoutMetrics.preferredHeightInPopup() : Math.max(tasksRoot.height / tasksRoot.plasmoid.configuration.maxStripes, LayoutMetrics.preferredMinHeight()) - implicitWidth: tasksRoot.vertical ? Math.max(LayoutMetrics.preferredMinWidth(), Math.min(LayoutMetrics.preferredMaxWidth(), tasksRoot.width / tasksRoot.plasmoid.configuration.maxStripes)) : 0 + implicitHeight: inPopup ? + LayoutMetrics.preferredHeightInPopup() : Math.max(tasksRoot.height / tasksRoot.plasmoid.configuration.maxStripes, LayoutMetrics.preferredMinHeight()) + implicitWidth: tasksRoot.vertical ? + Math.max(LayoutMetrics.preferredMinWidth(), Math.min(LayoutMetrics.preferredMaxWidth(), tasksRoot.width / tasksRoot.plasmoid.configuration.maxStripes)) : 0 Layout.fillWidth: true Layout.fillHeight: !inPopup - Layout.maximumWidth: tasksRoot.vertical ? -1 : ((model.IsLauncher && !tasks.iconsOnly) ? tasksRoot.height / taskList.rows : LayoutMetrics.preferredMaxWidth()) - Layout.maximumHeight: tasksRoot.vertical ? LayoutMetrics.preferredMaxHeight() : -1 + Layout.maximumWidth: tasksRoot.vertical ? + -1 : ((model.IsLauncher && !tasks.iconsOnly) ? tasksRoot.height / taskList.rows : LayoutMetrics.preferredMaxWidth()) + Layout.maximumHeight: tasksRoot.vertical ? + LayoutMetrics.preferredMaxHeight() : -1 required property var model required property int index @@ -51,7 +54,8 @@ PlasmaCore.ToolTipArea { readonly property int pid: model.AppPid readonly property string appName: model.AppName readonly property string appId: model.AppId.replace(/\.desktop/, '') - readonly property bool isIcon: tasksRoot.iconsOnly || model.IsLauncher + readonly property bool isIcon: tasksRoot.iconsOnly || + model.IsLauncher property bool toolTipOpen: false property bool inPopup: false property bool isWindow: model.IsWindow @@ -66,19 +70,250 @@ PlasmaCore.ToolTipArea { property var audioStreams: [] property bool delayAudioStreamIndicator: false property bool completed: false - readonly property bool audioIndicatorsEnabled: Plasmoid.configuration.indicateAudioStreams + readonly property + bool audioIndicatorsEnabled: Plasmoid.configuration.indicateAudioStreams readonly property bool hasAudioStream: audioStreams.length > 0 readonly property bool playingAudio: hasAudioStream && audioStreams.some(item => !item.corked) readonly property bool muted: hasAudioStream && audioStreams.every(item => item.muted) - readonly property bool highlighted: (inPopup && activeFocus) || (!inPopup && containsMouse) || (task.contextMenu && task.contextMenu.status === PlasmaExtras.Menu.Open) || (!!tasksRoot.groupDialog && tasksRoot.groupDialog.visualParent === task) + readonly property bool highlighted: (inPopup && activeFocus) || + (!inPopup && containsMouse) || (task.contextMenu && task.contextMenu.status === PlasmaExtras.Menu.Open) || + (!!tasksRoot.groupDialog && tasksRoot.groupDialog.visualParent === task) property int itemIndex: index // fancytasks + // --- MODIFICATION START --- + + // Disable standard tooltip (mainItem: null) but keep active for events active: (Plasmoid.configuration.showToolTips || tasksRoot.toolTipOpenedByClick === task) && !inPopup && !tasksRoot.groupDialog - interactive: model.IsWindow || mainItem.playerData + mainItem: null location: Plasmoid.location - mainItem: model.IsWindow ? openWindowToolTipDelegate : pinnedAppToolTipDelegate + + property alias tooltipContent: delegateLoader.item + + // Check interaction capability (windows always interactive, others check playerData) + interactive: model.IsWindow || (tooltipContent && tooltipContent.playerData) + + // Custom Tooltip Dialog + PlasmaCore.Dialog { + id: tooltipDialog + visualParent: task + location: Plasmoid.location + type: PlasmaCore.Dialog.Tooltip + + // We draw our own background to handle the gap + backgroundHints: PlasmaCore.Types.NoBackground + flags: Qt.ToolTip | Qt.FramelessWindowHint | Qt.WA_TranslucentBackground + + visible: false + + mainItem: Item { + id: contentWrapper + + // Interaction handler for the whole area (including the empty gap) + HoverHandler { id: wrapperHover } + + // Gap configuration + readonly property int gapSize: Kirigami.Units.gridUnit / 2 + readonly property int loc: Plasmoid.location + + // Calculate size: Background Frame + Gap + implicitWidth: (loc === PlasmaCore.Types.LeftEdge || loc === PlasmaCore.Types.RightEdge) ? (bgFrame.width + gapSize) : bgFrame.width + implicitHeight: (loc === PlasmaCore.Types.TopEdge || loc === PlasmaCore.Types.BottomEdge) ? (bgFrame.height + gapSize) : bgFrame.height + + // The visual bubble + KSvg.FrameSvgItem { + id: bgFrame + imagePath: "widgets/tooltip" + + // Size depends on the loaded content + margins. + // Ensure at least some size to avoid visual glitches. + width: Math.max(delegateLoader.item ? delegateLoader.item.implicitWidth : 0, Kirigami.Units.gridUnit * 2) + margins.left + margins.right + height: Math.max(delegateLoader.item ? delegateLoader.item.implicitHeight : 0, Kirigami.Units.gridUnit) + margins.top + margins.bottom + + // Position logic: push away from the panel + anchors.top: (contentWrapper.loc === PlasmaCore.Types.BottomEdge) ? parent.top : undefined + anchors.bottom: (contentWrapper.loc === PlasmaCore.Types.TopEdge) ? parent.bottom : undefined + anchors.left: (contentWrapper.loc === PlasmaCore.Types.RightEdge) ? parent.left : undefined + anchors.right: (contentWrapper.loc === PlasmaCore.Types.LeftEdge) ? parent.right : undefined + + // Center on the other axis + anchors.horizontalCenter: (contentWrapper.loc === PlasmaCore.Types.TopEdge || contentWrapper.loc === PlasmaCore.Types.BottomEdge) ? parent.horizontalCenter : undefined + anchors.verticalCenter: (contentWrapper.loc === PlasmaCore.Types.LeftEdge || contentWrapper.loc === PlasmaCore.Types.RightEdge) ? parent.verticalCenter : undefined + + // Loader switches between complex window delegate and simple text delegate + Loader { + id: delegateLoader + + // FIXED: Removed anchors.fill to avoid constraining content size. + // Instead, anchor only top/left and let content define the size. + anchors.left: parent.left + anchors.top: parent.top + anchors.leftMargin: bgFrame.margins.left + anchors.topMargin: bgFrame.margins.top + + // Select component based on task type + sourceComponent: model.IsWindow ? windowDelegate : pinnedAppDelegate + asynchronous: false + + onLoaded: { + // Force update when loaded to ensure data is populated immediately + if (task.toolTipOpen) { + task.updateMainItemBindings() + } + } + } + } + } + } + + // Component for Windows (complex delegate with previews) + Component { + id: windowDelegate + // We load the external file to avoid cyclic dependency issues directly in Task.qml + Loader { + source: "ToolTipDelegate.qml" + + // Re-expose properties required by updateMainItemBindings + property var parentTask + property var rootIndex + property string appName + property int pidParent + property var windows + property bool isGroup + property var icon + property url launcherUrl + property bool isLauncher + property bool isMinimized + property string display + property string genericName + property var virtualDesktops + property bool isOnAllVirtualDesktops + property list activities + property bool smartLauncherCountVisible + property int smartLauncherCount + property bool blockingUpdates + + // Expose playerData from inner item up to here, so Task can see it for 'interactive' check + readonly property var playerData: item ? item.playerData : null + + // Forward these properties to the inner ToolTipDelegate when it loads + onLoaded: { + item.parentTask = Qt.binding(() => parentTask) + item.rootIndex = Qt.binding(() => rootIndex) + item.appName = Qt.binding(() => appName) + item.pidParent = Qt.binding(() => pidParent) + item.windows = Qt.binding(() => windows) + item.isGroup = Qt.binding(() => isGroup) + item.icon = Qt.binding(() => icon) + item.launcherUrl = Qt.binding(() => launcherUrl) + item.isLauncher = Qt.binding(() => isLauncher) + item.isMinimized = Qt.binding(() => isMinimized) + item.display = Qt.binding(() => display) + item.genericName = Qt.binding(() => genericName) + item.virtualDesktops = Qt.binding(() => virtualDesktops) + item.isOnAllVirtualDesktops = Qt.binding(() => isOnAllVirtualDesktops) + item.activities = Qt.binding(() => activities) + item.smartLauncherCountVisible = Qt.binding(() => smartLauncherCountVisible) + item.smartLauncherCount = Qt.binding(() => smartLauncherCount) + item.blockingUpdates = Qt.binding(() => blockingUpdates) + } + } + } + + // Component for Pinned Apps (Simple text) + Component { + id: pinnedAppDelegate + Item { + // These properties are set by updateMainItemBindings + property var parentTask + property var rootIndex + property string appName + property int pidParent + property var windows + property bool isGroup + property var icon + property url launcherUrl + property bool isLauncher + property bool isMinimized + property string display + property string genericName + property var virtualDesktops + property bool isOnAllVirtualDesktops + property list activities + property bool smartLauncherCountVisible + property int smartLauncherCount + property bool blockingUpdates + + // Dummy playerData for interactive check (always null for pinned) + property var playerData: null + + implicitWidth: label.implicitWidth + implicitHeight: label.implicitHeight + + PlasmaComponents3.Label { + id: label + text: parent.display + anchors.centerIn: parent + } + } + } + + // Timers for interaction + Timer { + id: closeTimer + interval: 250 // Time to cross the gap + onTriggered: { + if (!task.containsMouse && !wrapperHover.hovered) { + tooltipDialog.visible = false; + task.toolTipOpen = false; + tasksRoot.toolTipOpenedByClick = null; + } + } + } + + Timer { + id: openTimer + interval: 500 + onTriggered: { + if (task.containsMouse) { + tooltipDialog.visible = true; + task.toolTipOpen = true; + task.updateMainItemBindings(); + tasksRoot.toolTipAreaItem = task; + } + } + } + + Connections { + target: wrapperHover + function onHoveredChanged() { + if (wrapperHover.hovered) { + closeTimer.stop(); + } else { + if (!task.containsMouse) closeTimer.start(); + } + } + } + + onContainsMouseChanged: { + if (containsMouse) { + task.forceActiveFocus(Qt.MouseFocusReason); + closeTimer.stop(); + + if (tooltipDialog.visible) { + task.updateMainItemBindings(); + task.toolTipOpen = true; + tasksRoot.toolTipAreaItem = task; + } else { + openTimer.restart(); + } + } else { + openTimer.stop(); + closeTimer.start(); + } + } + // --- MODIFICATION END --- onXChanged: { if (!completed) { @@ -132,7 +367,8 @@ PlasmaCore.ToolTipArea { NumberAnimation { target: translateTransform properties: "y" - from: moveAnim.y + + from: moveAnim.y to: 0 easing.type: Easing.OutQuad duration: Kirigami.Units.longDuration @@ -141,6 +377,7 @@ PlasmaCore.ToolTipArea { } transform: Translate { id: translateTransform + } Accessible.name: model.display @@ -167,48 +404,31 @@ PlasmaCore.ToolTipArea { { if (Plasmoid.configuration.showToolTips) { return `${i18nc("@info:usagetip %1 task name", "Show Task tooltip for %1", model.display)}; -${smartLauncherDescription}`; + ${smartLauncherDescription}`; } // fallthrough } case 2: { if (effectWatcher.registered) { - return `${i18nc("@info:usagetip %1 task name", "Show windows side by side for %1", model.display)}; -${smartLauncherDescription}`; + + return `${i18nc("@info:usagetip %1 task name", "Show windows side by side for %1", model.display)}; + ${smartLauncherDescription}`; } // fallthrough } default: return `${i18nc("@info:usagetip %1 task name", "Open textual list of windows for %1", model.display)}; -${smartLauncherDescription}`; + ${smartLauncherDescription}`; } } return `${i18n("Activate %1", model.display)}; -${smartLauncherDescription}`; + ${smartLauncherDescription}`; } Accessible.role: Accessible.Button Accessible.onPressAction: leftTapHandler.leftClick() - onToolTipVisibleChanged: toolTipVisible => { - task.toolTipOpen = toolTipVisible; - if (!toolTipVisible) { - tasksRoot.toolTipOpenedByClick = null; - } else { - tasksRoot.toolTipAreaItem = task; - } - } - - onContainsMouseChanged: { - if (containsMouse) { - task.forceActiveFocus(Qt.MouseFocusReason); - task.updateMainItemBindings(); - } else { - tasksRoot.toolTipOpenedByClick = null; - } - } - onHighlightedChanged: { // ensure it doesn't get stuck with a window highlighted tasksRoot.cancelHighlightWindows(); @@ -239,7 +459,8 @@ ${smartLauncherDescription}`; } onIndexChanged: { - hideToolTip(); + tooltipDialog.visible = false; + if (!inPopup && !tasksRoot.vertical && !Plasmoid.configuration.separateLaunchers) { tasksRoot.requestLayout(); } @@ -282,7 +503,8 @@ ${smartLauncherDescription}`; Keys.onDownPressed: event => Keys.rightPressed(event) Keys.onLeftPressed: event => { if (!inPopup && (event.modifiers & Qt.ControlModifier) && (event.modifiers & Qt.ShiftModifier)) { - tasksModel.move(task.index, task.index - 1); + tasksModel.move(task.index, task.index + - 1); } else { event.accepted = false; } @@ -296,11 +518,14 @@ ${smartLauncherDescription}`; } function modelIndex(): /*QModelIndex*/ var { - return inPopup ? tasksModel.makeModelIndex(groupDialog.visualParent.index, index) : tasksModel.makeModelIndex(index); + return inPopup ? + tasksModel.makeModelIndex(groupDialog.visualParent.index, index) : tasksModel.makeModelIndex(index); } function showContextMenu(args: var): void { task.hideImmediately(); + tooltipDialog.visible = false; + contextMenu = tasksRoot.createContextMenu(task, modelIndex(), args); contextMenu.show(); } @@ -350,36 +575,38 @@ ${smartLauncherDescription}`; } } - // Will also be called in activateTaskAtIndex(index) + // UPDATED: Bindings for delegateLoader.item function updateMainItemBindings(): void { - if ((mainItem.parentTask === this && mainItem.rootIndex.row === index) || (tasksRoot.toolTipOpenedByClick === null && !active) || (tasksRoot.toolTipOpenedByClick !== null && tasksRoot.toolTipOpenedByClick !== this)) { + var item = delegateLoader.item; + if (!item) return; + + if ((item.parentTask === this && item.rootIndex.row === index) || (tasksRoot.toolTipOpenedByClick === null && !active) || (tasksRoot.toolTipOpenedByClick !== null && tasksRoot.toolTipOpenedByClick !== this)) { return; } - mainItem.blockingUpdates = (mainItem.isGroup !== model.IsGroupParent); - // BUG 464597 Force unload the previous component - - mainItem.parentTask = this; - mainItem.rootIndex = tasksModel.makeModelIndex(index, -1); - - mainItem.appName = Qt.binding(() => model.AppName); - mainItem.pidParent = Qt.binding(() => model.AppPid); - mainItem.windows = Qt.binding(() => model.WinIdList); - mainItem.isGroup = Qt.binding(() => model.IsGroupParent); - mainItem.icon = Qt.binding(() => model.decoration); - mainItem.launcherUrl = Qt.binding(() => model.LauncherUrlWithoutIcon); - mainItem.isLauncher = Qt.binding(() => model.IsLauncher); - mainItem.isMinimized = Qt.binding(() => model.IsMinimized); - mainItem.display = Qt.binding(() => model.display); - mainItem.genericName = Qt.binding(() => model.GenericName); - mainItem.virtualDesktops = Qt.binding(() => model.VirtualDesktops); - mainItem.isOnAllVirtualDesktops = Qt.binding(() => model.IsOnAllVirtualDesktops); - mainItem.activities = Qt.binding(() => model.Activities); - - mainItem.smartLauncherCountVisible = Qt.binding(() => smartLauncherItem?.countVisible ?? false); - mainItem.smartLauncherCount = Qt.binding(() => mainItem.smartLauncherCountVisible ? smartLauncherItem.count : 0); - - mainItem.blockingUpdates = false; + item.blockingUpdates = (item.isGroup !== model.IsGroupParent); + + item.parentTask = this; + item.rootIndex = tasksModel.makeModelIndex(index, -1); + + item.appName = Qt.binding(() => model.AppName); + item.pidParent = Qt.binding(() => model.AppPid); + item.windows = Qt.binding(() => model.WinIdList); + item.isGroup = Qt.binding(() => model.IsGroupParent); + item.icon = Qt.binding(() => model.decoration); + item.launcherUrl = Qt.binding(() => model.LauncherUrlWithoutIcon); + item.isLauncher = Qt.binding(() => model.IsLauncher); + item.isMinimized = Qt.binding(() => model.IsMinimized); + item.display = Qt.binding(() => model.display); + item.genericName = Qt.binding(() => model.GenericName); + item.virtualDesktops = Qt.binding(() => model.VirtualDesktops); + item.isOnAllVirtualDesktops = Qt.binding(() => model.IsOnAllVirtualDesktops); + item.activities = Qt.binding(() => model.Activities); + + item.smartLauncherCountVisible = Qt.binding(() => smartLauncherItem?.countVisible ?? false); + item.smartLauncherCount = Qt.binding(() => item.smartLauncherCountVisible ? smartLauncherItem.count : 0); + + item.blockingUpdates = false; tasksRoot.toolTipAreaItem = this; } @@ -431,14 +658,17 @@ ${smartLauncherDescription}`; id: colorOverride anchors.fill: frame source: frame - color: plasmoid.configuration.buttonColorizeDominant ? frame.indicatorColor : plasmoid.configuration.buttonColorizeCustom - visible: plasmoid.configuration.buttonColorize ? true : false + color: plasmoid.configuration.buttonColorizeDominant ? + frame.indicatorColor : plasmoid.configuration.buttonColorizeCustom + visible: plasmoid.configuration.buttonColorize ? + true : false } Indicators { id: indicator taskCount: task.childCount - visible: plasmoid.configuration.indicatorsEnabled ? true : false + visible: plasmoid.configuration.indicatorsEnabled ? + true : false flow: Flow.LeftToRight spacing: Kirigami.Units.smallSpacing clip: true @@ -447,7 +677,8 @@ ${smartLauncherDescription}`; TapHandler { id: menuTapHandler acceptedButtons: Qt.LeftButton - acceptedDevices: PointerDevice.TouchScreen | PointerDevice.Stylus + acceptedDevices: PointerDevice.TouchScreen | + PointerDevice.Stylus gesturePolicy: TapHandler.ReleaseWithinBounds onLongPressed: { // When we're a launcher, there's no window controls, so we can show all @@ -464,7 +695,8 @@ ${smartLauncherDescription}`; TapHandler { acceptedButtons: Qt.RightButton - acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus + acceptedDevices: PointerDevice.Mouse | + PointerDevice.TouchPad | PointerDevice.Stylus gesturePolicy: TapHandler.WithinBounds // Release grab when menu appears onPressedChanged: if (pressed) contextMenuTimer.start() @@ -478,19 +710,21 @@ ${smartLauncherDescription}`; TapHandler { id: leftTapHandler + acceptedButtons: Qt.LeftButton onTapped: (eventPoint, button) => leftClick() function leftClick(): void { if (Plasmoid.configuration.showToolTips && task.active) { - hideToolTip(); + tooltipDialog.visible = false; } TaskTools.activateTask(modelIndex(), model, point.modifiers, task, Plasmoid, tasksRoot, effectWatcher.registered); } } TapHandler { - acceptedButtons: Qt.MiddleButton | Qt.BackButton | Qt.ForwardButton + acceptedButtons: Qt.MiddleButton | + Qt.BackButton | Qt.ForwardButton onTapped: (eventPoint, button) => { if (button === Qt.MiddleButton) { if (Plasmoid.configuration.middleClickAction === TaskManagerApplet.Backend.NewInstance) { @@ -533,19 +767,27 @@ ${smartLauncherDescription}`; property color indicatorColor: Kirigami.ColorUtils.tintWithAlpha(frame.dominantColor, tintColor, .38) anchors { + fill: parent - topMargin: (!tasksRoot.vertical && taskList.rows > 1) ? LayoutMetrics.iconMargin : 0 - bottomMargin: (!tasksRoot.vertical && taskList.rows > 1) ? LayoutMetrics.iconMargin : 0 - leftMargin: ((inPopup || tasksRoot.vertical) && taskList.columns > 1) ? LayoutMetrics.iconMargin : 0 - rightMargin: ((inPopup || tasksRoot.vertical) && taskList.columns > 1) ? LayoutMetrics.iconMargin : 0 + topMargin: (!tasksRoot.vertical && taskList.rows > 1) ? + LayoutMetrics.iconMargin : 0 + bottomMargin: (!tasksRoot.vertical && taskList.rows > 1) ? + LayoutMetrics.iconMargin : 0 + leftMargin: ((inPopup || tasksRoot.vertical) && taskList.columns > 1) ? + LayoutMetrics.iconMargin : 0 + rightMargin: ((inPopup || tasksRoot.vertical) && taskList.columns > 1) ? + LayoutMetrics.iconMargin : 0 } - imagePath: plasmoid.configuration.disableButtonSvg ? "" : "widgets/tasks" - enabledBorders: plasmoid.configuration.useBorders ? 1 | 2 | 4 | 8 : 0 + imagePath: plasmoid.configuration.disableButtonSvg ? + "" : "widgets/tasks" + enabledBorders: plasmoid.configuration.useBorders ? 1 | 2 | 4 | + 8 : 0 property bool isHovered: task.highlighted && Plasmoid.configuration.taskHoverEffect property string basePrefix: "normal" - prefix: isHovered ? TaskTools.taskPrefixHovered(basePrefix, Plasmoid.location) : TaskTools.taskPrefix(basePrefix, Plasmoid.location) + prefix: isHovered ? + TaskTools.taskPrefixHovered(basePrefix, Plasmoid.location) : TaskTools.taskPrefix(basePrefix, Plasmoid.location) // Avoid repositioning delegate item after dragFinished DragHandler { @@ -554,6 +796,7 @@ ${smartLauncherDescription}`; function setRequestedInhibitDnd(value: bool): void { // This is modifying the value in the panel containment that + // inhibits accepting drag and drop, so that we don't accidentally // drop the task on this panel. let item = this; @@ -568,17 +811,21 @@ ${smartLauncherDescription}`; onActiveChanged: { if (active) { icon.grabToImage(result => { + if (!dragHandler.active) { // BUG 466675 grabToImage is async, so avoid updating dragSource when active is false return; + } setRequestedInhibitDnd(true); tasksRoot.dragSource = task; dragHelper.Drag.imageSource = result.url; + dragHelper.Drag.mimeData = { "text/x-orgkdeplasmataskmanager_taskurl": backend.tryDecodeApplicationsUrl(model.LauncherUrlWithoutIcon).toString(), [model.MimeType]: model.MimeData, + "application/x-orgkdeplasmataskmanager_taskbuttonitem": model.MimeData }; dragHelper.Drag.active = dragHandler.active; @@ -603,6 +850,7 @@ ${smartLauncherDescription}`; } Loader { + id: iconBox anchors { @@ -612,8 +860,10 @@ ${smartLauncherDescription}`; topMargin: adjustMargin(false, parent.height, taskFrame.margins.top) } - width: task.inPopup ? Math.max(Kirigami.Units.iconSizes.sizeForLabels, Kirigami.Units.iconSizes.medium) : Math.min(task.parent?.minimumWidth ?? 0, task.height) - height: task.inPopup ? width : (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - adjustMargin(false, parent.height, taskFrame.margins.bottom)) + width: task.inPopup ? + Math.max(Kirigami.Units.iconSizes.sizeForLabels, Kirigami.Units.iconSizes.medium) : Math.min(task.parent?.minimumWidth ?? 0, task.height) + height: task.inPopup ? + width : (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - adjustMargin(false, parent.height, taskFrame.margins.bottom)) asynchronous: true active: height >= Kirigami.Units.iconSizes.small && task.smartLauncherItem && task.smartLauncherItem.countVisible @@ -634,7 +884,8 @@ ${smartLauncherDescription}`; Kirigami.Icon { id: icon - property int growSize: active ? plasmoid.configuration.iconZoomFactor : 0 + property int growSize: active ? + plasmoid.configuration.iconZoomFactor : 0 property bool sizeOverride: plasmoid.configuration.iconSizeOverride property int fixedSize: plasmoid.configuration.iconSizePx @@ -643,6 +894,7 @@ ${smartLauncherDescription}`; width: (sizeOverride ? fixedSize : (parent.width * iconScale)) + growSize height: (sizeOverride ? fixedSize : (parent.height * iconScale)) + growSize + anchors.centerIn: parent Behavior on growSize { @@ -650,6 +902,7 @@ ${smartLauncherDescription}`; duration: plasmoid.configuration.iconZoomDuration easing.type: Easing.InOutQuad } + } roundToIconSize: growSize === 0 active: task.highlighted @@ -659,7 +912,8 @@ ${smartLauncherDescription}`; } states: [ - // Using a state transition avoids a binding loop between label.visible and + // Using a state transition avoids a binding loop between label.visible + // and // the text label margin, which derives from the icon width. State { name: "standalone" @@ -668,12 +922,14 @@ ${smartLauncherDescription}`; AnchorChanges { target: iconBox anchors.left: undefined + anchors.horizontalCenter: parent.horizontalCenter } PropertyChanges { target: iconBox anchors.leftMargin: 0 + width: Math.min(task.parent.minimumWidth, tasks.height) - adjustMargin(true, task.width, taskFrame.margins.left) - adjustMargin(true, task.width, taskFrame.margins.right) } } @@ -682,6 +938,7 @@ ${smartLauncherDescription}`; Loader { anchors.centerIn: parent width: Math.min(parent.width, parent.height) + height: width active: model.IsStartup sourceComponent: busyIndicator @@ -694,18 +951,22 @@ ${smartLauncherDescription}`; visible: (inPopup || !iconsOnly && !model.IsLauncher && (parent.width - iconBox.height - Kirigami.Units.smallSpacing) >= LayoutMetrics.spaceRequiredToShowText()) anchors { + fill: parent leftMargin: taskFrame.margins.left + iconBox.width + LayoutMetrics.labelMargin topMargin: taskFrame.margins.top - rightMargin: taskFrame.margins.right + (audioStreamIcon !== null && audioStreamIcon.visible ? (audioStreamIcon.width + LayoutMetrics.labelMargin) : 0) + rightMargin: taskFrame.margins.right + (audioStreamIcon !== null && audioStreamIcon.visible ? + (audioStreamIcon.width + LayoutMetrics.labelMargin) : 0) bottomMargin: taskFrame.margins.bottom } - wrapMode: (maximumLineCount === 1) ? Text.NoWrap : Text.Wrap + wrapMode: (maximumLineCount === 1) ? + Text.NoWrap : Text.Wrap elide: Text.ElideRight textFormat: Text.PlainText verticalAlignment: Text.AlignVCenter - maximumLineCount: Plasmoid.configuration.maxTextLines || undefined + maximumLineCount: Plasmoid.configuration.maxTextLines || + undefined Accessible.ignored: true @@ -716,6 +977,7 @@ ${smartLauncherDescription}`; PropertyChanges { target: label + text: model.display } } @@ -727,6 +989,7 @@ ${smartLauncherDescription}`; when: model.IsLauncher === true PropertyChanges { + target: frame basePrefix: "" } @@ -734,15 +997,18 @@ ${smartLauncherDescription}`; target: colorOverride visible: false } + }, State { name: "attention" - when: model.IsDemandingAttention === true || (task.smartLauncherItem && task.smartLauncherItem.urgent) + when: model.IsDemandingAttention === true || + (task.smartLauncherItem && task.smartLauncherItem.urgent) PropertyChanges { target: frame basePrefix: "attention" - visible: (plasmoid.configuration.buttonColorize && !frame.isHovered) || !plasmoid.configuration.buttonColorize + visible: (plasmoid.configuration.buttonColorize && !frame.isHovered) || + !plasmoid.configuration.buttonColorize } PropertyChanges { target: colorOverride @@ -750,21 +1016,25 @@ ${smartLauncherDescription}`; } }, State { + name: "minimized" when: model.IsMinimized === true && !frame.isHovered && !plasmoid.configuration.disableButtonInactiveSvg PropertyChanges { target: frame basePrefix: "minimized" - visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? false : true + visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? + false : true } PropertyChanges { target: colorOverride - visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? true : false + visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? + true : false } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? false : true + visible: plasmoid.configuration.disableInactiveIndicators ? + false : true } }, State { @@ -773,16 +1043,20 @@ ${smartLauncherDescription}`; PropertyChanges { target: frame + basePrefix: "minimized" - visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true + visible: plasmoid.configuration.disableButtonInactiveSvg ? + false : true } PropertyChanges { target: colorOverride - visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true + visible: plasmoid.configuration.disableButtonInactiveSvg ? + false : true } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? false : true + visible: plasmoid.configuration.disableInactiveIndicators ? + false : true } }, State { @@ -791,15 +1065,18 @@ ${smartLauncherDescription}`; PropertyChanges { target: frame + basePrefix: "focus" } PropertyChanges { target: colorOverride - visible: plasmoid.configuration.buttonColorize ? true : false + visible: plasmoid.configuration.buttonColorize ? + true : false } PropertyChanges { target: indicator - visible: plasmoid.configuration.indicatorsEnabled ? true : false + visible: plasmoid.configuration.indicatorsEnabled ? + true : false } }, State { @@ -807,15 +1084,19 @@ ${smartLauncherDescription}`; when: model.IsActive === false && !frame.isHovered && !plasmoid.configuration.disableButtonInactiveSvg PropertyChanges { target: colorOverride - visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? true : false + + visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? + true : false } PropertyChanges { target: frame - visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? false : true + visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? + false : true } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? false : true + visible: plasmoid.configuration.disableInactiveIndicators ? + false : true } }, State { @@ -823,15 +1104,19 @@ ${smartLauncherDescription}`; when: (model.IsActive === false && !frame.isHovered) && plasmoid.configuration.disableButtonInactiveSvg PropertyChanges { target: colorOverride - visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true + + visible: plasmoid.configuration.disableButtonInactiveSvg ? + false : true } PropertyChanges { target: frame - visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true + visible: plasmoid.configuration.disableButtonInactiveSvg ? + false : true } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? false : true + visible: plasmoid.configuration.disableInactiveIndicators ? + false : true } }, State { @@ -839,15 +1124,18 @@ ${smartLauncherDescription}`; when: frame.isHovered PropertyChanges { target: colorOverride + visible: plasmoid.configuration.buttonColorize ? true : false } PropertyChanges { target: frame - visible: plasmoid.configuration.buttonColorize ? false : true + visible: plasmoid.configuration.buttonColorize ? + false : true } PropertyChanges { target: indicator - visible: plasmoid.configuration.disableInactiveIndicators ? false : true + visible: plasmoid.configuration.disableInactiveIndicators ? + false : true } } ] From 97b9825ce61ec278935ddefafee4740f9ff5fc97 Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Tue, 30 Dec 2025 13:06:44 +0200 Subject: [PATCH 136/141] Fix windows thumbnails --- package/contents/ui/Task.qml | 64 ++++++++++++----------- package/contents/ui/ToolTipInstance.qml | 67 +++++++++++++++---------- 2 files changed, 75 insertions(+), 56 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 84da85db..35da7c82 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -125,39 +125,43 @@ PlasmaCore.ToolTipArea { KSvg.FrameSvgItem { id: bgFrame imagePath: "widgets/tooltip" - - // Size depends on the loaded content + margins. - // Ensure at least some size to avoid visual glitches. - width: Math.max(delegateLoader.item ? delegateLoader.item.implicitWidth : 0, Kirigami.Units.gridUnit * 2) + margins.left + margins.right - height: Math.max(delegateLoader.item ? delegateLoader.item.implicitHeight : 0, Kirigami.Units.gridUnit) + margins.top + margins.bottom - + + readonly property int thumbBaseWidth: Kirigami.Units.gridUnit * 14 + readonly property int thumbBaseHeight: thumbBaseWidth / (Screen.width / Screen.height) + + width: Math.max(delegateLoader.item ? delegateLoader.item.implicitWidth : 0, model.IsWindow ? thumbBaseWidth : Kirigami.Units.gridUnit * 2) + margins.left + margins.right + height: Math.max(delegateLoader.item ? delegateLoader.item.implicitHeight : 0, model.IsWindow ? thumbBaseHeight : Kirigami.Units.gridUnit) + margins.top + margins.bottom + // Position logic: push away from the panel - anchors.top: (contentWrapper.loc === PlasmaCore.Types.BottomEdge) ? parent.top : undefined - anchors.bottom: (contentWrapper.loc === PlasmaCore.Types.TopEdge) ? parent.bottom : undefined - anchors.left: (contentWrapper.loc === PlasmaCore.Types.RightEdge) ? parent.left : undefined - anchors.right: (contentWrapper.loc === PlasmaCore.Types.LeftEdge) ? parent.right : undefined - + anchors.top: (contentWrapper.loc === PlasmaCore.Types.BottomEdge) ? + parent.top : undefined + anchors.bottom: (contentWrapper.loc === PlasmaCore.Types.TopEdge) ? + parent.bottom : undefined + anchors.left: (contentWrapper.loc === PlasmaCore.Types.RightEdge) ? + parent.left : undefined + anchors.right: (contentWrapper.loc === PlasmaCore.Types.LeftEdge) ? + parent.right : undefined + // Center on the other axis - anchors.horizontalCenter: (contentWrapper.loc === PlasmaCore.Types.TopEdge || contentWrapper.loc === PlasmaCore.Types.BottomEdge) ? parent.horizontalCenter : undefined - anchors.verticalCenter: (contentWrapper.loc === PlasmaCore.Types.LeftEdge || contentWrapper.loc === PlasmaCore.Types.RightEdge) ? parent.verticalCenter : undefined + anchors.horizontalCenter: (contentWrapper.loc === PlasmaCore.Types.TopEdge || contentWrapper.loc === PlasmaCore.Types.BottomEdge) ? + parent.horizontalCenter : undefined + anchors.verticalCenter: (contentWrapper.loc === PlasmaCore.Types.LeftEdge || contentWrapper.loc === PlasmaCore.Types.RightEdge) ? + parent.verticalCenter : undefined // Loader switches between complex window delegate and simple text delegate Loader { id: delegateLoader - // FIXED: Removed anchors.fill to avoid constraining content size. - // Instead, anchor only top/left and let content define the size. - anchors.left: parent.left - anchors.top: parent.top + anchors.fill: parent anchors.leftMargin: bgFrame.margins.left + anchors.rightMargin: bgFrame.margins.right anchors.topMargin: bgFrame.margins.top - - // Select component based on task type + anchors.bottomMargin: bgFrame.margins.bottom + sourceComponent: model.IsWindow ? windowDelegate : pinnedAppDelegate - asynchronous: false + asynchronous: false onLoaded: { - // Force update when loaded to ensure data is populated immediately if (task.toolTipOpen) { task.updateMainItemBindings() } @@ -368,7 +372,7 @@ PlasmaCore.ToolTipArea { target: translateTransform properties: "y" - from: moveAnim.y + from: moveAnim.y to: 0 easing.type: Easing.OutQuad duration: Kirigami.Units.longDuration @@ -411,9 +415,9 @@ PlasmaCore.ToolTipArea { case 2: { if (effectWatcher.registered) { - - return `${i18nc("@info:usagetip %1 task name", "Show windows side by side for %1", model.display)}; - ${smartLauncherDescription}`; + + return `${i18nc("@info:usagetip %1 task name", "Show windows side by side for %1", model.display)}; + ${smartLauncherDescription}`; } // fallthrough } @@ -710,7 +714,7 @@ PlasmaCore.ToolTipArea { TapHandler { id: leftTapHandler - + acceptedButtons: Qt.LeftButton onTapped: (eventPoint, button) => leftClick() @@ -811,7 +815,7 @@ PlasmaCore.ToolTipArea { onActiveChanged: { if (active) { icon.grabToImage(result => { - + if (!dragHandler.active) { // BUG 466675 grabToImage is async, so avoid updating dragSource when active is false return; @@ -850,7 +854,7 @@ PlasmaCore.ToolTipArea { } Loader { - + id: iconBox anchors { @@ -951,7 +955,7 @@ PlasmaCore.ToolTipArea { visible: (inPopup || !iconsOnly && !model.IsLauncher && (parent.width - iconBox.height - Kirigami.Units.smallSpacing) >= LayoutMetrics.spaceRequiredToShowText()) anchors { - + fill: parent leftMargin: taskFrame.margins.left + iconBox.width + LayoutMetrics.labelMargin topMargin: taskFrame.margins.top @@ -1016,7 +1020,7 @@ PlasmaCore.ToolTipArea { } }, State { - + name: "minimized" when: model.IsMinimized === true && !frame.isHovered && !plasmoid.configuration.disableButtonInactiveSvg diff --git a/package/contents/ui/ToolTipInstance.qml b/package/contents/ui/ToolTipInstance.qml index bb19abe5..4afc5305 100644 --- a/package/contents/ui/ToolTipInstance.qml +++ b/package/contents/ui/ToolTipInstance.qml @@ -75,27 +75,45 @@ ColumnLayout { // text labels + close button RowLayout { id: header - // match spacing of DefaultToolTip.qml in plasma-framework + // Отступ между текстом и кнопкой закрытия spacing: toolTipDelegate.isWin ? Kirigami.Units.smallSpacing : Kirigami.Units.gridUnit - // This number controls the overall size of the window tooltips + // Ограничиваем максимальную ширину Layout.maximumWidth: toolTipDelegate.tooltipInstanceMaximumWidth - Layout.minimumWidth: toolTipDelegate.isWin ? Layout.maximumWidth : 0 + + // Позволяем хедеру сжиматься (чтобы влезать в рамку 14 юнитов) + Layout.minimumWidth: 0 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - // match margins of DefaultToolTip.qml in plasma-framework - Layout.margins: toolTipDelegate.isWin ? 0 : Kirigami.Units.gridUnit / 2 + + // ИСПРАВЛЕНИЕ: Добавляем отступы для окон (было 0, стало smallSpacing) + // Теперь текст и кнопка не будут прилипать к краям рамки. + Layout.margins: toolTipDelegate.isWin ? Kirigami.Units.smallSpacing : Kirigami.Units.gridUnit / 2 + + // Чтобы контент занимал всю ширину (важно для правильной работы отступов) + Layout.fillWidth: true // all textlabels ColumnLayout { spacing: 0 + + // ИСПРАВЛЕНИЕ: Заставляем колонку с текстом занимать все место, + // но разрешаем ей сжиматься, чтобы она не выталкивала кнопку закрытия. + Layout.fillWidth: true + Layout.minimumWidth: 0 + // app name Kirigami.Heading { id: appNameHeading level: 3 maximumLineCount: 1 lineHeight: toolTipDelegate.isWin ? 1 : appNameHeading.lineHeight + + // Свойства для правильного обрезания текста Layout.fillWidth: true + Layout.minimumWidth: 0 elide: Text.ElideRight + text: toolTipDelegate.appName opacity: root.index === 0 ? 1 : 0 visible: text.length !== 0 @@ -105,8 +123,11 @@ ColumnLayout { PlasmaComponents3.Label { id: winTitle maximumLineCount: 1 + Layout.fillWidth: true + Layout.minimumWidth: 0 elide: Text.ElideRight + text: root.titleIncludesTrack ? "" : root.title opacity: 0.75 visible: root.title.length !== 0 && root.title !== appNameHeading.text @@ -116,8 +137,11 @@ ColumnLayout { PlasmaComponents3.Label { id: subtext maximumLineCount: 2 + Layout.fillWidth: true + Layout.minimumWidth: 0 elide: Text.ElideRight + text: toolTipDelegate.isWin ? root.generateSubText() : "" opacity: 0.6 visible: text.length !== 0 && text !== appNameHeading.text @@ -126,7 +150,6 @@ ColumnLayout { } // Count badge. - // The badge itself is inside an item to better center the text in the bubble Item { Layout.alignment: Qt.AlignRight | Qt.AlignTop Layout.preferredHeight: closeButton.height @@ -159,21 +182,18 @@ ColumnLayout { Item { id: thumbnailSourceItem - Layout.fillWidth: true - Layout.preferredHeight: Math.min(Kirigami.Units.gridUnit * 12, Screen.desktopAvailableHeight * 0.4) + readonly property int targetWidth: Kirigami.Units.gridUnit * 14 + readonly property int targetHeight: targetWidth / (Screen.width / Screen.height) - // Add maximum width constraint to help with portrait windows - Layout.maximumWidth: Math.min(Layout.preferredHeight * 1.77, Screen.desktopAvailableWidth * 0.3) + Layout.preferredWidth: targetWidth + Layout.preferredHeight: targetHeight - // Center in available space Layout.alignment: Qt.AlignCenter - clip: true visible: toolTipDelegate.isWin - readonly property /*undefined|WId where WId = int|string*/ var winId: toolTipDelegate.isWin ? toolTipDelegate.windows[root.index] : undefined + readonly property var winId: toolTipDelegate.isWin ? toolTipDelegate.windows[root.index] : undefined - // There's no PlasmaComponents3 version PlasmaExtras.Highlight { anchors.fill: hoverHandler visible: (hoverHandler.item as MouseArea)?.containsMouse ?? false @@ -183,42 +203,37 @@ ColumnLayout { Loader { id: thumbnailLoader - active: !toolTipDelegate.isLauncher && !albumArtImage.visible && (Number.isInteger(thumbnailSourceItem.winId) || pipeWireLoader.item && !pipeWireLoader.item.hasThumbnail) && root.index !== -1 // Avoid loading when the instance is going to be destroyed + active: !toolTipDelegate.isLauncher && !albumArtImage.visible && (Number.isInteger(thumbnailSourceItem.winId) || pipeWireLoader.item && !pipeWireLoader.item.hasThumbnail) && root.index !== -1 asynchronous: true visible: active + anchors.fill: hoverHandler - // Indent a little bit so that neither the thumbnail nor the drop - // shadow can cover up the highlight - anchors.margins: Kirigami.Units.smallSpacing * 2 + anchors.margins: 0 sourceComponent: root.isMinimized || pipeWireLoader.active ? iconItem : x11Thumbnail Component { id: x11Thumbnail - PlasmaCore.WindowThumbnail { winId: thumbnailSourceItem.winId } } - // when minimized, we don't have a preview on X11, so show the icon Component { id: iconItem - Kirigami.Icon { id: realIconItem source: toolTipDelegate.icon animated: false visible: valid opacity: pipeWireLoader.active ? 0 : 1 + + anchors.fill: parent + anchors.margins: Kirigami.Units.gridUnit SequentialAnimation { running: true - - PauseAnimation { - duration: Kirigami.Units.humanMoment - } - + PauseAnimation { duration: Kirigami.Units.humanMoment } NumberAnimation { id: showAnimation duration: Kirigami.Units.longDuration From 4c8a07255b90238f48f6b0e4268bfdba49d8494d Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Fri, 2 Jan 2026 16:30:12 +0200 Subject: [PATCH 137/141] Fix tooltips header --- package/contents/ui/ToolTipInstance.qml | 69 ++++++++++++++++++++----- 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/package/contents/ui/ToolTipInstance.qml b/package/contents/ui/ToolTipInstance.qml index 4afc5305..6aae3aec 100644 --- a/package/contents/ui/ToolTipInstance.qml +++ b/package/contents/ui/ToolTipInstance.qml @@ -47,27 +47,70 @@ ColumnLayout { return ""; } - // Normally the window title will always have " — [app name]" at the end of - // the window-provided title. - // But if it doesn't, this is intentional 100% - // of the time because the developer or user has deliberately removed that - // part, so just display it with no more fancy processing. - if (!text.match(/\s+(—|-|–)/)) { - return text; - } - // KWin appends increasing integers in between pointy brackets to otherwise equal window titles. // In this case save <#number> as counter and delete it at the end of text. - text = `${(text.match(/.*(?=\s+(—|-|–))/) || [""])[0]}${(text.match(/<\d+>/) || [""]).pop()}`; + let counter = ""; + const counterMatch = text.match(/\s*<\d+>$/); + if (counterMatch) { + counter = counterMatch[0]; + text = text.replace(/\s*<\d+>$/, ""); + } + + const appName = root.calculatedAppName; + + if (appName && appName.length > 0) { + const escapedAppName = appName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + // Try to remove " - AppName" followed by any text (version, suffixes, etc) + const cleanupRegex = new RegExp(`\\s+(?:—|-|–)\\s+${escapedAppName}.*$`, "i"); + + if (text.match(cleanupRegex)) { + text = text.replace(cleanupRegex, ""); + } else { + // Fallback: strip everything after the last separator + const greedyMatch = text.match(/.*(?=\s+(—|-|–))/); + if (greedyMatch) { + text = greedyMatch[0]; + } + } + } else { + const greedyMatch = text.match(/.*(?=\s+(—|-|–))/); + if (greedyMatch) { + text = greedyMatch[0]; + } + } // In case the window title had only redundant information (i.e. appName), text is now empty. // Add a hyphen to indicate that and avoid empty space. if (text === "") { text = "—"; } - return text; + + return text + counter; } + readonly property string calculatedAppName: { + if (toolTipDelegate.appName && toolTipDelegate.appName.length > 0) { + return toolTipDelegate.appName; + } + + const text = display; + + // Try to match " - AppName - Version" pattern (e.g. QOwnNotes) + const versionRegex = /\s+(?:—|-|–)\s+([^\s(—|-|–)]+)\s+(?:—|-|–)\s+v?\d+(?:\.\d+)+.*$/i; + const matchVersion = text.match(versionRegex); + if (matchVersion && matchVersion[1]) { + return matchVersion[1]; + } + + // Try to match standard " - AppName" pattern + const lastSepRegex = /.*(?:—|-|–)\s+(.*)$/; + const matchLast = text.match(lastSepRegex); + if (matchLast && matchLast[1]) { + return matchLast[1]; + } + + return ""; + } readonly property bool titleIncludesTrack: toolTipDelegate.playerData !== null && title.includes(toolTipDelegate.playerData.track) spacing: Kirigami.Units.smallSpacing @@ -101,6 +144,7 @@ ColumnLayout { // но разрешаем ей сжиматься, чтобы она не выталкивала кнопку закрытия. Layout.fillWidth: true Layout.minimumWidth: 0 + Layout.preferredWidth: 0 // app name Kirigami.Heading { @@ -109,12 +153,11 @@ ColumnLayout { maximumLineCount: 1 lineHeight: toolTipDelegate.isWin ? 1 : appNameHeading.lineHeight - // Свойства для правильного обрезания текста Layout.fillWidth: true Layout.minimumWidth: 0 elide: Text.ElideRight - text: toolTipDelegate.appName + text: root.calculatedAppName opacity: root.index === 0 ? 1 : 0 visible: text.length !== 0 textFormat: Text.PlainText From 7103bd4fc22b34c7f8e22183cfa1b1b4f1c42234 Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Fri, 2 Jan 2026 20:14:06 +0200 Subject: [PATCH 138/141] Fix thumbnails highlight --- package/contents/ui/Task.qml | 12 ++++++++++-- package/contents/ui/ToolTipInstance.qml | 2 +- package/contents/ui/ToolTipWindowMouseArea.qml | 5 ++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 35da7c82..676406e6 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -526,9 +526,17 @@ PlasmaCore.ToolTipArea { tasksModel.makeModelIndex(groupDialog.visualParent.index, index) : tasksModel.makeModelIndex(index); } - function showContextMenu(args: var): void { - task.hideImmediately(); + function closeTooltip(): void { tooltipDialog.visible = false; + task.toolTipOpen = false; + tasksRoot.toolTipOpenedByClick = null; + if (typeof task.hideImmediately === "function") { + task.hideImmediately(); + } + } + + function showContextMenu(args: var): void { + task.closeTooltip(); contextMenu = tasksRoot.createContextMenu(task, modelIndex(), args); contextMenu.show(); diff --git a/package/contents/ui/ToolTipInstance.qml b/package/contents/ui/ToolTipInstance.qml index 6aae3aec..b50135d2 100644 --- a/package/contents/ui/ToolTipInstance.qml +++ b/package/contents/ui/ToolTipInstance.qml @@ -251,7 +251,7 @@ ColumnLayout { visible: active anchors.fill: hoverHandler - anchors.margins: 0 + anchors.margins: Kirigami.Units.smallSpacing sourceComponent: root.isMinimized || pipeWireLoader.active ? iconItem : x11Thumbnail diff --git a/package/contents/ui/ToolTipWindowMouseArea.qml b/package/contents/ui/ToolTipWindowMouseArea.qml index b042aa25..ed2e4dc8 100644 --- a/package/contents/ui/ToolTipWindowMouseArea.qml +++ b/package/contents/ui/ToolTipWindowMouseArea.qml @@ -13,7 +13,7 @@ import QtQuick MouseArea { required property var modelIndex required property var winId - required property var rootTask // Используем var вместо Task, чтобы избежать циклических зависимостей + required property var rootTask acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton hoverEnabled: true @@ -23,8 +23,7 @@ MouseArea { switch (mouse.button) { case Qt.LeftButton: tasksModel.requestActivate(modelIndex); - rootTask.hideImmediately(); - // Используем tasksRoot для доступа к корневому элементу + rootTask.closeTooltip(); if (rootTask.tasksRoot) { rootTask.tasksRoot.cancelHighlightWindows(); } From 455b7be0fc23105422fbd7645475e127bee1b513 Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Sat, 3 Jan 2026 01:44:10 +0200 Subject: [PATCH 139/141] Fix tooltips with thumbnails --- package/contents/ui/ToolTipDelegate.qml | 7 +- package/contents/ui/ToolTipInstance.qml | 116 +++++++++--------- .../contents/ui/ToolTipWindowMouseArea.qml | 13 +- 3 files changed, 72 insertions(+), 64 deletions(-) diff --git a/package/contents/ui/ToolTipDelegate.qml b/package/contents/ui/ToolTipDelegate.qml index 17671ead..10626240 100644 --- a/package/contents/ui/ToolTipDelegate.qml +++ b/package/contents/ui/ToolTipDelegate.qml @@ -52,7 +52,7 @@ Loader { readonly property bool isVerticalPanel: Plasmoid.formFactor === PlasmaCore.Types.Vertical // This number controls the overall size of the window tooltips - readonly property int tooltipInstanceMaximumWidth: Kirigami.Units.gridUnit * 16 + readonly property int tooltipInstanceMaximumWidth: Kirigami.Units.gridUnit * 14 // These properties are required to make tooltip interactive when there is a player but no window is present. readonly property Mpris.PlayerContainer playerData: mpris2Source.playerForLauncherUrl(launcherUrl, pidParent) @@ -86,14 +86,15 @@ Loader { PlasmaComponents3.ScrollView { // 2 * Kirigami.Units.smallSpacing is for the margin of tooltipDialog implicitWidth: leftPadding + rightPadding + Math.min(Screen.desktopAvailableWidth - 2 * Kirigami.Units.smallSpacing, Math.max(delegateModel.estimatedWidth, contentItem.contentItem.childrenRect.width)) - implicitHeight: bottomPadding + Math.min(Screen.desktopAvailableHeight - 2 * Kirigami.Units.smallSpacing, Math.max(delegateModel.estimatedHeight, contentItem.contentItem.childrenRect.height)) + implicitHeight: topPadding + bottomPadding + Math.min(Screen.desktopAvailableHeight - 2 * Kirigami.Units.smallSpacing, Math.max(delegateModel.estimatedHeight, contentItem.contentItem.childrenRect.height)) ListView { id: groupToolTipListView model: delegateModel - orientation: isVerticalPanel ? ListView.Vertical : ListView.Horizontal + orientation: isVerticalPanel ? + ListView.Vertical : ListView.Horizontal reuseItems: true spacing: Kirigami.Units.gridUnit } diff --git a/package/contents/ui/ToolTipInstance.qml b/package/contents/ui/ToolTipInstance.qml index b50135d2..d63c8cb8 100644 --- a/package/contents/ui/ToolTipInstance.qml +++ b/package/contents/ui/ToolTipInstance.qml @@ -24,19 +24,46 @@ import org.kde.kwindowsystem ColumnLayout { id: root + // ADDED: Tracks hover over the entire ColumnLayout (including headers, gaps) + HoverHandler { + id: rootHover + } + required property int index - required property /*QModelIndex*/ var submodelIndex + required property var submodelIndex required property int appPid required property string display required property bool isMinimized required property bool isOnAllVirtualDesktops - required property /*list*/ var virtualDesktops // Can't use list because of QTBUG-127600 + required property var virtualDesktops required property list activities // HACK: Avoid blank space in the tooltip after closing a window ListView.onPooled: width = height = 0 ListView.onReused: width = height = undefined + readonly property string calculatedAppName: { + if (toolTipDelegate.appName && toolTipDelegate.appName.length > 0) { + return toolTipDelegate.appName; + } + + const text = display; + + const versionRegex = /\s+(?:—|-|–)\s+([^\s(—|-|–)]+)\s+(?:—|-|–)\s+v?\d+(?:\.\d+)+.*$/i; + const matchVersion = text.match(versionRegex); + if (matchVersion && matchVersion[1]) { + return matchVersion[1]; + } + + const lastSepRegex = /.*(?:—|-|–)\s+(.*)$/; + const matchLast = text.match(lastSepRegex); + if (matchLast && matchLast[1]) { + return matchLast[1]; + } + + return ""; + } + readonly property string title: { if (!toolTipDelegate.isWin) { return toolTipDelegate.genericName; @@ -47,8 +74,6 @@ ColumnLayout { return ""; } - // KWin appends increasing integers in between pointy brackets to otherwise equal window titles. - // In this case save <#number> as counter and delete it at the end of text. let counter = ""; const counterMatch = text.match(/\s*<\d+>$/); if (counterMatch) { @@ -60,13 +85,11 @@ ColumnLayout { if (appName && appName.length > 0) { const escapedAppName = appName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - // Try to remove " - AppName" followed by any text (version, suffixes, etc) const cleanupRegex = new RegExp(`\\s+(?:—|-|–)\\s+${escapedAppName}.*$`, "i"); if (text.match(cleanupRegex)) { text = text.replace(cleanupRegex, ""); } else { - // Fallback: strip everything after the last separator const greedyMatch = text.match(/.*(?=\s+(—|-|–))/); if (greedyMatch) { text = greedyMatch[0]; @@ -79,8 +102,6 @@ ColumnLayout { } } - // In case the window title had only redundant information (i.e. appName), text is now empty. - // Add a hyphen to indicate that and avoid empty space. if (text === "") { text = "—"; } @@ -88,29 +109,6 @@ ColumnLayout { return text + counter; } - readonly property string calculatedAppName: { - if (toolTipDelegate.appName && toolTipDelegate.appName.length > 0) { - return toolTipDelegate.appName; - } - - const text = display; - - // Try to match " - AppName - Version" pattern (e.g. QOwnNotes) - const versionRegex = /\s+(?:—|-|–)\s+([^\s(—|-|–)]+)\s+(?:—|-|–)\s+v?\d+(?:\.\d+)+.*$/i; - const matchVersion = text.match(versionRegex); - if (matchVersion && matchVersion[1]) { - return matchVersion[1]; - } - - // Try to match standard " - AppName" pattern - const lastSepRegex = /.*(?:—|-|–)\s+(.*)$/; - const matchLast = text.match(lastSepRegex); - if (matchLast && matchLast[1]) { - return matchLast[1]; - } - - return ""; - } readonly property bool titleIncludesTrack: toolTipDelegate.playerData !== null && title.includes(toolTipDelegate.playerData.track) spacing: Kirigami.Units.smallSpacing @@ -118,33 +116,21 @@ ColumnLayout { // text labels + close button RowLayout { id: header - // Отступ между текстом и кнопкой закрытия spacing: toolTipDelegate.isWin ? Kirigami.Units.smallSpacing : Kirigami.Units.gridUnit - // Ограничиваем максимальную ширину Layout.maximumWidth: toolTipDelegate.tooltipInstanceMaximumWidth - - // Позволяем хедеру сжиматься (чтобы влезать в рамку 14 юнитов) Layout.minimumWidth: 0 - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - - // ИСПРАВЛЕНИЕ: Добавляем отступы для окон (было 0, стало smallSpacing) - // Теперь текст и кнопка не будут прилипать к краям рамки. Layout.margins: toolTipDelegate.isWin ? Kirigami.Units.smallSpacing : Kirigami.Units.gridUnit / 2 - - // Чтобы контент занимал всю ширину (важно для правильной работы отступов) Layout.fillWidth: true // all textlabels ColumnLayout { spacing: 0 - // ИСПРАВЛЕНИЕ: Заставляем колонку с текстом занимать все место, - // но разрешаем ей сжиматься, чтобы она не выталкивала кнопку закрытия. Layout.fillWidth: true + Layout.preferredWidth: 0 Layout.minimumWidth: 0 - Layout.preferredWidth: 0 // app name Kirigami.Heading { @@ -235,11 +221,15 @@ ColumnLayout { clip: true visible: toolTipDelegate.isWin - readonly property var winId: toolTipDelegate.isWin ? toolTipDelegate.windows[root.index] : undefined + readonly property var winId: toolTipDelegate.isWin ? + toolTipDelegate.windows[root.index] : undefined PlasmaExtras.Highlight { - anchors.fill: hoverHandler - visible: (hoverHandler.item as MouseArea)?.containsMouse ?? false + anchors.fill: hoverHandler // Anchor to the interaction area + + // FIX: Highlight is visible when hovering ANYWHERE on the tooltip (rootHover) + visible: rootHover.hovered + pressed: (hoverHandler.item as MouseArea)?.containsPress ?? false hovered: true } @@ -253,7 +243,8 @@ ColumnLayout { anchors.fill: hoverHandler anchors.margins: Kirigami.Units.smallSpacing - sourceComponent: root.isMinimized || pipeWireLoader.active ? iconItem : x11Thumbnail + sourceComponent: root.isMinimized || + pipeWireLoader.active ? iconItem : x11Thumbnail Component { id: x11Thumbnail @@ -269,7 +260,8 @@ ColumnLayout { source: toolTipDelegate.icon animated: false visible: valid - opacity: pipeWireLoader.active ? 0 : 1 + opacity: pipeWireLoader.active ? + 0 : 1 anchors.fill: parent anchors.margins: Kirigami.Units.gridUnit @@ -293,8 +285,6 @@ ColumnLayout { Loader { id: pipeWireLoader anchors.fill: hoverHandler - // Indent a little bit so that neither the thumbnail nor the drop - // shadow can cover up the highlight anchors.margins: thumbnailLoader.anchors.margins active: !toolTipDelegate.isLauncher && !albumArtImage.visible && KWindowSystem.isPlatformWayland && root.index !== -1 @@ -304,10 +294,12 @@ ColumnLayout { } Loader { - active: (pipeWireLoader.item?.hasThumbnail ?? false) || (thumbnailLoader.status === Loader.Ready && !root.isMinimized) + active: (pipeWireLoader.item?.hasThumbnail ?? false) || + (thumbnailLoader.status === Loader.Ready && !root.isMinimized) asynchronous: true visible: active - anchors.fill: pipeWireLoader.active ? pipeWireLoader : thumbnailLoader + anchors.fill: pipeWireLoader.active ? + pipeWireLoader : thumbnailLoader sourceComponent: GE.DropShadow { horizontalOffset: 0 @@ -315,7 +307,8 @@ ColumnLayout { radius: 8 samples: Math.round(radius * 1.5) color: "Black" - source: pipeWireLoader.active ? pipeWireLoader.item : thumbnailLoader.item // source could be undefined when albumArt is available, so put it in a Loader. + source: pipeWireLoader.active ? + pipeWireLoader.item : thumbnailLoader.item // source could be undefined when albumArt is available, so put it in a Loader. } } @@ -331,6 +324,7 @@ ColumnLayout { // Manual implementation of Image.PreserveAspectCrop readonly property real scaleFactor: Math.max(hoverHandler.width / source.paintedWidth, hoverHandler.height / source.paintedHeight) + width: Math.round(source.paintedWidth * scaleFactor) height: Math.round(source.paintedHeight * scaleFactor) layer.enabled: true @@ -349,7 +343,8 @@ ColumnLayout { // if this is a group tooltip, we check if window title and track match, to allow distinguishing the different windows // if this app is a browser, we also check the title, so album art is not shown when the user is on some other tab // in all other cases we can safely show the album art without checking the title - readonly property bool available: (status === Image.Ready || status === Image.Loading) && (!(toolTipDelegate.isGroup || backend.applicationCategories(launcherUrl).includes("WebBrowser")) || root.titleIncludesTrack) + readonly property bool available: (status === Image.Ready || + status === Image.Loading) && (!(toolTipDelegate.isGroup || backend.applicationCategories(launcherUrl).includes("WebBrowser")) || root.titleIncludesTrack) anchors.fill: hoverHandler // Indent by one pixel to make sure we never cover up the entire highlight @@ -362,7 +357,7 @@ ColumnLayout { visible: available } - // hoverHandler has to be unloaded after the instance is pooled in order to avoid getting the old containsMouse status when the same instance is reused, so put it in a Loader. + // RESTORED: Loader for MouseArea to handle recycling correctly. Loader { id: hoverHandler active: root.index !== -1 @@ -371,6 +366,9 @@ ColumnLayout { rootTask: toolTipDelegate.parentTask modelIndex: root.submodelIndex winId: thumbnailSourceItem.winId + + // FIX: Pass global hover state to the mouse area logic + globalHovered: rootHover.hovered } } } @@ -416,7 +414,8 @@ ColumnLayout { checked: toolTipDelegate.parentTask.muted PlasmaComponents3.ToolTip { - text: parent.checked ? i18nc("button to unmute app", "Unmute %1", toolTipDelegate.parentTask.appName) : i18nc("button to mute app", "Mute %1", toolTipDelegate.parentTask.appName) + text: parent.checked ? + i18nc("button to unmute app", "Unmute %1", toolTipDelegate.parentTask.appName) : i18nc("button to mute app", "Mute %1", toolTipDelegate.parentTask.appName) } } @@ -431,7 +430,8 @@ ColumnLayout { to: pulseAudio.item.normalVolume value: loudestVolume stepSize: to / 100 - opacity: toolTipDelegate.parentTask.muted ? 0.5 : 1 + opacity: toolTipDelegate.parentTask.muted ? + 0.5 : 1 Accessible.name: i18nc("Accessibility data on volume slider", "Adjust volume for %1", toolTipDelegate.parentTask.appName) diff --git a/package/contents/ui/ToolTipWindowMouseArea.qml b/package/contents/ui/ToolTipWindowMouseArea.qml index ed2e4dc8..8f461965 100644 --- a/package/contents/ui/ToolTipWindowMouseArea.qml +++ b/package/contents/ui/ToolTipWindowMouseArea.qml @@ -13,7 +13,9 @@ import QtQuick MouseArea { required property var modelIndex required property var winId - required property var rootTask + required property var rootTask + + property bool globalHovered: false acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton hoverEnabled: true @@ -42,9 +44,14 @@ MouseArea { } } - onContainsMouseChanged: { + function updateHoverState() { if (rootTask.tasksRoot) { - rootTask.tasksRoot.windowsHovered([winId], containsMouse); + // Окно подсвечивается/скрывает другие, если мышь внутри этого MouseArea ИЛИ где-то еще в тултипе + const isHovered = containsMouse || globalHovered; + rootTask.tasksRoot.windowsHovered([winId], isHovered); } } + + onContainsMouseChanged: updateHoverState() + onGlobalHoveredChanged: updateHoverState() } From e1621046a5918fdc6320fe9b97750b3fba5dc1b1 Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Sat, 3 Jan 2026 13:26:22 +0200 Subject: [PATCH 140/141] Set icon scale direction --- package/contents/ui/Task.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 676406e6..f26a6cb5 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -907,7 +907,9 @@ PlasmaCore.ToolTipArea { height: (sizeOverride ? fixedSize : (parent.height * iconScale)) + growSize - anchors.centerIn: parent + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: (parent.height - (sizeOverride ? fixedSize : (parent.height * iconScale))) / 2 Behavior on growSize { NumberAnimation { From fc1eed1a5fe73f98d82e7d9efae9754673e0a425 Mon Sep 17 00:00:00 2001 From: Vitaliy Elin Date: Sat, 3 Jan 2026 14:03:57 +0200 Subject: [PATCH 141/141] Fix tooltip margin for scaled icons --- package/contents/ui/Task.qml | 103 +++++++++++++++++------------------ 1 file changed, 49 insertions(+), 54 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index f26a6cb5..6cd522db 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -33,7 +33,8 @@ PlasmaCore.ToolTipArea { property string tintColor: Kirigami.ColorUtils.brightnessForColor(Kirigami.Theme.backgroundColor) === Kirigami.ColorUtils.Dark ? "#ffffff" : "#000000" - rotation: Plasmoid.configuration.reverseMode && Plasmoid.formFactor === PlasmaCore.Types.Vertical ? 180 : 0 + rotation: Plasmoid.configuration.reverseMode && Plasmoid.formFactor === PlasmaCore.Types.Vertical ? + 180 : 0 implicitHeight: inPopup ? LayoutMetrics.preferredHeightInPopup() : Math.max(tasksRoot.height / tasksRoot.plasmoid.configuration.maxStripes, LayoutMetrics.preferredMinHeight()) @@ -71,7 +72,7 @@ PlasmaCore.ToolTipArea { property bool delayAudioStreamIndicator: false property bool completed: false readonly property - bool audioIndicatorsEnabled: Plasmoid.configuration.indicateAudioStreams + bool audioIndicatorsEnabled: Plasmoid.configuration.indicateAudioStreams readonly property bool hasAudioStream: audioStreams.length > 0 readonly property bool playingAudio: hasAudioStream && audioStreams.some(item => !item.corked) readonly property bool muted: hasAudioStream && audioStreams.every(item => item.muted) @@ -92,7 +93,8 @@ PlasmaCore.ToolTipArea { property alias tooltipContent: delegateLoader.item // Check interaction capability (windows always interactive, others check playerData) - interactive: model.IsWindow || (tooltipContent && tooltipContent.playerData) + interactive: model.IsWindow || + (tooltipContent && tooltipContent.playerData) // Custom Tooltip Dialog PlasmaCore.Dialog { @@ -103,7 +105,8 @@ PlasmaCore.ToolTipArea { // We draw our own background to handle the gap backgroundHints: PlasmaCore.Types.NoBackground - flags: Qt.ToolTip | Qt.FramelessWindowHint | Qt.WA_TranslucentBackground + flags: Qt.ToolTip | + Qt.FramelessWindowHint | Qt.WA_TranslucentBackground visible: false @@ -114,12 +117,34 @@ PlasmaCore.ToolTipArea { HoverHandler { id: wrapperHover } // Gap configuration - readonly property int gapSize: Kirigami.Units.gridUnit / 2 + readonly property int gapSize: { + const standardGap = Kirigami.Units.smallSpacing; + + const zoom = plasmoid.configuration.iconZoomFactor; + const sizeOverride = plasmoid.configuration.iconSizeOverride; + const fixedSize = plasmoid.configuration.iconSizePx; + const iconScale = plasmoid.configuration.iconScale / 100; + + const baseIconHeight = sizeOverride ? fixedSize : (iconBox.height * iconScale); + const zoomedIconHeight = baseIconHeight + zoom; + + const padding = (iconBox.height - baseIconHeight) / 2; + const overflow = zoom - padding; + + if (overflow > 0 && zoomedIconHeight > (iconBox.height + standardGap)) { + return overflow + 1; + } + + return standardGap; + } + readonly property int loc: Plasmoid.location // Calculate size: Background Frame + Gap - implicitWidth: (loc === PlasmaCore.Types.LeftEdge || loc === PlasmaCore.Types.RightEdge) ? (bgFrame.width + gapSize) : bgFrame.width - implicitHeight: (loc === PlasmaCore.Types.TopEdge || loc === PlasmaCore.Types.BottomEdge) ? (bgFrame.height + gapSize) : bgFrame.height + implicitWidth: (loc === PlasmaCore.Types.LeftEdge || loc === PlasmaCore.Types.RightEdge) ? + (bgFrame.width + gapSize) : bgFrame.width + implicitHeight: (loc === PlasmaCore.Types.TopEdge || loc === PlasmaCore.Types.BottomEdge) ? + (bgFrame.height + gapSize) : bgFrame.height // The visual bubble KSvg.FrameSvgItem { @@ -158,7 +183,8 @@ PlasmaCore.ToolTipArea { anchors.topMargin: bgFrame.margins.top anchors.bottomMargin: bgFrame.margins.bottom - sourceComponent: model.IsWindow ? windowDelegate : pinnedAppDelegate + sourceComponent: model.IsWindow ? + windowDelegate : pinnedAppDelegate asynchronous: false onLoaded: { @@ -199,7 +225,8 @@ PlasmaCore.ToolTipArea { property bool blockingUpdates // Expose playerData from inner item up to here, so Task can see it for 'interactive' check - readonly property var playerData: item ? item.playerData : null + readonly property var playerData: item ? + item.playerData : null // Forward these properties to the inner ToolTipDelegate when it loads onLoaded: { @@ -371,7 +398,6 @@ PlasmaCore.ToolTipArea { NumberAnimation { target: translateTransform properties: "y" - from: moveAnim.y to: 0 easing.type: Easing.OutQuad @@ -381,7 +407,6 @@ PlasmaCore.ToolTipArea { } transform: Translate { id: translateTransform - } Accessible.name: model.display @@ -403,32 +428,31 @@ PlasmaCore.ToolTipArea { switch (Plasmoid.configuration.groupedTaskVisualization) { case 0: break; - // Use the default description + // Use the default description case 1: { if (Plasmoid.configuration.showToolTips) { return `${i18nc("@info:usagetip %1 task name", "Show Task tooltip for %1", model.display)}; - ${smartLauncherDescription}`; +${smartLauncherDescription}`; } // fallthrough } case 2: { if (effectWatcher.registered) { - - return `${i18nc("@info:usagetip %1 task name", "Show windows side by side for %1", model.display)}; - ${smartLauncherDescription}`; + return `${i18nc("@info:usagetip %1 task name", "Show windows side by side for %1", model.display)}; +${smartLauncherDescription}`; } // fallthrough } default: return `${i18nc("@info:usagetip %1 task name", "Open textual list of windows for %1", model.display)}; - ${smartLauncherDescription}`; +${smartLauncherDescription}`; } } return `${i18n("Activate %1", model.display)}; - ${smartLauncherDescription}`; +${smartLauncherDescription}`; } Accessible.role: Accessible.Button Accessible.onPressAction: leftTapHandler.leftClick() @@ -464,7 +488,6 @@ PlasmaCore.ToolTipArea { onIndexChanged: { tooltipDialog.visible = false; - if (!inPopup && !tasksRoot.vertical && !Plasmoid.configuration.separateLaunchers) { tasksRoot.requestLayout(); } @@ -507,8 +530,7 @@ PlasmaCore.ToolTipArea { Keys.onDownPressed: event => Keys.rightPressed(event) Keys.onLeftPressed: event => { if (!inPopup && (event.modifiers & Qt.ControlModifier) && (event.modifiers & Qt.ShiftModifier)) { - tasksModel.move(task.index, task.index - - 1); + tasksModel.move(task.index, task.index - 1); } else { event.accepted = false; } @@ -537,7 +559,6 @@ PlasmaCore.ToolTipArea { function showContextMenu(args: var): void { task.closeTooltip(); - contextMenu = tasksRoot.createContextMenu(task, modelIndex(), args); contextMenu.show(); } @@ -600,7 +621,6 @@ PlasmaCore.ToolTipArea { item.parentTask = this; item.rootIndex = tasksModel.makeModelIndex(index, -1); - item.appName = Qt.binding(() => model.AppName); item.pidParent = Qt.binding(() => model.AppPid); item.windows = Qt.binding(() => model.WinIdList); @@ -641,8 +661,7 @@ PlasmaCore.ToolTipArea { var max = Math.max(r, g, b), min = Math.min(r, g, b); var h, s, l = (max + min) / 2; if (max == min) { - h = s = 0; - // achromatic + h = s = 0; // achromatic } else { var d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); @@ -722,7 +741,6 @@ PlasmaCore.ToolTipArea { TapHandler { id: leftTapHandler - acceptedButtons: Qt.LeftButton onTapped: (eventPoint, button) => leftClick() @@ -779,7 +797,6 @@ PlasmaCore.ToolTipArea { property color indicatorColor: Kirigami.ColorUtils.tintWithAlpha(frame.dominantColor, tintColor, .38) anchors { - fill: parent topMargin: (!tasksRoot.vertical && taskList.rows > 1) ? @@ -808,7 +825,6 @@ PlasmaCore.ToolTipArea { function setRequestedInhibitDnd(value: bool): void { // This is modifying the value in the panel containment that - // inhibits accepting drag and drop, so that we don't accidentally // drop the task on this panel. let item = this; @@ -823,21 +839,16 @@ PlasmaCore.ToolTipArea { onActiveChanged: { if (active) { icon.grabToImage(result => { - if (!dragHandler.active) { // BUG 466675 grabToImage is async, so avoid updating dragSource when active is false return; - } setRequestedInhibitDnd(true); tasksRoot.dragSource = task; dragHelper.Drag.imageSource = result.url; - - dragHelper.Drag.mimeData = { "text/x-orgkdeplasmataskmanager_taskurl": backend.tryDecodeApplicationsUrl(model.LauncherUrlWithoutIcon).toString(), [model.MimeType]: model.MimeData, - "application/x-orgkdeplasmataskmanager_taskbuttonitem": model.MimeData }; dragHelper.Drag.active = dragHandler.active; @@ -862,7 +873,6 @@ PlasmaCore.ToolTipArea { } Loader { - id: iconBox anchors { @@ -906,28 +916,25 @@ PlasmaCore.ToolTipArea { width: (sizeOverride ? fixedSize : (parent.width * iconScale)) + growSize height: (sizeOverride ? fixedSize : (parent.height * iconScale)) + growSize - anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: parent.bottom - anchors.bottomMargin: (parent.height - (sizeOverride ? fixedSize : (parent.height * iconScale))) / 2 + anchors.bottomMargin: (parent.height - (sizeOverride ? fixedSize : (parent.height * iconScale))) / 2 Behavior on growSize { NumberAnimation { duration: plasmoid.configuration.iconZoomDuration easing.type: Easing.InOutQuad } - } roundToIconSize: growSize === 0 - active: task.highlighted + active: task.highlighted || wrapperHover.hovered enabled: true source: model.decoration } states: [ - // Using a state transition avoids a binding loop between label.visible - // and + // Using a state transition avoids a binding loop between label.visible and // the text label margin, which derives from the icon width. State { name: "standalone" @@ -936,14 +943,12 @@ PlasmaCore.ToolTipArea { AnchorChanges { target: iconBox anchors.left: undefined - anchors.horizontalCenter: parent.horizontalCenter } PropertyChanges { target: iconBox anchors.leftMargin: 0 - width: Math.min(task.parent.minimumWidth, tasks.height) - adjustMargin(true, task.width, taskFrame.margins.left) - adjustMargin(true, task.width, taskFrame.margins.right) } } @@ -952,7 +957,6 @@ PlasmaCore.ToolTipArea { Loader { anchors.centerIn: parent width: Math.min(parent.width, parent.height) - height: width active: model.IsStartup sourceComponent: busyIndicator @@ -965,7 +969,6 @@ PlasmaCore.ToolTipArea { visible: (inPopup || !iconsOnly && !model.IsLauncher && (parent.width - iconBox.height - Kirigami.Units.smallSpacing) >= LayoutMetrics.spaceRequiredToShowText()) anchors { - fill: parent leftMargin: taskFrame.margins.left + iconBox.width + LayoutMetrics.labelMargin topMargin: taskFrame.margins.top @@ -991,7 +994,6 @@ PlasmaCore.ToolTipArea { PropertyChanges { target: label - text: model.display } } @@ -1003,7 +1005,6 @@ PlasmaCore.ToolTipArea { when: model.IsLauncher === true PropertyChanges { - target: frame basePrefix: "" } @@ -1011,7 +1012,6 @@ PlasmaCore.ToolTipArea { target: colorOverride visible: false } - }, State { name: "attention" @@ -1030,7 +1030,6 @@ PlasmaCore.ToolTipArea { } }, State { - name: "minimized" when: model.IsMinimized === true && !frame.isHovered && !plasmoid.configuration.disableButtonInactiveSvg @@ -1057,7 +1056,6 @@ PlasmaCore.ToolTipArea { PropertyChanges { target: frame - basePrefix: "minimized" visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true @@ -1079,7 +1077,6 @@ PlasmaCore.ToolTipArea { PropertyChanges { target: frame - basePrefix: "focus" } PropertyChanges { @@ -1098,7 +1095,6 @@ PlasmaCore.ToolTipArea { when: model.IsActive === false && !frame.isHovered && !plasmoid.configuration.disableButtonInactiveSvg PropertyChanges { target: colorOverride - visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? true : false } @@ -1118,7 +1114,6 @@ PlasmaCore.ToolTipArea { when: (model.IsActive === false && !frame.isHovered) && plasmoid.configuration.disableButtonInactiveSvg PropertyChanges { target: colorOverride - visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true } @@ -1138,8 +1133,8 @@ PlasmaCore.ToolTipArea { when: frame.isHovered PropertyChanges { target: colorOverride - - visible: plasmoid.configuration.buttonColorize ? true : false + visible: plasmoid.configuration.buttonColorize ? + true : false } PropertyChanges { target: frame

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 literal 0 HcmV?d00001 From 1c8e8e789a134aa7e728b39c46d067e092b218a9 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sat, 29 Oct 2022 04:41:41 -0600 Subject: [PATCH 021/141] add another picture --- docs/colorfulicons crop.png | Bin 0 -> 36542 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/colorfulicons crop.png diff --git a/docs/colorfulicons crop.png b/docs/colorfulicons crop.png new file mode 100644 index 0000000000000000000000000000000000000000..299f7106cc074fafc101512b2dd445e23225488c GIT binary patch literal 36542 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 uv?KvEfC$C_6II( Date: Sat, 29 Oct 2022 04:47:24 -0600 Subject: [PATCH 022/141] Add new pics to readme --- README.MD | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.MD b/README.MD index dbb57ed2..4f80aad8 100644 --- a/README.MD +++ b/README.MD @@ -33,28 +33,28 @@ Features improvements tweaks and options to the original task manager plasmoid m ## Pictures Colorful Tasks -![Colorful tasks](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/ColoredTasks.png?raw=true) +![Colorful tasks](https://github.com/alexankitty/FancyTasks/blob/main/docs/colorfulicons%20crop.png?raw=true) -Metro Full Sized +Metro -![Metro Full Sized](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/Metro%20Full.png?raw=true) +![Metro](https://github.com/alexankitty/FancyTasks/blob/main/docs/metro.png?raw=true) -Ciliora Full Sized +Ciliora -![Ciliora Full Sized](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/Ciliora%20Full.png?raw=true) +![Ciliora](https://github.com/alexankitty/FancyTasks/blob/main/docs/ciliora.png?raw=true) -Dashes Full Sized +Dashes -![Dashes Full Sized](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/Dashes%20Full.png?raw=true) +![Dashes](https://github.com/alexankitty/FancyTasks/blob/main/docs/dashes.png?raw=true) -Metro Icon Only +Dots -![Metro Icon Only](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/Metro%20Short.png?raw=true) +![Dots](https://github.com/alexankitty/FancyTasks/blob/main/docs/dots.png?raw=true) -Ciliora Icon Only +Desaturate minimized tasks -![Ciliora Icon Only](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/Ciliora%20Short.png?raw=true) +![Desaturated Minimized Tasks](https://github.com/alexankitty/FancyTasks/blob/main/docs/desaturate%20crop.png?raw=true) -Dashes Icon Only +Minimized task shrinking -![Dashes Icon Only](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/docs/Dashes%20Short.png?raw=true) +![Minimized task shrinking](https://github.com/alexankitty/FancyTasks/blob/main/docs/shrink%20crop.png?raw=true) \ No newline at end of file From 5ddda8a524a400bcebb7e68c0d2ecbc8bfdd9f68 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Sat, 29 Oct 2022 08:05:14 -0600 Subject: [PATCH 023/141] Added notes about the project. --- README.MD | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.MD b/README.MD index 4f80aad8..ac3f190c 100644 --- a/README.MD +++ b/README.MD @@ -57,4 +57,9 @@ Desaturate minimized tasks Minimized task shrinking -![Minimized task shrinking](https://github.com/alexankitty/FancyTasks/blob/main/docs/shrink%20crop.png?raw=true) \ No newline at end of file +![Minimized task shrinking](https://github.com/alexankitty/FancyTasks/blob/main/docs/shrink%20crop.png?raw=true) + +## Extra Notes +I'm a solo developer working on this project in my free time so it may take me a bit of time to work on issues. You can help me out by either doing a PR with fixes and I'll validate that they work in the code, or put in an issue for things that need to be changed. +Especially helpful will be settings names to make them more clear. I have a code bias unfortunately so it does make it exceedingly difficult to convey what everything does. +Lastly any feedback is appreciated, and I'll try to implement it as soon as I can. From 5ea8895c223f3ffc75054b6833f40d4d3012f935 Mon Sep 17 00:00:00 2001 From: Samisafool Date: Sun, 30 Oct 2022 09:22:37 +0530 Subject: [PATCH 024/141] Update README.MD --- README.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.MD b/README.MD index ac3f190c..4b9f7928 100644 --- a/README.MD +++ b/README.MD @@ -5,7 +5,7 @@ ## Installing 1. Clone this repository with the following command `git clone https://github.com/alexankitty/FancyTasks` -2. CD into the foloder and run the script `install.sh`, you may need to chmod +x or run append your shell in front of the script to run it +2. CD into the foloder and run the script `install.sh`, you may need to chmod +x or prepend your shell before the script in order to run it 3. Right click your panel, click add widgets and search for fancy tasks. 4. Right click the new task panel and click Configure Fancy Tasks... - everything you will want to configure to enable the new features will be in there. Default features are based on the KDE's team existing vision. From fc32ce05dca83dbe94210315080540f40f3e1ad6 Mon Sep 17 00:00:00 2001 From: Han Prower <1781312+HanPrower@users.noreply.github.com> Date: Sun, 30 Oct 2022 07:56:11 +0000 Subject: [PATCH 025/141] Update metadata.json Rename any "Name" fields that still said Task Manager (I spent a while wondering why I couldn't find it as I use en_GB...). --- metadata.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/metadata.json b/metadata.json index f4361387..39d06372 100644 --- a/metadata.json +++ b/metadata.json @@ -100,7 +100,7 @@ "Name[da]": "Opgavelinje", "Name[de]": "Fensterleiste", "Name[el]": "Διαχειριστής εργασιών", - "Name[en_GB]": "Task Manager", + "Name[en_GB]": "Fancy Tasks", "Name[eo]": "Taskadministrilo", "Name[es]": "Gestor de tareas", "Name[et]": "Tegumihaldur", @@ -118,7 +118,7 @@ "Name[hsb]": "Rjadowar nadawkow", "Name[hu]": "Feladatkezelő", "Name[ia]": "Gerente de carga", - "Name[id]": "Task Manager", + "Name[id]": "Fancy Tasks", "Name[is]": "Verkefnastjóri", "Name[it]": "Gestore dei processi", "Name[ja]": "タスクマネージャ", @@ -164,7 +164,7 @@ "Name[uz]": "Vazifa boshqaruvchisi", "Name[vi]": "Trình quản lí tác vụ", "Name[wa]": "Manaedjeu des bouyes", - "Name[x-test]": "xxTask Managerxx", + "Name[x-test]": "xxFancy Tasksxx", "Name[zh_CN]": "任务管理器", "Name[zh_TW]": "含描述文字的工作管理員", "ServiceTypes": [ From dfa3234802951cf80d6ccac15877d8b659f6ef32 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Sun, 13 Nov 2022 19:40:43 -0700 Subject: [PATCH 026/141] Update README.MD Added known issues to readme --- README.MD | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.MD b/README.MD index 4b9f7928..3c88d695 100644 --- a/README.MD +++ b/README.MD @@ -30,6 +30,9 @@ Features improvements tweaks and options to the original task manager plasmoid m * Customization of number of indicators displayed - limit 10. +## Known Issues +* Does not support LTS currently! (fix me pls) + ## Pictures Colorful Tasks From 0f9000f465e49dfd3482e03bbd7a4fd84f067710 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Sun, 13 Nov 2022 19:44:37 -0700 Subject: [PATCH 027/141] Update README.MD Added To Do --- README.MD | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.MD b/README.MD index 3c88d695..b8cd21d2 100644 --- a/README.MD +++ b/README.MD @@ -33,6 +33,11 @@ Features improvements tweaks and options to the original task manager plasmoid m ## Known Issues * Does not support LTS currently! (fix me pls) +## To Do +* Fix LTS support +* Allow disabling of the plasma SVG (easy) +* Update colorize to a more clear radio button. + ## Pictures Colorful Tasks From 9fbb071ff1b1a425b97307681c4daf488522425a Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Sun, 13 Nov 2022 19:45:41 -0700 Subject: [PATCH 028/141] Update README.MD --- README.MD | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.MD b/README.MD index b8cd21d2..a66c5726 100644 --- a/README.MD +++ b/README.MD @@ -37,6 +37,8 @@ Features improvements tweaks and options to the original task manager plasmoid m * Fix LTS support * Allow disabling of the plasma SVG (easy) * Update colorize to a more clear radio button. +* Correct Metro to have *no* spacing (the multi app running indicator doesn't have a spacing in win10 and I apparently missed this) +* Allow customization of the space between indicators (may have dangerous implications) ## Pictures Colorful Tasks From 59a32238bf227dca3a64b7e355138c00d6cbc79c Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Sun, 13 Nov 2022 20:06:22 -0700 Subject: [PATCH 029/141] Update README.MD --- README.MD | 1 + 1 file changed, 1 insertion(+) diff --git a/README.MD b/README.MD index a66c5726..2ca2583e 100644 --- a/README.MD +++ b/README.MD @@ -39,6 +39,7 @@ Features improvements tweaks and options to the original task manager plasmoid m * Update colorize to a more clear radio button. * Correct Metro to have *no* spacing (the multi app running indicator doesn't have a spacing in win10 and I apparently missed this) * Allow customization of the space between indicators (may have dangerous implications) +* Allow disabling of animations ## Pictures Colorful Tasks From 6545f274375e956960db1f976edf07da76f2cb1e Mon Sep 17 00:00:00 2001 From: Alexandra Stone Date: Sun, 13 Nov 2022 20:39:35 -0700 Subject: [PATCH 030/141] Added disabling of decorations. Colorizationlater. --- contents/config/main.xml | 4 ++++ contents/ui/ConfigAppearance.qml | 7 +++++++ contents/ui/Task.qml | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/contents/config/main.xml b/contents/config/main.xml index 9cc41291..da92b9f0 100644 --- a/contents/config/main.xml +++ b/contents/config/main.xml @@ -211,6 +211,10 @@ #FFFFFF + + + + false diff --git a/contents/ui/ConfigAppearance.qml b/contents/ui/ConfigAppearance.qml index e30aa115..b1ba209d 100644 --- a/contents/ui/ConfigAppearance.qml +++ b/contents/ui/ConfigAppearance.qml @@ -37,6 +37,7 @@ Kirigami.FormLayout { property alias cfg_buttonColorizeDominant: buttonColorizeDominant.checked property alias cfg_buttonColorizeCustom: buttonColorizeCustom.color + property alias cfg_disableButtonSvg: disableButtonSvg.checked property alias cfg_overridePlasmaButtonDirection: overridePlasmaButtonDirection.checked property alias cfg_plasmaButtonDirection: plasmaButtonDirection.currentIndex @@ -97,6 +98,12 @@ Kirigami.FormLayout { Kirigami.FormData.isSection: true } + CheckBox { + id: disableButtonSvg + Kirigami.FormData.label: i18n("Plasma Button Decorations:") + text: i18n("Disable") + } + CheckBox { id: overridePlasmaButtonDirection Kirigami.FormData.label: i18n("Plasma Button Direction:") diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml index 985bd03a..cfdb4b17 100644 --- a/contents/ui/Task.qml +++ b/contents/ui/Task.qml @@ -374,7 +374,7 @@ MouseArea { rightMargin: ((inPopup || tasks.vertical) && taskList.columns > 1) ? LayoutManager.iconMargin : 0 } - imagePath: "widgets/tasks" + imagePath: plasmoid.configuration.disableButtonSvg ? "" : "widgets/tasks" enabledBorders: plasmoid.configuration.useBorders ? 1 | 2 | 4 | 8 : 0 property bool isHovered: task.highlighted && plasmoid.configuration.taskHoverEffect property string basePrefix: "normal" From 2eb145c6a52c4e58be3d901a684a7684f1cbd7b4 Mon Sep 17 00:00:00 2001 From: Alexandra Stone Date: Sun, 13 Nov 2022 20:50:36 -0700 Subject: [PATCH 031/141] Enable disabling of animations (wording?) --- contents/config/main.xml | 4 ++++ contents/ui/ConfigIndicators.qml | 13 +++++++++++++ contents/ui/Task.qml | 8 ++++---- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/contents/config/main.xml b/contents/config/main.xml index da92b9f0..83e1715c 100644 --- a/contents/config/main.xml +++ b/contents/config/main.xml @@ -136,6 +136,10 @@ 0 + + + true + 1 diff --git a/contents/ui/ConfigIndicators.qml b/contents/ui/ConfigIndicators.qml index ce2b3cc3..78ab6b4f 100644 --- a/contents/ui/ConfigIndicators.qml +++ b/contents/ui/ConfigIndicators.qml @@ -14,6 +14,7 @@ Kirigami.FormLayout { property alias cfg_indicatorsEnabled: indicatorsEnabled.currentIndex property alias cfg_groupIconEnabled: groupIconEnabled.currentIndex + property alias cfg_indicatorsAnimated: indicatorsAnimated.checked property alias cfg_indicatorLocation: indicatorLocation.currentIndex property alias cfg_indicatorReverse: indicatorReverse.checked property alias cfg_indicatorOverride: indicatorOverride.checked @@ -46,6 +47,18 @@ Kirigami.FormLayout { font: Kirigami.Theme.smallFont } + Item { + Kirigami.FormData.isSection: true + } + + CheckBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorsAnimated + Kirigami.FormData.label: i18n("Animate Indicators:") + text: i18n("Enabled") + } + + Item { Kirigami.FormData.isSection: true } diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml index cfdb4b17..082909ec 100644 --- a/contents/ui/Task.qml +++ b/contents/ui/Task.qml @@ -416,10 +416,10 @@ MouseArea { Rectangle{ id: stateRect - Behavior on height { PropertyAnimation {} } - Behavior on width { PropertyAnimation {} } - Behavior on color { PropertyAnimation {} } - Behavior on radius { PropertyAnimation {} } + Behavior on height { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } + Behavior on width { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } + Behavior on color { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } + Behavior on radius { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } readonly property color decoColor: frame.dominantColor readonly property int maxStates: plasmoid.configuration.indicatorLimit readonly property bool isFirst: index === 0 From ecaeb068090578ac30c4b7458ad2d43096783c70 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Mon, 14 Nov 2022 15:42:32 -0700 Subject: [PATCH 032/141] Update README.MD Update to do with additional usability ideas. --- README.MD | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.MD b/README.MD index 2ca2583e..5c646af0 100644 --- a/README.MD +++ b/README.MD @@ -38,8 +38,10 @@ Features improvements tweaks and options to the original task manager plasmoid m * Allow disabling of the plasma SVG (easy) * Update colorize to a more clear radio button. * Correct Metro to have *no* spacing (the multi app running indicator doesn't have a spacing in win10 and I apparently missed this) -* Allow customization of the space between indicators (may have dangerous implications) -* Allow disabling of animations +* Allow customization of the space between indicators (may have dangerous implications, required for presets) +* Allow changing of animation duration +* Change styles (Metro, Ciliora, Dashes) to presets, switch preset to custom when modifying settings. Add in Dots as a preset. +* Fix naming conventions to be more clear to users. ## Pictures Colorful Tasks From 83ca1e905b0c2c5f2155e8e182857d5169f7ee0e Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Mon, 14 Nov 2022 15:43:07 -0700 Subject: [PATCH 033/141] Update README.MD --- README.MD | 1 + 1 file changed, 1 insertion(+) diff --git a/README.MD b/README.MD index 5c646af0..09818283 100644 --- a/README.MD +++ b/README.MD @@ -42,6 +42,7 @@ Features improvements tweaks and options to the original task manager plasmoid m * Allow changing of animation duration * Change styles (Metro, Ciliora, Dashes) to presets, switch preset to custom when modifying settings. Add in Dots as a preset. * Fix naming conventions to be more clear to users. +* Translations. ## Pictures Colorful Tasks From 5a64e1ab4f396b92346f7449c0967704e0b4541c Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Fri, 3 Feb 2023 15:03:56 -0700 Subject: [PATCH 034/141] Update README.MD --- README.MD | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.MD b/README.MD index 09818283..63b9490d 100644 --- a/README.MD +++ b/README.MD @@ -1,3 +1,7 @@ +# Notice +I'm not using Linux enough to actively work on this project. If someone wants to become the maintainer of this project, let me know. Unfortunately between work and everything else I don't have the time to maintain this. I understand there's a very real desire for this to exist and be in a more usable state, but Linux also isn't quite there yet for me to attempt active development either. You can reach out to me at ideas@alexankitty.com +Thanks for your understanding. + # FancyTasks ![Fancy Tasks Icon](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/FancyTasks.png?raw=true) From f65669eee25717a077dc07b1826880b3e63f0516 Mon Sep 17 00:00:00 2001 From: Andrei Shevchuk Date: Mon, 13 Feb 2023 15:51:49 +0300 Subject: [PATCH 035/141] Add min indicators limit Fix #28 --- contents/config/main.xml | 6 +++++- contents/ui/ConfigIndicators.qml | 17 +++++++++++++---- contents/ui/Task.qml | 6 ++++-- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/contents/config/main.xml b/contents/config/main.xml index 83e1715c..65c229ff 100644 --- a/contents/config/main.xml +++ b/contents/config/main.xml @@ -152,7 +152,11 @@ 0 - + + + 1 + + 4 diff --git a/contents/ui/ConfigIndicators.qml b/contents/ui/ConfigIndicators.qml index 78ab6b4f..58a3884d 100644 --- a/contents/ui/ConfigIndicators.qml +++ b/contents/ui/ConfigIndicators.qml @@ -19,7 +19,8 @@ Kirigami.FormLayout { property alias cfg_indicatorReverse: indicatorReverse.checked property alias cfg_indicatorOverride: indicatorOverride.checked property alias cfg_indicatorStyle: indicatorStyle.currentIndex - property alias cfg_indicatorLimit: indicatorLimit.value + property alias cfg_indicatorMinLimit: indicatorMinLimit.value + property alias cfg_indicatorMaxLimit: indicatorMaxLimit.value property alias cfg_indicatorDesaturate: indicatorDesaturate.checked property alias cfg_indicatorGrow: indicatorGrow.checked property alias cfg_indicatorGrowFactor: indicatorGrowFactor.value @@ -112,8 +113,16 @@ Kirigami.FormLayout { SpinBox { enabled: indicatorsEnabled.currentIndex - id: indicatorLimit - Kirigami.FormData.label: i18n("Indicator Limit:") + id: indicatorMinLimit + Kirigami.FormData.label: i18n("Indicator Min Limit:") + from: 1 + to: 10 + } + + SpinBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorMaxLimit + Kirigami.FormData.label: i18n("Indicator Max Limit:") from: 1 to: 10 } @@ -221,4 +230,4 @@ Kirigami.FormLayout { Item { Kirigami.FormData.isSection: true } -} \ No newline at end of file +} diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml index 082909ec..277455c3 100644 --- a/contents/ui/Task.qml +++ b/contents/ui/Task.qml @@ -401,6 +401,8 @@ MouseArea { if(!plasmoid.configuration.indicatorsEnabled) return 0; + if(task.childCount < plasmoid.configuration.indicatorMinLimit) + return 0; if(task.parent.toString().includes('QQuickItem'))//Target only the main task items. return 0; /*for(var key in task) { @@ -412,7 +414,7 @@ MouseArea { } return Math.min((task.childCount === 0) ? 1 : task.childCount, maxStates); } - readonly property int maxStates: plasmoid.configuration.indicatorLimit + readonly property int maxStates: plasmoid.configuration.indicatorMaxLimit Rectangle{ id: stateRect @@ -421,7 +423,7 @@ MouseArea { Behavior on color { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } Behavior on radius { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } readonly property color decoColor: frame.dominantColor - readonly property int maxStates: plasmoid.configuration.indicatorLimit + readonly property int maxStates: plasmoid.configuration.indicatorMaxLimit readonly property bool isFirst: index === 0 readonly property int adjust: plasmoid.configuration.indicatorShrink readonly property int indicatorLength: plasmoid.configuration.indicatorLength From d515bee26c638a5404eac0c1074f430ab9c71ca1 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Tue, 8 Aug 2023 15:36:15 -0600 Subject: [PATCH 036/141] Create necessary parent directories before copy --- install.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/install.sh b/install.sh index d8bbc858..45eb1d6f 100755 --- a/install.sh +++ b/install.sh @@ -1,4 +1,5 @@ #!/bin/sh SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) kpackagetool5 -i $SCRIPT_DIR -cp ./FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png \ No newline at end of file +mkdir -p ~/.local/share/icons/hicolor/256x256/apps/ +cp ./FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png From d5f479ae3fc3d3a6c19cd1d960225568642b30db Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Sat, 12 Aug 2023 19:52:19 -0600 Subject: [PATCH 037/141] Change the indicator minimum to 0 instead of 1 --- contents/ui/ConfigIndicators.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/ui/ConfigIndicators.qml b/contents/ui/ConfigIndicators.qml index 58a3884d..028ee5b4 100644 --- a/contents/ui/ConfigIndicators.qml +++ b/contents/ui/ConfigIndicators.qml @@ -115,7 +115,7 @@ Kirigami.FormLayout { enabled: indicatorsEnabled.currentIndex id: indicatorMinLimit Kirigami.FormData.label: i18n("Indicator Min Limit:") - from: 1 + from: 0 to: 10 } From a02c9c66a9bc7f8a7c813534fcafc6d58927dd42 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Tue, 22 Aug 2023 18:22:45 -0600 Subject: [PATCH 038/141] Fix color bugs, refactor color code --- contents/ui/Task.qml | 373 +++++++++++++++++++++---------------------- 1 file changed, 186 insertions(+), 187 deletions(-) diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml index 277455c3..25cb56d7 100644 --- a/contents/ui/Task.qml +++ b/contents/ui/Task.qml @@ -357,14 +357,14 @@ MouseArea { Component.onCompleted: timer.start() } } + PlasmaCore.FrameSvgItem { id: frame - property color dominantColor: imageColors.dominant Kirigami.ImageColors { id: imageColors source: model.decoration } - + property color dominantColor: imageColors.dominant anchors { fill: parent @@ -379,192 +379,127 @@ MouseArea { property bool isHovered: task.highlighted && plasmoid.configuration.taskHoverEffect property string basePrefix: "normal" prefix: isHovered ? TaskTools.taskPrefixHovered(basePrefix) : TaskTools.taskPrefix(basePrefix) + visible: plasmoid.configuration.buttonColorize ? false : true + } - property Colorize colorOverride: colorOverride - Colorize { - id: colorOverride - anchors.fill: frame - source: parent - hue: hexToHSL(plasmoid.configuration.buttonColorizeDominant ? imageColors.dominant : plasmoid.configuration.buttonColorizeCustom).h - lightness: frame.isHovered ? hexToHSL(plasmoid.configuration.buttonColorizeDominant ? imageColors.dominant : plasmoid.configuration.buttonColorizeCustom).l - 0.5 : hexToHSL(plasmoid.configuration.buttonColorizeDominant ? imageColors.dominant : plasmoid.configuration.buttonColorizeCustom).l - 0.6 - saturation: hexToHSL(plasmoid.configuration.buttonColorizeDominant ? imageColors.dominant : plasmoid.configuration.buttonColorizeCustom).s - visible: plasmoid.configuration.buttonColorize ? frame.isHovered ? true : false : false - } - - Flow { - id: indicator - flow: Flow.LeftToRight - spacing: PlasmaCore.Units.smallSpacing - Repeater { - - model: { - - if(!plasmoid.configuration.indicatorsEnabled) + Flow { + id: indicator + flow: Flow.LeftToRight + spacing: PlasmaCore.Units.smallSpacing + Repeater { + + model: { + + if(!plasmoid.configuration.indicatorsEnabled) + return 0; + if(task.childCount < plasmoid.configuration.indicatorMinLimit) + return 0; + if(task.parent.toString().includes('QQuickItem'))//Target only the main task items. + return 0; + /*for(var key in task) { + console.log(key) + console.log(task[key]) + }*/ //Kept for debugging + if(task.state === 'launcher') { return 0; - if(task.childCount < plasmoid.configuration.indicatorMinLimit) - return 0; - if(task.parent.toString().includes('QQuickItem'))//Target only the main task items. - return 0; - /*for(var key in task) { - console.log(key) - console.log(task[key]) - }*/ //Kept for debugging - if(task.state === 'launcher') { - return 0; - } - return Math.min((task.childCount === 0) ? 1 : task.childCount, maxStates); } + return Math.min((task.childCount === 0) ? 1 : task.childCount, maxStates); + } + readonly property int maxStates: plasmoid.configuration.indicatorMaxLimit + + Rectangle{ + id: stateRect + Behavior on height { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } + Behavior on width { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } + Behavior on color { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } + Behavior on radius { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } + readonly property color decoColor: frame.dominantColor readonly property int maxStates: plasmoid.configuration.indicatorMaxLimit - - Rectangle{ - id: stateRect - Behavior on height { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } - Behavior on width { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } - Behavior on color { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } - Behavior on radius { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } - readonly property color decoColor: frame.dominantColor - readonly property int maxStates: plasmoid.configuration.indicatorMaxLimit - readonly property bool isFirst: index === 0 - readonly property int adjust: plasmoid.configuration.indicatorShrink - readonly property int indicatorLength: plasmoid.configuration.indicatorLength - readonly property int spacing: PlasmaCore.Units.smallSpacing - readonly property bool isVertical: { - if(plasmoid.formFactor === PlasmaCore.Types.Vertical && !plasmoid.configuration.indicatorOverride) - return true; - if(plasmoid.formFactor == PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 1 || plasmoid.configuration.indicatorLocation === 2) - return true; - if(plasmoid.configuration.indicatorLocation === 1 || plasmoid.configuration.indicatorLocation === 2) - return true; - else{ - return false; - } + readonly property bool isFirst: index === 0 + readonly property int adjust: plasmoid.configuration.indicatorShrink + readonly property int indicatorLength: plasmoid.configuration.indicatorLength + readonly property int spacing: PlasmaCore.Units.smallSpacing + readonly property bool isVertical: { + if(plasmoid.formFactor === PlasmaCore.Types.Vertical && !plasmoid.configuration.indicatorOverride) + return true; + if(plasmoid.formFactor == PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 1 || plasmoid.configuration.indicatorLocation === 2) + return true; + if(plasmoid.configuration.indicatorLocation === 1 || plasmoid.configuration.indicatorLocation === 2) + return true; + else{ + return false; } - readonly property var computedVar: { - var height; - var width; - var colorCalc; - var colorEval = '#FFFFFF'; - var parentSize = !isVertical ? frame.width : frame.height; - var indicatorComputedSize; - var adjustment = isFirst ? adjust : 0 - var parentSpacingAdjust = task.childCount >= 1 && maxStates >= 2 ? (spacing * 2.5) : 0 //Spacing fix for multiple items - if(plasmoid.configuration.indicatorDominantColor){ - colorEval = decoColor - } - if(plasmoid.configuration.indicatorAccentColor){ - colorEval = PlasmaCore.Theme.highlightColor - } - else if(!plasmoid.configuration.indicatorDominantColor && !plasmoid.configuration.indicatorAccentColor){ - colorEval = plasmoid.configuration.indicatorCustomColor - } - if(isFirst){//compute the size - var growFactor = plasmoid.configuration.indicatorGrowFactor / 100 - if(plasmoid.configuration.indicatorGrow && task.state === "minimized") { - var mainSize = indicatorLength * growFactor; - } - else{ - var mainSize = (parentSize + parentSpacingAdjust); - } - switch(plasmoid.configuration.indicatorStyle){ - case 0: - indicatorComputedSize = mainSize - (Math.min(task.childCount, maxStates === 1 ? 0 : maxStates) * (spacing + indicatorLength)) - adjust - break - case 1: - indicatorComputedSize = mainSize - (Math.min(task.childCount, maxStates === 1 ? 0 : maxStates) * (spacing + indicatorLength)) - adjust - break - case 2: - indicatorComputedSize = plasmoid.configuration.indicatorGrow && task.state !== "minimized" ? indicatorLength * growFactor : indicatorLength - break - default: - break - } - } - else { - indicatorComputedSize = indicatorLength - } - if(!isVertical){ - width = indicatorComputedSize; - height = plasmoid.configuration.indicatorSize + } + readonly property var computedVar: { + var height; + var width; + var colorCalc; + var colorEval = '#FFFFFF'; + var parentSize = !isVertical ? frame.width : frame.height; + var indicatorComputedSize; + var adjustment = isFirst ? adjust : 0 + var parentSpacingAdjust = task.childCount >= 1 && maxStates >= 2 ? (spacing * 2.5) : 0 //Spacing fix for multiple items + if(plasmoid.configuration.indicatorDominantColor){ + colorEval = decoColor + } + if(plasmoid.configuration.indicatorAccentColor){ + colorEval = PlasmaCore.Theme.highlightColor + } + else if(!plasmoid.configuration.indicatorDominantColor && !plasmoid.configuration.indicatorAccentColor){ + colorEval = plasmoid.configuration.indicatorCustomColor + } + if(isFirst){//compute the size + var growFactor = plasmoid.configuration.indicatorGrowFactor / 100 + if(plasmoid.configuration.indicatorGrow && task.state === "minimized") { + var mainSize = indicatorLength * growFactor; } else{ - width = plasmoid.configuration.indicatorSize - height = indicatorComputedSize + var mainSize = (parentSize + parentSpacingAdjust); } - if(plasmoid.configuration.indicatorDesaturate && task.state === "minimized") { - var colorHSL = hexToHSL(colorEval) - colorCalc = Qt.hsla(colorHSL.h, 0.2, 0.6, 1) + switch(plasmoid.configuration.indicatorStyle){ + case 0: + indicatorComputedSize = mainSize - (Math.min(task.childCount, maxStates === 1 ? 0 : maxStates) * (spacing + indicatorLength)) - adjust + break + case 1: + indicatorComputedSize = mainSize - (Math.min(task.childCount, maxStates === 1 ? 0 : maxStates) * (spacing + indicatorLength)) - adjust + break + case 2: + indicatorComputedSize = plasmoid.configuration.indicatorGrow && task.state !== "minimized" ? indicatorLength * growFactor : indicatorLength + break + default: + break } - else if(!isFirst && plasmoid.configuration.indicatorStyle === 0 && task.state !== "minimized") {//Metro specific handling - colorCalc = Qt.darker(colorEval, 1.2) - } - else { - colorCalc = colorEval - } - return {height: height, width: width, colorCalc: colorCalc} } - width: computedVar.width - height: computedVar.height - color: computedVar.colorCalc - radius: (Math.max(width, height) / Math.min(width, height)) * (plasmoid.configuration.indicatorRadius / 100) - } - } - } - - PlasmaCore.ToolTipArea { - id: toolTipArea - - anchors.fill: parent - location: plasmoid.location - - enabled: plasmoid.configuration.showToolTips && !inPopup && !tasks.groupDialog && (tasks.toolTipOpenedByClick === task || tasks.toolTipOpenedByClick === null) - interactive: model.IsWindow === true || mainItem.hasPlayer - - // when the mouse leaves the tooltip area, a timer to hide is set for (timeout / 20) ms - // see plasma-framework/src/declarativeimports/core/tooltipdialog.cpp function dismiss() - // to compensate for that we multiply by 20 here, to get an effective leave timeout of 2s. - timeout: (tasks.toolTipOpenedByClick === task) ? 2000*20 : 4000 - - mainItem: (model.IsWindow === true) ? openWindowToolTipDelegate : pinnedAppToolTipDelegate - - onToolTipVisibleChanged: { - if (!toolTipVisible) { - tasks.toolTipOpenedByClick = null; - } - } - - onContainsMouseChanged: if (containsMouse) { - updateMainItemBindings(); - } - - // Will also be called in activateTaskAtIndex(index) - function updateMainItemBindings() { - if (tasks.toolTipOpenedByClick !== null && tasks.toolTipOpenedByClick !== task) { - return; + else { + indicatorComputedSize = indicatorLength + } + if(!isVertical){ + width = indicatorComputedSize; + height = plasmoid.configuration.indicatorSize + } + else{ + width = plasmoid.configuration.indicatorSize + height = indicatorComputedSize + } + if(plasmoid.configuration.indicatorDesaturate && task.state === "minimized") { + var colorHSL = hexToHSL(colorEval) + colorCalc = Qt.hsla(colorHSL.h, 0.2, 0.6, 1) + } + else if(!isFirst && plasmoid.configuration.indicatorStyle === 0 && task.state !== "minimized") {//Metro specific handling + colorCalc = Qt.darker(colorEval, 1.2) + } + else { + colorCalc = colorEval + } + return {height: height, width: width, colorCalc: colorCalc} } - - mainItem.parentTask = task; - mainItem.rootIndex = tasksModel.makeModelIndex(itemIndex, -1); - - mainItem.appName = Qt.binding(() => model.AppName); - mainItem.pidParent = Qt.binding(() => model.AppPid !== undefined ? model.AppPid : 0); - mainItem.windows = Qt.binding(() => model.WinIdList); - mainItem.isGroup = Qt.binding(() => model.IsGroupParent === true); - mainItem.icon = Qt.binding(() => model.decoration); - mainItem.launcherUrl = Qt.binding(() => model.LauncherUrlWithoutIcon); - mainItem.isLauncher = Qt.binding(() => model.IsLauncher === true); - mainItem.isMinimizedParent = Qt.binding(() => model.IsMinimized === true); - mainItem.displayParent = Qt.binding(() => model.display); - mainItem.genericName = Qt.binding(() => model.GenericName); - mainItem.virtualDesktopParent = Qt.binding(() => - (model.VirtualDesktops !== undefined && model.VirtualDesktops.length > 0) ? model.VirtualDesktops : [0]); - mainItem.isOnAllVirtualDesktopsParent = Qt.binding(() => model.IsOnAllVirtualDesktops === true); - mainItem.activitiesParent = Qt.binding(() => model.Activities); - - mainItem.smartLauncherCountVisible = Qt.binding(() => task.smartLauncherItem && task.smartLauncherItem.countVisible); - mainItem.smartLauncherCount = Qt.binding(() => mainItem.smartLauncherCountVisible ? task.smartLauncherItem.count : 0); - } + width: computedVar.width + height: computedVar.height + color: computedVar.colorCalc + radius: (Math.max(width, height) / Math.min(width, height)) * (plasmoid.configuration.indicatorRadius / 100) + } } - + states:[ State {//safety case - use bottom when not override name: "floating-fallback" @@ -644,8 +579,8 @@ MouseArea { State { name: "bottom" when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 0) - || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.BottomEdge && !plasmoid.configuration.indicatorReverse) - || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.TopEdge && plasmoid.configuration.indicatorReverse) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.BottomEdge && !plasmoid.configuration.indicatorReverse) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.TopEdge && plasmoid.configuration.indicatorReverse) AnchorChanges { target: indicator @@ -661,9 +596,9 @@ MouseArea { State { name: "left" when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 1) - || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.LeftEdge && !plasmoid.configuration.indicatorReverse) - || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.RightEdge && plasmoid.configuration.indicatorReverse) - + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.LeftEdge && !plasmoid.configuration.indicatorReverse) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.RightEdge && plasmoid.configuration.indicatorReverse) + AnchorChanges { target: indicator @@ -679,8 +614,8 @@ MouseArea { State { name: "right" when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 2) - || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.RightEdge && !plasmoid.configuration.indicatorReverse) - || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.LeftEdge && plasmoid.configuration.indicatorReverse) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.RightEdge && !plasmoid.configuration.indicatorReverse) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.LeftEdge && plasmoid.configuration.indicatorReverse) AnchorChanges { target: indicator @@ -696,8 +631,8 @@ MouseArea { State { name: "top" when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 3) - || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.TopEdge && !plasmoid.configuration.indicatorReverse) - || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.BottomEdge && plasmoid.configuration.indicatorReverse) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.TopEdge && !plasmoid.configuration.indicatorReverse) + || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.BottomEdge && plasmoid.configuration.indicatorReverse) AnchorChanges { target: indicator @@ -711,9 +646,73 @@ MouseArea { } } ] - } + PlasmaCore.ToolTipArea { + id: toolTipArea + + anchors.fill: parent + location: plasmoid.location + + enabled: plasmoid.configuration.showToolTips && !inPopup && !tasks.groupDialog && (tasks.toolTipOpenedByClick === task || tasks.toolTipOpenedByClick === null) + interactive: model.IsWindow === true || mainItem.hasPlayer + + // when the mouse leaves the tooltip area, a timer to hide is set for (timeout / 20) ms + // see plasma-framework/src/declarativeimports/core/tooltipdialog.cpp function dismiss() + // to compensate for that we multiply by 20 here, to get an effective leave timeout of 2s. + timeout: (tasks.toolTipOpenedByClick === task) ? 2000*20 : 4000 + + mainItem: (model.IsWindow === true) ? openWindowToolTipDelegate : pinnedAppToolTipDelegate + + onToolTipVisibleChanged: { + if (!toolTipVisible) { + tasks.toolTipOpenedByClick = null; + } + } + + onContainsMouseChanged: if (containsMouse) { + updateMainItemBindings(); + } + + // Will also be called in activateTaskAtIndex(index) + function updateMainItemBindings() { + if (tasks.toolTipOpenedByClick !== null && tasks.toolTipOpenedByClick !== task) { + return; + } + + mainItem.parentTask = task; + mainItem.rootIndex = tasksModel.makeModelIndex(itemIndex, -1); + + mainItem.appName = Qt.binding(() => model.AppName); + mainItem.pidParent = Qt.binding(() => model.AppPid !== undefined ? model.AppPid : 0); + mainItem.windows = Qt.binding(() => model.WinIdList); + mainItem.isGroup = Qt.binding(() => model.IsGroupParent === true); + mainItem.icon = Qt.binding(() => model.decoration); + mainItem.launcherUrl = Qt.binding(() => model.LauncherUrlWithoutIcon); + mainItem.isLauncher = Qt.binding(() => model.IsLauncher === true); + mainItem.isMinimizedParent = Qt.binding(() => model.IsMinimized === true); + mainItem.displayParent = Qt.binding(() => model.display); + mainItem.genericName = Qt.binding(() => model.GenericName); + mainItem.virtualDesktopParent = Qt.binding(() => + (model.VirtualDesktops !== undefined && model.VirtualDesktops.length > 0) ? model.VirtualDesktops : [0]); + mainItem.isOnAllVirtualDesktopsParent = Qt.binding(() => model.IsOnAllVirtualDesktops === true); + mainItem.activitiesParent = Qt.binding(() => model.Activities); + + mainItem.smartLauncherCountVisible = Qt.binding(() => task.smartLauncherItem && task.smartLauncherItem.countVisible); + mainItem.smartLauncherCount = Qt.binding(() => mainItem.smartLauncherCountVisible ? task.smartLauncherItem.count : 0); + } + } + + ColorOverlay { + id: colorOverride + anchors.fill: frame + source: frame + /*hue: hexToHSL(plasmoid.configuration.buttonColorizeDominant ? frame.dominantColor : plasmoid.configuration.buttonColorizeCustom).h + lightness: frame.isHovered ? hexToHSL(plasmoid.configuration.buttonColorizeDominant ? frame.dominantColor : plasmoid.configuration.buttonColorizeCustom).l - 0.5 : hexToHSL(plasmoid.configuration.buttonColorizeDominant ? imageColors.dominant : plasmoid.configuration.buttonColorizeCustom).l - 1 + saturation: hexToHSL(plasmoid.configuration.buttonColorizeDominant ? frame.dominantColor : plasmoid.configuration.buttonColorizeCustom).s*/ + color: plasmoid.configuration.buttonColorizeDominant ? frame.dominantColor : plasmoid.configuration.buttonColorizeCustom + visible: plasmoid.configuration.buttonColorize ? true : false + } Loader { @@ -901,7 +900,7 @@ MouseArea { PropertyChanges { target: colorOverride visible: plasmoid.configuration.buttonColorize ? frame.isHovered ? true : false : false - lightness: hexToHSL(plasmoid.configuration.buttonColorizeDominant ? imageColors.dominant : plasmoid.configuration.buttonColorizeCustom).l - 0.8 + //lightness: hexToHSL(plasmoid.configuration.buttonColorizeDominant ? imageColors.dominant : plasmoid.configuration.buttonColorizeCustom).l - 0.8 } }, State { From 823b3088233709c548291b5ba8cc306cef23e086 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Tue, 22 Aug 2023 19:18:06 -0600 Subject: [PATCH 039/141] Show decoration when minimized and colorized --- contents/ui/Task.qml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml index 25cb56d7..cd6cdfb2 100644 --- a/contents/ui/Task.qml +++ b/contents/ui/Task.qml @@ -897,11 +897,6 @@ MouseArea { target: frame basePrefix: "minimized" } - PropertyChanges { - target: colorOverride - visible: plasmoid.configuration.buttonColorize ? frame.isHovered ? true : false : false - //lightness: hexToHSL(plasmoid.configuration.buttonColorizeDominant ? imageColors.dominant : plasmoid.configuration.buttonColorizeCustom).l - 0.8 - } }, State { name: "active" From 26c406759cfa1fe44168fb264a63b9840da04357 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Tue, 22 Aug 2023 20:20:11 -0600 Subject: [PATCH 040/141] Colorize inactive setting --- contents/config/main.xml | 4 ++++ contents/ui/ConfigAppearance.qml | 9 +++++++++ contents/ui/Task.qml | 24 ++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/contents/config/main.xml b/contents/config/main.xml index 65c229ff..a2191c7b 100644 --- a/contents/config/main.xml +++ b/contents/config/main.xml @@ -212,6 +212,10 @@ false + + + false + true diff --git a/contents/ui/ConfigAppearance.qml b/contents/ui/ConfigAppearance.qml index b1ba209d..997dd948 100644 --- a/contents/ui/ConfigAppearance.qml +++ b/contents/ui/ConfigAppearance.qml @@ -34,6 +34,7 @@ Kirigami.FormLayout { property alias cfg_taskSpacingSize: taskSpacingSize.value property alias cfg_buttonColorize: buttonColorize.checked + property alias cfg_buttonColorizeInactive: buttonColorizeInactive.checked property alias cfg_buttonColorizeDominant: buttonColorizeDominant.checked property alias cfg_buttonColorizeCustom: buttonColorizeCustom.color @@ -80,6 +81,14 @@ Kirigami.FormLayout { text: i18n("Colorize buttons") } + RowLayout { + Item { implicitWidth: Kirigami.Units.gridUnit } + CheckBox { + id: buttonColorizeInactive + text: i18n("Colorize inactive buttons") + } + } + CheckBox { enabled: buttonColorize.checked id: buttonColorizeDominant diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml index cd6cdfb2..95b2d9e9 100644 --- a/contents/ui/Task.qml +++ b/contents/ui/Task.qml @@ -910,6 +910,30 @@ MouseArea { target: colorOverride visible: plasmoid.configuration.buttonColorize ? true : false } + }, + State { + name: "inactive" + when: model.IsActive === false && !frame.isHovered + PropertyChanges { + target: colorOverride + visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? true : false + } + PropertyChanges { + target: frame + visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? false : true + } + }, + State { + name: "hover" + when: frame.isHovered + PropertyChanges { + target: colorOverride + visible: plasmoid.configuration.buttonColorize ? true : false + } + PropertyChanges { + target: frame + visible: plasmoid.configuration.buttonColorize ? false : true + } } ] From b0c205fc5d85831368a7740b593ac7475278a856 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Tue, 22 Aug 2023 21:06:41 -0600 Subject: [PATCH 041/141] Make audio frame follow colorize if applicable --- contents/ui/AudioStream.qml | 14 +++++++++++++- contents/ui/Task.qml | 10 ++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/contents/ui/AudioStream.qml b/contents/ui/AudioStream.qml index 41bfd135..318e1289 100644 --- a/contents/ui/AudioStream.qml +++ b/contents/ui/AudioStream.qml @@ -7,8 +7,11 @@ import QtQuick 2.15 import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.kirigami 2.20 as Kirigami +import QtGraphicalEffects 1.15 MouseArea { + property string dominantIconColor id: audioStreamIconBox hoverEnabled: true onClicked: toggleMuted() @@ -80,12 +83,21 @@ MouseArea { visible: opacity > 0 PlasmaCore.FrameSvgItem { + id: audioStreamFrame anchors.fill: audioStreamIcon - visible: parent.containsMouse + visible: parent.containsMouse && !plasmoid.configuration.buttonColorize ? true : false imagePath: "widgets/viewitem" prefix: "hover" } + ColorOverlay { + id: colorOverrideAudio + anchors.fill: audioStreamFrame + source: audioStreamFrame + color: plasmoid.configuration.buttonColorizeDominant ? dominantIconColor : plasmoid.configuration.buttonColorizeCustom + visible: parent.containsMouse && plasmoid.configuration.buttonColorize ? true : false + } + PlasmaCore.Svg { id: audioSvg imagePath: "icons/audio" diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml index 95b2d9e9..afa49262 100644 --- a/contents/ui/Task.qml +++ b/contents/ui/Task.qml @@ -16,7 +16,6 @@ import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet import QtQuick.Layouts 1.3 - import QtGraphicalEffects 1.15 import "code/layout.js" as LayoutManager @@ -707,9 +706,6 @@ MouseArea { id: colorOverride anchors.fill: frame source: frame - /*hue: hexToHSL(plasmoid.configuration.buttonColorizeDominant ? frame.dominantColor : plasmoid.configuration.buttonColorizeCustom).h - lightness: frame.isHovered ? hexToHSL(plasmoid.configuration.buttonColorizeDominant ? frame.dominantColor : plasmoid.configuration.buttonColorizeCustom).l - 0.5 : hexToHSL(plasmoid.configuration.buttonColorizeDominant ? imageColors.dominant : plasmoid.configuration.buttonColorizeCustom).l - 1 - saturation: hexToHSL(plasmoid.configuration.buttonColorizeDominant ? frame.dominantColor : plasmoid.configuration.buttonColorizeCustom).s*/ color: plasmoid.configuration.buttonColorizeDominant ? frame.dominantColor : plasmoid.configuration.buttonColorizeCustom visible: plasmoid.configuration.buttonColorize ? true : false } @@ -822,6 +818,12 @@ MouseArea { width: Math.min(Math.min(iconBox.width, iconBox.height) * 0.4, PlasmaCore.Units.iconSizes.smallMedium) height: width + Binding { + target: audioStreamIconLoader.item + property: "dominantIconColor" + value: frame.dominantColor + } + anchors { right: frame.right top: frame.top From e1cac098127da28ad62104a3b71a7df8476fc884 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Tue, 22 Aug 2023 21:11:08 -0600 Subject: [PATCH 042/141] Fix minimize when colorize inactive --- contents/ui/Task.qml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml index afa49262..2ab06dd7 100644 --- a/contents/ui/Task.qml +++ b/contents/ui/Task.qml @@ -893,11 +893,16 @@ MouseArea { }, State { name: "minimized" - when: model.IsMinimized === true + when: model.IsMinimized === true && !frame.isHovered PropertyChanges { target: frame basePrefix: "minimized" + visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? false : true + } + PropertyChanges { + target: colorOverride + visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? true : false } }, State { From a802b9b7915821876755139efdbd9b9f7d13e2c3 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Tue, 22 Aug 2023 23:14:35 -0600 Subject: [PATCH 043/141] Make colorize option clearer --- contents/ui/ConfigAppearance.qml | 33 +++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/contents/ui/ConfigAppearance.qml b/contents/ui/ConfigAppearance.qml index 997dd948..ba4d0588 100644 --- a/contents/ui/ConfigAppearance.qml +++ b/contents/ui/ConfigAppearance.qml @@ -76,31 +76,46 @@ Kirigami.FormLayout { Kirigami.FormData.isSection: true } - CheckBox { - id: buttonColorize - text: i18n("Colorize buttons") + ButtonGroup { + id: colorizeButtonGroup } - RowLayout { - Item { implicitWidth: Kirigami.Units.gridUnit } - CheckBox { - id: buttonColorizeInactive - text: i18n("Colorize inactive buttons") - } + RadioButton { + Kirigami.FormData.label: i18n("Button Colors:") + checked: !buttonColorize.checked + text: i18n("Using Plasma Style/Accent") + ButtonGroup.group: colorizeButtonGroup + } + + RadioButton { + id: buttonColorize + checked: plasmoid.configuration.buttonColorize === true + text: i18n("Using Color Overlay") + ButtonGroup.group: colorizeButtonGroup } CheckBox { enabled: buttonColorize.checked id: buttonColorizeDominant text: i18n("Use dominant icon color") + visible: buttonColorize.checked } + + KQControls.ColorButton { Layout.leftMargin: Kirigami.Units.GridUnit enabled: buttonColorize.checked & !buttonColorizeDominant.checked id: buttonColorizeCustom Kirigami.FormData.label: i18n("Custom Color:") showAlphaChannel: true + visible: buttonColorize.checked && !buttonColorizeDominant.checked + } + + CheckBox { + id: buttonColorizeInactive + text: i18n("Colorize inactive buttons") + visible: buttonColorize.checked } Item { From ae6d810b50ba1bf63a04e10abe262e71ac90a916 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Tue, 22 Aug 2023 23:56:25 -0600 Subject: [PATCH 044/141] Move color overlay, tweak desaturation --- contents/ui/Task.qml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/contents/ui/Task.qml b/contents/ui/Task.qml index 2ab06dd7..fc9b65a0 100644 --- a/contents/ui/Task.qml +++ b/contents/ui/Task.qml @@ -381,6 +381,14 @@ MouseArea { visible: plasmoid.configuration.buttonColorize ? false : true } + ColorOverlay { + id: colorOverride + anchors.fill: frame + source: frame + color: plasmoid.configuration.buttonColorizeDominant ? frame.dominantColor : plasmoid.configuration.buttonColorizeCustom + visible: plasmoid.configuration.buttonColorize ? true : false + } + Flow { id: indicator flow: Flow.LeftToRight @@ -482,7 +490,7 @@ MouseArea { } if(plasmoid.configuration.indicatorDesaturate && task.state === "minimized") { var colorHSL = hexToHSL(colorEval) - colorCalc = Qt.hsla(colorHSL.h, 0.2, 0.6, 1) + colorCalc = Qt.hsla(colorHSL.h, 0.2, colorHSL.l, 1) } else if(!isFirst && plasmoid.configuration.indicatorStyle === 0 && task.state !== "minimized") {//Metro specific handling colorCalc = Qt.darker(colorEval, 1.2) @@ -702,13 +710,7 @@ MouseArea { } } - ColorOverlay { - id: colorOverride - anchors.fill: frame - source: frame - color: plasmoid.configuration.buttonColorizeDominant ? frame.dominantColor : plasmoid.configuration.buttonColorizeCustom - visible: plasmoid.configuration.buttonColorize ? true : false - } + Loader { From e838c2f5f968653284750de0b8550ac6b290581a Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Wed, 23 Aug 2023 08:43:35 -0600 Subject: [PATCH 045/141] Update To Do list --- README.MD | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.MD b/README.MD index 63b9490d..5886734d 100644 --- a/README.MD +++ b/README.MD @@ -39,11 +39,9 @@ Features improvements tweaks and options to the original task manager plasmoid m ## To Do * Fix LTS support -* Allow disabling of the plasma SVG (easy) -* Update colorize to a more clear radio button. * Correct Metro to have *no* spacing (the multi app running indicator doesn't have a spacing in win10 and I apparently missed this) * Allow customization of the space between indicators (may have dangerous implications, required for presets) -* Allow changing of animation duration +* Allow changing of animation duration, and possibly animating of button color and frame transitions. * Change styles (Metro, Ciliora, Dashes) to presets, switch preset to custom when modifying settings. Add in Dots as a preset. * Fix naming conventions to be more clear to users. * Translations. From cdba0767a22aa7392ef59886e4d94ae090387e3c Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Wed, 23 Aug 2023 08:58:25 -0600 Subject: [PATCH 046/141] fix typo --- README.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.MD b/README.MD index 5886734d..4c210436 100644 --- a/README.MD +++ b/README.MD @@ -9,7 +9,7 @@ Thanks for your understanding. ## Installing 1. Clone this repository with the following command `git clone https://github.com/alexankitty/FancyTasks` -2. CD into the foloder and run the script `install.sh`, you may need to chmod +x or prepend your shell before the script in order to run it +2. CD into the folder and run the script `install.sh`, you may need to chmod +x or prepend your shell before the script in order to run it 3. Right click your panel, click add widgets and search for fancy tasks. 4. Right click the new task panel and click Configure Fancy Tasks... - everything you will want to configure to enable the new features will be in there. Default features are based on the KDE's team existing vision. From 23423051d13480f81fd64bbb324802291b3ec198 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Wed, 23 Aug 2023 08:59:46 -0600 Subject: [PATCH 047/141] Change notice --- README.MD | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.MD b/README.MD index 4c210436..4b4887f6 100644 --- a/README.MD +++ b/README.MD @@ -1,6 +1,5 @@ # Notice -I'm not using Linux enough to actively work on this project. If someone wants to become the maintainer of this project, let me know. Unfortunately between work and everything else I don't have the time to maintain this. I understand there's a very real desire for this to exist and be in a more usable state, but Linux also isn't quite there yet for me to attempt active development either. You can reach out to me at ideas@alexankitty.com -Thanks for your understanding. +Development of this project has more or less resumed. Help is always wanted and appreciated, however. # FancyTasks From 141348d72e15f4bad0c00209b0f6cea71477fe6e Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Wed, 23 Aug 2023 09:13:12 -0600 Subject: [PATCH 048/141] Add dependency --- README.MD | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.MD b/README.MD index 4b4887f6..2f789168 100644 --- a/README.MD +++ b/README.MD @@ -7,6 +7,8 @@ Development of this project has more or less resumed. Help is always wanted and ## Installing +If your distro does not include kirigami2, install it now. It's required for the settings, and used for the dominant icon color effect. + 1. Clone this repository with the following command `git clone https://github.com/alexankitty/FancyTasks` 2. CD into the folder and run the script `install.sh`, you may need to chmod +x or prepend your shell before the script in order to run it 3. Right click your panel, click add widgets and search for fancy tasks. From a2ce214142daa9007c0316239b1649c74a0527d8 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 23 Aug 2023 10:31:48 -0600 Subject: [PATCH 049/141] Update metadata, move to package folder --- metadata.json | 12 ++++++------ {contents => package/contents}/config/config.qml | 0 {contents => package/contents}/config/main.xml | 0 {contents => package/contents}/ui/AudioStream.qml | 0 {contents => package/contents}/ui/Badge.qml | 0 .../contents}/ui/ConfigAppearance.qml | 0 {contents => package/contents}/ui/ConfigBehavior.qml | 0 .../contents}/ui/ConfigIndicators.qml | 0 {contents => package/contents}/ui/ContextMenu.qml | 0 {contents => package/contents}/ui/GroupDialog.qml | 0 .../contents}/ui/GroupExpanderOverlay.qml | 0 {contents => package/contents}/ui/MouseHandler.qml | 0 .../contents}/ui/PipeWireThumbnail.qml | 0 .../contents}/ui/PlayerController.qml | 0 {contents => package/contents}/ui/PulseAudio.qml | 0 .../contents}/ui/ScrollableTextWrapper.qml | 0 {contents => package/contents}/ui/Task.qml | 0 .../contents}/ui/TaskBadgeOverlay.qml | 0 {contents => package/contents}/ui/TaskList.qml | 0 .../contents}/ui/TaskProgressOverlay.qml | 0 .../contents}/ui/ToolTipDelegate.qml | 0 .../contents}/ui/ToolTipInstance.qml | 0 .../contents}/ui/ToolTipWindowMouseArea.qml | 0 {contents => package/contents}/ui/code/layout.js | 0 {contents => package/contents}/ui/code/tools.js | 0 {contents => package/contents}/ui/main.qml | 0 26 files changed, 6 insertions(+), 6 deletions(-) rename {contents => package/contents}/config/config.qml (100%) rename {contents => package/contents}/config/main.xml (100%) rename {contents => package/contents}/ui/AudioStream.qml (100%) rename {contents => package/contents}/ui/Badge.qml (100%) rename {contents => package/contents}/ui/ConfigAppearance.qml (100%) rename {contents => package/contents}/ui/ConfigBehavior.qml (100%) rename {contents => package/contents}/ui/ConfigIndicators.qml (100%) rename {contents => package/contents}/ui/ContextMenu.qml (100%) rename {contents => package/contents}/ui/GroupDialog.qml (100%) rename {contents => package/contents}/ui/GroupExpanderOverlay.qml (100%) rename {contents => package/contents}/ui/MouseHandler.qml (100%) rename {contents => package/contents}/ui/PipeWireThumbnail.qml (100%) rename {contents => package/contents}/ui/PlayerController.qml (100%) rename {contents => package/contents}/ui/PulseAudio.qml (100%) rename {contents => package/contents}/ui/ScrollableTextWrapper.qml (100%) rename {contents => package/contents}/ui/Task.qml (100%) rename {contents => package/contents}/ui/TaskBadgeOverlay.qml (100%) rename {contents => package/contents}/ui/TaskList.qml (100%) rename {contents => package/contents}/ui/TaskProgressOverlay.qml (100%) rename {contents => package/contents}/ui/ToolTipDelegate.qml (100%) rename {contents => package/contents}/ui/ToolTipInstance.qml (100%) rename {contents => package/contents}/ui/ToolTipWindowMouseArea.qml (100%) rename {contents => package/contents}/ui/code/layout.js (100%) rename {contents => package/contents}/ui/code/tools.js (100%) rename {contents => package/contents}/ui/main.qml (100%) diff --git a/metadata.json b/metadata.json index 39d06372..87f410d3 100644 --- a/metadata.json +++ b/metadata.json @@ -3,11 +3,11 @@ "Authors": [ { "Email": "Hein@kde.org, ideas@alexankitty.com", - "Name": "Eike Hein, Alexandra Stone, Alexandra Stone", - "Name[ar]": "Eike Hein, Alexandra Stone, Alexandra Stone", - "Name[az]": "Eike Hein, Alexandra Stone, Alexandra Stone", - "Name[bg]": "Eike Hein, Alexandra Stone, Alexandra Stone", - "Name[ca@valencia]": "Eike Hein, Alexandra Stone, Alexandra Stone", + "Name": "Eike Hein, Alexandra Stone", + "Name[ar]": "Eike Hein, Alexandra Stone", + "Name[az]": "Eike Hein, Alexandra Stone", + "Name[bg]": "Eike Hein, Alexandra Stone", + "Name[ca@valencia]": "Eike Hein, Alexandra Stone", "Name[ca]": "Eike Hein, Alexandra Stone", "Name[cs]": "Eike Hein, Alexandra Stone", "Name[da]": "Eike Hein, Alexandra Stone", @@ -45,7 +45,7 @@ } ], "Category": "Windows and Tasks", - "Description": "More modern style taskbar-style window switcher displaying icons and text, with some improvments", + "Description": "More modern taskbar-style window switcher displaying icons and text, with some improvments and customization options.", "Description[ar]": "مبدل نوافذ تقليدي بنمط شريط المهام يعرض الأيقونات والنص", "Description[az]": "Nişanlar və mətn göstərən klassik tapşırıq paneli üslubunda pəncərə dəyişdirici", "Description[bg]": "Класически превключвател на прозорци в стил лента на задачите, показващ икони и текст", diff --git a/contents/config/config.qml b/package/contents/config/config.qml similarity index 100% rename from contents/config/config.qml rename to package/contents/config/config.qml diff --git a/contents/config/main.xml b/package/contents/config/main.xml similarity index 100% rename from contents/config/main.xml rename to package/contents/config/main.xml diff --git a/contents/ui/AudioStream.qml b/package/contents/ui/AudioStream.qml similarity index 100% rename from contents/ui/AudioStream.qml rename to package/contents/ui/AudioStream.qml diff --git a/contents/ui/Badge.qml b/package/contents/ui/Badge.qml similarity index 100% rename from contents/ui/Badge.qml rename to package/contents/ui/Badge.qml diff --git a/contents/ui/ConfigAppearance.qml b/package/contents/ui/ConfigAppearance.qml similarity index 100% rename from contents/ui/ConfigAppearance.qml rename to package/contents/ui/ConfigAppearance.qml diff --git a/contents/ui/ConfigBehavior.qml b/package/contents/ui/ConfigBehavior.qml similarity index 100% rename from contents/ui/ConfigBehavior.qml rename to package/contents/ui/ConfigBehavior.qml diff --git a/contents/ui/ConfigIndicators.qml b/package/contents/ui/ConfigIndicators.qml similarity index 100% rename from contents/ui/ConfigIndicators.qml rename to package/contents/ui/ConfigIndicators.qml diff --git a/contents/ui/ContextMenu.qml b/package/contents/ui/ContextMenu.qml similarity index 100% rename from contents/ui/ContextMenu.qml rename to package/contents/ui/ContextMenu.qml diff --git a/contents/ui/GroupDialog.qml b/package/contents/ui/GroupDialog.qml similarity index 100% rename from contents/ui/GroupDialog.qml rename to package/contents/ui/GroupDialog.qml diff --git a/contents/ui/GroupExpanderOverlay.qml b/package/contents/ui/GroupExpanderOverlay.qml similarity index 100% rename from contents/ui/GroupExpanderOverlay.qml rename to package/contents/ui/GroupExpanderOverlay.qml diff --git a/contents/ui/MouseHandler.qml b/package/contents/ui/MouseHandler.qml similarity index 100% rename from contents/ui/MouseHandler.qml rename to package/contents/ui/MouseHandler.qml diff --git a/contents/ui/PipeWireThumbnail.qml b/package/contents/ui/PipeWireThumbnail.qml similarity index 100% rename from contents/ui/PipeWireThumbnail.qml rename to package/contents/ui/PipeWireThumbnail.qml diff --git a/contents/ui/PlayerController.qml b/package/contents/ui/PlayerController.qml similarity index 100% rename from contents/ui/PlayerController.qml rename to package/contents/ui/PlayerController.qml diff --git a/contents/ui/PulseAudio.qml b/package/contents/ui/PulseAudio.qml similarity index 100% rename from contents/ui/PulseAudio.qml rename to package/contents/ui/PulseAudio.qml diff --git a/contents/ui/ScrollableTextWrapper.qml b/package/contents/ui/ScrollableTextWrapper.qml similarity index 100% rename from contents/ui/ScrollableTextWrapper.qml rename to package/contents/ui/ScrollableTextWrapper.qml diff --git a/contents/ui/Task.qml b/package/contents/ui/Task.qml similarity index 100% rename from contents/ui/Task.qml rename to package/contents/ui/Task.qml diff --git a/contents/ui/TaskBadgeOverlay.qml b/package/contents/ui/TaskBadgeOverlay.qml similarity index 100% rename from contents/ui/TaskBadgeOverlay.qml rename to package/contents/ui/TaskBadgeOverlay.qml diff --git a/contents/ui/TaskList.qml b/package/contents/ui/TaskList.qml similarity index 100% rename from contents/ui/TaskList.qml rename to package/contents/ui/TaskList.qml diff --git a/contents/ui/TaskProgressOverlay.qml b/package/contents/ui/TaskProgressOverlay.qml similarity index 100% rename from contents/ui/TaskProgressOverlay.qml rename to package/contents/ui/TaskProgressOverlay.qml diff --git a/contents/ui/ToolTipDelegate.qml b/package/contents/ui/ToolTipDelegate.qml similarity index 100% rename from contents/ui/ToolTipDelegate.qml rename to package/contents/ui/ToolTipDelegate.qml diff --git a/contents/ui/ToolTipInstance.qml b/package/contents/ui/ToolTipInstance.qml similarity index 100% rename from contents/ui/ToolTipInstance.qml rename to package/contents/ui/ToolTipInstance.qml diff --git a/contents/ui/ToolTipWindowMouseArea.qml b/package/contents/ui/ToolTipWindowMouseArea.qml similarity index 100% rename from contents/ui/ToolTipWindowMouseArea.qml rename to package/contents/ui/ToolTipWindowMouseArea.qml diff --git a/contents/ui/code/layout.js b/package/contents/ui/code/layout.js similarity index 100% rename from contents/ui/code/layout.js rename to package/contents/ui/code/layout.js diff --git a/contents/ui/code/tools.js b/package/contents/ui/code/tools.js similarity index 100% rename from contents/ui/code/tools.js rename to package/contents/ui/code/tools.js diff --git a/contents/ui/main.qml b/package/contents/ui/main.qml similarity index 100% rename from contents/ui/main.qml rename to package/contents/ui/main.qml From 002215664c20f55db95c1b6d73e55c9ee1e4d162 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 23 Aug 2023 10:53:59 -0600 Subject: [PATCH 050/141] update scripts --- install.sh | 2 +- update.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 45eb1d6f..25b52eea 100755 --- a/install.sh +++ b/install.sh @@ -1,5 +1,5 @@ #!/bin/sh SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -kpackagetool5 -i $SCRIPT_DIR +kpackagetool5 -i $SCRIPT_DIR/package mkdir -p ~/.local/share/icons/hicolor/256x256/apps/ cp ./FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png diff --git a/update.sh b/update.sh index 5d6dfeb5..b17db48f 100755 --- a/update.sh +++ b/update.sh @@ -1,6 +1,6 @@ #!/bin/sh SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -kpackagetool5 -u $SCRIPT_DIR +kpackagetool5 -u $SCRIPT_DIR/package kquitapp5 plasmashell kstart5 plasmashell cp ./FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png \ No newline at end of file From 2c06e294df19210b8adc64944782618fe6f3c7d4 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 23 Aug 2023 10:55:12 -0600 Subject: [PATCH 051/141] move metadata --- metadata.json => package/metadata.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename metadata.json => package/metadata.json (100%) diff --git a/metadata.json b/package/metadata.json similarity index 100% rename from metadata.json rename to package/metadata.json From 86b4edbaa96821989d6b4b3d1faae11860235ad1 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 23 Aug 2023 11:50:23 -0600 Subject: [PATCH 052/141] add translation scripts. --- package/translate/build | 53 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 package/translate/build diff --git a/package/translate/build b/package/translate/build new file mode 100644 index 00000000..751e1445 --- /dev/null +++ b/package/translate/build @@ -0,0 +1,53 @@ +#!/bin/sh +# Version: 6 + +# This script will convert the *.po files to *.mo files, rebuilding the package/contents/locale folder. +# Feature discussion: https://phabricator.kde.org/D5209 +# Eg: contents/locale/fr_CA/LC_MESSAGES/plasma_applet_org.kde.plasma.eventcalendar.mo + +DIR=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd` +plasmoidName=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Name"` +website=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Website"` +bugAddress="$website" +packageRoot=".." # Root of translatable sources +projectName="plasma_applet_${plasmoidName}" # project name + +#--- +if [ -z "$plasmoidName" ]; then + echo "[build] Error: Couldn't read plasmoidName." + exit +fi + +if [ -z "$(which msgfmt)" ]; then + echo "[build] Error: msgfmt command not found. Need to install gettext" + echo "[build] Running 'sudo apt install gettext'" + sudo apt install gettext + echo "[build] gettext installation should be finished. Going back to installing translations." +fi + +#--- +echo "[build] Compiling messages" + +catalogs=`find . -name '*.po' | sort` +for cat in $catalogs; do + echo "$cat" + catLocale=`basename ${cat%.*}` + msgfmt -o "${catLocale}.mo" "$cat" + + installPath="$DIR/../contents/locale/${catLocale}/LC_MESSAGES/${projectName}.mo" + + echo "[build] Install to ${installPath}" + mkdir -p "$(dirname "$installPath")" + mv "${catLocale}.mo" "${installPath}" +done + +echo "[build] Done building messages" + +if [ "$1" = "--restartplasma" ]; then + echo "[build] Restarting plasmashell" + killall plasmashell + kstart5 plasmashell + echo "[build] Done restarting plasmashell" +else + echo "[build] (re)install the plasmoid and restart plasmashell to test." +fi \ No newline at end of file From 40fb877980dd9d9e05a8bb8fbe2a2cb49ef4a771 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 23 Aug 2023 11:50:30 -0600 Subject: [PATCH 053/141] Add translation scripts and jsonparse --- package/translate/jsonParse.py | 17 +++ package/translate/merge | 239 +++++++++++++++++++++++++++++++++ 2 files changed, 256 insertions(+) create mode 100644 package/translate/jsonParse.py create mode 100644 package/translate/merge diff --git a/package/translate/jsonParse.py b/package/translate/jsonParse.py new file mode 100644 index 00000000..50e4873b --- /dev/null +++ b/package/translate/jsonParse.py @@ -0,0 +1,17 @@ +import json +import sys + +f = open(sys.argv[1],) +values = json.load(f) +keys = sys.argv[2].split(".") +first = True +try: + for key in keys: + if first: + first = False + curValue = values[key] + else: + curValue = curValue[key] + print(curValue) +except: + raise SystemExit('Error: Invalid Key or File') diff --git a/package/translate/merge b/package/translate/merge new file mode 100644 index 00000000..49e3f091 --- /dev/null +++ b/package/translate/merge @@ -0,0 +1,239 @@ +#!/bin/sh +# Version: 22 + +# https://techbase.kde.org/Development/Tutorials/Localization/i18n_Build_Systems +# https://techbase.kde.org/Development/Tutorials/Localization/i18n_Build_Systems/Outside_KDE_repositories +# https://invent.kde.org/sysadmin/l10n-scripty/-/blob/master/extract-messages.sh + +DIR=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd` +plasmoidName=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Name"` +widgetName="${plasmoidName##*.}" # Strip namespace +website=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Website"` +bugAddress="$website" +packageRoot=".." # Root of translatable sources +projectName="plasma_applet_${plasmoidName}" # project name + +#--- +if [ -z "$plasmoidName" ]; then + echo "[merge] Error: Couldn't read plasmoidName." + exit +fi + +if [ -z "$(which xgettext)" ]; then + echo "[merge] Error: xgettext command not found. Need to install gettext" + echo "[merge] Running 'sudo apt install gettext'" + sudo apt install gettext + echo "[merge] gettext installation should be finished. Going back to merging translations." +fi + +#--- +echo "[merge] Extracting messages" +potArgs="--from-code=UTF-8 --width=200 --add-location=file" + +# Note: xgettext v0.20.1 (Kubuntu 20.04) and below will attempt to translate Icon, +# so we need to specify Name, GenericName, Comment, and Keywords. +# https://github.com/Zren/plasma-applet-lib/issues/1 +# https://savannah.gnu.org/support/?108887 +find "${packageRoot}" -name '*.desktop' | sort > "${DIR}/infiles.list" +xgettext \ + ${potArgs} \ + --files-from="${DIR}/infiles.list" \ + --language=Desktop \ + -k -kName -kGenericName -kComment -kKeywords \ + -D "${packageRoot}" \ + -D "${DIR}" \ + -o "template.pot.new" \ + || \ + { echo "[merge] error while calling xgettext. aborting."; exit 1; } + +sed -i 's/"Content-Type: text\/plain; charset=CHARSET\\n"/"Content-Type: text\/plain; charset=UTF-8\\n"/' "template.pot.new" + +# See Ki18n's extract-messages.sh for a full example: +# https://invent.kde.org/sysadmin/l10n-scripty/-/blob/master/extract-messages.sh#L25 +# The -kN_ and -kaliasLocale keywords are mentioned in the Outside_KDE_repositories wiki. +# We don't need -kN_ since we don't use intltool-extract but might as well keep it. +# I have no idea what -kaliasLocale is used for. Googling aliasLocale found only listed kde1 code. +# We don't need to parse -ki18nd since that'll extract messages from other domains. +find "${packageRoot}" -name '*.cpp' -o -name '*.h' -o -name '*.c' -o -name '*.qml' -o -name '*.js' | sort > "${DIR}/infiles.list" +xgettext \ + ${potArgs} \ + --files-from="${DIR}/infiles.list" \ + -C -kde \ + -ci18n \ + -ki18n:1 -ki18nc:1c,2 -ki18np:1,2 -ki18ncp:1c,2,3 \ + -kki18n:1 -kki18nc:1c,2 -kki18np:1,2 -kki18ncp:1c,2,3 \ + -kxi18n:1 -kxi18nc:1c,2 -kxi18np:1,2 -kxi18ncp:1c,2,3 \ + -kkxi18n:1 -kkxi18nc:1c,2 -kkxi18np:1,2 -kkxi18ncp:1c,2,3 \ + -kI18N_NOOP:1 -kI18NC_NOOP:1c,2 \ + -kI18N_NOOP2:1c,2 -kI18N_NOOP2_NOSTRIP:1c,2 \ + -ktr2i18n:1 -ktr2xi18n:1 \ + -kN_:1 \ + -kaliasLocale \ + --package-name="${widgetName}" \ + --msgid-bugs-address="${bugAddress}" \ + -D "${packageRoot}" \ + -D "${DIR}" \ + --join-existing \ + -o "template.pot.new" \ + || \ + { echo "[merge] error while calling xgettext. aborting."; exit 1; } + +sed -i 's/# SOME DESCRIPTIVE TITLE./'"# Translation of ${widgetName} in LANGUAGE"'/' "template.pot.new" +sed -i 's/# Copyright (C) YEAR THE PACKAGE'"'"'S COPYRIGHT HOLDER/'"# Copyright (C) $(date +%Y)"'/' "template.pot.new" + +if [ -f "template.pot" ]; then + newPotDate=`grep "POT-Creation-Date:" template.pot.new | sed 's/.\{3\}$//'` + oldPotDate=`grep "POT-Creation-Date:" template.pot | sed 's/.\{3\}$//'` + sed -i 's/'"${newPotDate}"'/'"${oldPotDate}"'/' "template.pot.new" + changes=`diff "template.pot" "template.pot.new"` + if [ ! -z "$changes" ]; then + # There's been changes + sed -i 's/'"${oldPotDate}"'/'"${newPotDate}"'/' "template.pot.new" + mv "template.pot.new" "template.pot" + + addedKeys=`echo "$changes" | grep "> msgid" | cut -c 9- | sort` + removedKeys=`echo "$changes" | grep "< msgid" | cut -c 9- | sort` + echo "" + echo "Added Keys:" + echo "$addedKeys" + echo "" + echo "Removed Keys:" + echo "$removedKeys" + echo "" + + else + # No changes + rm "template.pot.new" + fi +else + # template.pot didn't already exist + mv "template.pot.new" "template.pot" +fi + +potMessageCount=`expr $(grep -Pzo 'msgstr ""\n(\n|$)' "template.pot" | grep -c 'msgstr ""')` +echo "| Locale | Lines | % Done|" > "./Status.md" +echo "|----------|---------|-------|" >> "./Status.md" +entryFormat="| %-8s | %7s | %5s |" +templateLine=`perl -e "printf(\"$entryFormat\", \"Template\", \"${potMessageCount}\", \"\")"` +echo "$templateLine" >> "./Status.md" + +rm "${DIR}/infiles.list" +echo "[merge] Done extracting messages" + +#--- +echo "[merge] Merging messages" +catalogs=`find . -name '*.po' | sort` +for cat in $catalogs; do + echo "[merge] $cat" + catLocale=`basename ${cat%.*}` + + widthArg="" + catUsesGenerator=`grep "X-Generator:" "$cat"` + if [ -z "$catUsesGenerator" ]; then + widthArg="--width=400" + fi + + compendiumArg="" + if [ ! -z "$COMPENDIUM_DIR" ]; then + langCode=`basename "${cat%.*}"` + compendiumPath=`realpath "$COMPENDIUM_DIR/compendium-${langCode}.po"` + if [ -f "$compendiumPath" ]; then + echo "compendiumPath=$compendiumPath" + compendiumArg="--compendium=$compendiumPath" + fi + fi + + cp "$cat" "$cat.new" + sed -i 's/"Content-Type: text\/plain; charset=CHARSET\\n"/"Content-Type: text\/plain; charset=UTF-8\\n"/' "$cat.new" + + msgmerge \ + ${widthArg} \ + --add-location=file \ + --no-fuzzy-matching \ + ${compendiumArg} \ + -o "$cat.new" \ + "$cat.new" "${DIR}/template.pot" + + sed -i 's/# SOME DESCRIPTIVE TITLE./'"# Translation of ${widgetName} in ${catLocale}"'/' "$cat.new" + sed -i 's/# Translation of '"${widgetName}"' in LANGUAGE/'"# Translation of ${widgetName} in ${catLocale}"'/' "$cat.new" + sed -i 's/# Copyright (C) YEAR THE PACKAGE'"'"'S COPYRIGHT HOLDER/'"# Copyright (C) $(date +%Y)"'/' "$cat.new" + + poEmptyMessageCount=`expr $(grep -Pzo 'msgstr ""\n(\n|$)' "$cat.new" | grep -c 'msgstr ""')` + poMessagesDoneCount=`expr $potMessageCount - $poEmptyMessageCount` + poCompletion=`perl -e "printf(\"%d\", $poMessagesDoneCount * 100 / $potMessageCount)"` + poLine=`perl -e "printf(\"$entryFormat\", \"$catLocale\", \"${poMessagesDoneCount}/${potMessageCount}\", \"${poCompletion}%\")"` + echo "$poLine" >> "./Status.md" + + # mv "$cat" "$cat.old" + mv "$cat.new" "$cat" +done +echo "[merge] Done merging messages" + +#--- +echo "[merge] Updating .desktop file" + +# Generate LINGUAS for msgfmt +if [ -f "$DIR/LINGUAS" ]; then + rm "$DIR/LINGUAS" +fi +touch "$DIR/LINGUAS" +for cat in $catalogs; do + catLocale=`basename ${cat%.*}` + echo "${catLocale}" >> "$DIR/LINGUAS" +done + +cp -f "$DIR/../metadata.desktop" "$DIR/template.desktop" +sed -i '/^Name\[/ d; /^GenericName\[/ d; /^Comment\[/ d; /^Keywords\[/ d' "$DIR/template.desktop" + +msgfmt \ + --desktop \ + --template="$DIR/template.desktop" \ + -d "$DIR/" \ + -o "$DIR/new.desktop" + +# Delete empty msgid messages that used the po header +if [ ! -z "$(grep '^Name=$' "$DIR/new.desktop")" ]; then + echo "[merge] Name in metadata.desktop is empty!" + sed -i '/^Name\[/ d' "$DIR/new.desktop" +fi +if [ ! -z "$(grep '^GenericName=$' "$DIR/new.desktop")" ]; then + echo "[merge] GenericName in metadata.desktop is empty!" + sed -i '/^GenericName\[/ d' "$DIR/new.desktop" +fi +if [ ! -z "$(grep '^Comment=$' "$DIR/new.desktop")" ]; then + echo "[merge] Comment in metadata.desktop is empty!" + sed -i '/^Comment\[/ d' "$DIR/new.desktop" +fi +if [ ! -z "$(grep '^Keywords=$' "$DIR/new.desktop")" ]; then + echo "[merge] Keywords in metadata.desktop is empty!" + sed -i '/^Keywords\[/ d' "$DIR/new.desktop" +fi + +# Place translations at the bottom of the desktop file. +translatedLines=`cat "$DIR/new.desktop" | grep "]="` +if [ ! -z "${translatedLines}" ]; then + sed -i '/^Name\[/ d; /^GenericName\[/ d; /^Comment\[/ d; /^Keywords\[/ d' "$DIR/new.desktop" + if [ "$(tail -c 2 "$DIR/new.desktop" | wc -l)" != "2" ]; then + # Does not end with 2 empty lines, so add an empty line. + echo "" >> "$DIR/new.desktop" + fi + echo "${translatedLines}" >> "$DIR/new.desktop" +fi + +# Cleanup +mv "$DIR/new.desktop" "$DIR/../metadata.desktop" +rm "$DIR/template.desktop" +rm "$DIR/LINGUAS" + +#--- +# Populate ReadMe.md +echo "[merge] Updating translate/ReadMe.md" +sed -i -E 's`share\/plasma\/plasmoids\/(.+)\/translate`share/plasma/plasmoids/'"${plasmoidName}"'/translate`' ./ReadMe.md +if [[ "$website" == *"github.com"* ]]; then + sed -i -E 's`\[new issue\]\(https:\/\/github\.com\/(.+)\/(.+)\/issues\/new\)`[new issue]('"${website}"'/issues/new)`' ./ReadMe.md +fi +sed -i '/^|/ d' ./ReadMe.md # Remove status table from ReadMe +cat ./Status.md >> ./ReadMe.md +rm ./Status.md + +echo "[merge] Done" \ No newline at end of file From 95935eebd78a8950207bdaa00f6102baae339a8b Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 23 Aug 2023 12:04:26 -0600 Subject: [PATCH 054/141] untested implementation of translation --- package/translate/build | 4 ++-- package/translate/merge | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package/translate/build b/package/translate/build index 751e1445..15e60195 100644 --- a/package/translate/build +++ b/package/translate/build @@ -6,8 +6,8 @@ # Eg: contents/locale/fr_CA/LC_MESSAGES/plasma_applet_org.kde.plasma.eventcalendar.mo DIR=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd` -plasmoidName=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Name"` -website=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Website"` +plasmoidName=`python3 jsonparse.py $DIR/../metadata.json KPlugin.Name` +website=`python3 jsonparse.py $DIR/../metadata.json KPlugin.Website` bugAddress="$website" packageRoot=".." # Root of translatable sources projectName="plasma_applet_${plasmoidName}" # project name diff --git a/package/translate/merge b/package/translate/merge index 49e3f091..5e8772f4 100644 --- a/package/translate/merge +++ b/package/translate/merge @@ -6,9 +6,9 @@ # https://invent.kde.org/sysadmin/l10n-scripty/-/blob/master/extract-messages.sh DIR=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd` -plasmoidName=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Name"` +plasmoidName=`python3 jsonparse.py $DIR/../metadata.json KPlugin.Name` widgetName="${plasmoidName##*.}" # Strip namespace -website=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Website"` +website=`python3 jsonparse.py $DIR/../metadata.json KPlugin.Website` bugAddress="$website" packageRoot=".." # Root of translatable sources projectName="plasma_applet_${plasmoidName}" # project name From 6e2eb2b6adbcace124ad301ada4efdcdef332ebc Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 23 Aug 2023 17:32:11 -0600 Subject: [PATCH 055/141] Add zh_CN and nl languages --- .../LC_MESSAGES/plasma_applet_Fancy Tasks.mo | Bin 0 -> 11643 bytes .../LC_MESSAGES/plasma_applet_Fancy Tasks.mo | Bin 0 -> 10785 bytes package/translate/ReadMe.md | 40 + package/translate/build | 4 +- package/translate/merge | 138 ++-- package/translate/nl.po | 712 ++++++++++++++++++ package/translate/template.pot | 688 +++++++++++++++++ package/translate/zh_CN.po | 694 +++++++++++++++++ 8 files changed, 2205 insertions(+), 71 deletions(-) create mode 100644 package/contents/locale/nl/LC_MESSAGES/plasma_applet_Fancy Tasks.mo create mode 100644 package/contents/locale/zh_CN/LC_MESSAGES/plasma_applet_Fancy Tasks.mo create mode 100644 package/translate/ReadMe.md create mode 100644 package/translate/nl.po create mode 100644 package/translate/template.pot create mode 100644 package/translate/zh_CN.po diff --git a/package/contents/locale/nl/LC_MESSAGES/plasma_applet_Fancy Tasks.mo b/package/contents/locale/nl/LC_MESSAGES/plasma_applet_Fancy Tasks.mo new file mode 100644 index 0000000000000000000000000000000000000000..e5a4db92b6701bf61d7a2898deec51fef873bd21 GIT binary patch literal 11643 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 O8>cK+u;)&lGXD?z{ksGJ literal 0 HcmV?d00001 diff --git a/package/contents/locale/zh_CN/LC_MESSAGES/plasma_applet_Fancy Tasks.mo b/package/contents/locale/zh_CN/LC_MESSAGES/plasma_applet_Fancy Tasks.mo new file mode 100644 index 0000000000000000000000000000000000000000..13d35cebeae3fda9dbcb8dc2f086a58699e15bd6 GIT binary patch literal 10785 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 literal 0 HcmV?d00001 diff --git a/package/translate/ReadMe.md b/package/translate/ReadMe.md new file mode 100644 index 00000000..06bca620 --- /dev/null +++ b/package/translate/ReadMe.md @@ -0,0 +1,40 @@ +> Version 7 of Zren's i18n scripts. + +With KDE Frameworks v5.37 and above, translations are bundled with the `*.plasmoid` file downloaded from the store. + +## Install Translations + +Go to `~/.local/share/plasma/plasmoids/Fancy Tasks/translate/` and run `sh ./build --restartplasma`. + +## New Translations + +1. Fill out [`template.pot`](template.pot) with your translations then open a [new issue](https://github.com/alexankitty/FancyTasks/issues/new), name the file `spanish.txt`, attach the txt file to the issue (drag and drop). + +Or if you know how to make a pull request + +1. Copy the `template.pot` file and name it your locale's code (Eg: `en`/`de`/`fr`) with the extension `.po`. Then fill out all the `msgstr ""`. + +## Scripts + +* `sh ./merge` will parse the `i18n()` calls in the `*.qml` files and write it to the `template.pot` file. Then it will merge any changes into the `*.po` language files. +* `sh ./build` will convert the `*.po` files to it's binary `*.mo` version and move it to `contents/locale/...` which will bundle the translations in the `*.plasmoid` without needing the user to manually install them. +* `sh ./plasmoidlocaletest` will run `./build` then `plasmoidviewer` (part of `plasma-sdk`). + +## Links + +* https://zren.github.io/kde/docs/widget/#translations-i18n +* https://techbase.kde.org/Development/Tutorials/Localization/i18n_Build_Systems +* https://api.kde.org/frameworks/ki18n/html/prg_guide.html + +## Examples + +* https://l10n.kde.org/stats/gui/trunk-kf5/team/fr/plasma-desktop/ +* https://github.com/psifidotos/nowdock-plasmoid/tree/master/po +* https://github.com/kotelnik/plasma-applet-redshift-control/tree/master/translations + +## Status +| Locale | Lines | % Done| +|----------|---------|-------| +| Template | 158 | | +| nl | 152/158 | 96% | +| zh_CN | 152/158 | 96% | diff --git a/package/translate/build b/package/translate/build index 15e60195..3bdb127e 100644 --- a/package/translate/build +++ b/package/translate/build @@ -6,8 +6,8 @@ # Eg: contents/locale/fr_CA/LC_MESSAGES/plasma_applet_org.kde.plasma.eventcalendar.mo DIR=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd` -plasmoidName=`python3 jsonparse.py $DIR/../metadata.json KPlugin.Name` -website=`python3 jsonparse.py $DIR/../metadata.json KPlugin.Website` +plasmoidName=`python3 jsonParse.py $DIR/../metadata.json KPlugin.Name` +website=`python3 jsonParse.py $DIR/../metadata.json KPlugin.Website` bugAddress="$website" packageRoot=".." # Root of translatable sources projectName="plasma_applet_${plasmoidName}" # project name diff --git a/package/translate/merge b/package/translate/merge index 5e8772f4..4f03c601 100644 --- a/package/translate/merge +++ b/package/translate/merge @@ -6,9 +6,9 @@ # https://invent.kde.org/sysadmin/l10n-scripty/-/blob/master/extract-messages.sh DIR=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd` -plasmoidName=`python3 jsonparse.py $DIR/../metadata.json KPlugin.Name` +plasmoidName=`python3 jsonParse.py $DIR/../metadata.json KPlugin.Name` widgetName="${plasmoidName##*.}" # Strip namespace -website=`python3 jsonparse.py $DIR/../metadata.json KPlugin.Website` +website=`python3 jsonParse.py $DIR/../metadata.json KPlugin.Website` bugAddress="$website" packageRoot=".." # Root of translatable sources projectName="plasma_applet_${plasmoidName}" # project name @@ -34,19 +34,20 @@ potArgs="--from-code=UTF-8 --width=200 --add-location=file" # so we need to specify Name, GenericName, Comment, and Keywords. # https://github.com/Zren/plasma-applet-lib/issues/1 # https://savannah.gnu.org/support/?108887 -find "${packageRoot}" -name '*.desktop' | sort > "${DIR}/infiles.list" -xgettext \ - ${potArgs} \ - --files-from="${DIR}/infiles.list" \ - --language=Desktop \ - -k -kName -kGenericName -kComment -kKeywords \ - -D "${packageRoot}" \ - -D "${DIR}" \ - -o "template.pot.new" \ - || \ - { echo "[merge] error while calling xgettext. aborting."; exit 1; } -sed -i 's/"Content-Type: text\/plain; charset=CHARSET\\n"/"Content-Type: text\/plain; charset=UTF-8\\n"/' "template.pot.new" +# find "${packageRoot}" -name '*.desktop' | sort > "${DIR}/infiles.list" +# xgettext \ +# ${potArgs} \ +# --files-from="${DIR}/infiles.list" \ +# --language=Desktop \ +# -k -kName -kGenericName -kComment -kKeywords \ +# -D "${packageRoot}" \ +# -D "${DIR}" \ +# -o "template.pot.new" \ +# || \ +# { echo "[merge] error while calling xgettext. aborting."; exit 1; } + +# sed -i 's/"Content-Type: text\/plain; charset=CHARSET\\n"/"Content-Type: text\/plain; charset=UTF-8\\n"/' "template.pot.new" # See Ki18n's extract-messages.sh for a full example: # https://invent.kde.org/sysadmin/l10n-scripty/-/blob/master/extract-messages.sh#L25 @@ -73,7 +74,6 @@ xgettext \ --msgid-bugs-address="${bugAddress}" \ -D "${packageRoot}" \ -D "${DIR}" \ - --join-existing \ -o "template.pot.new" \ || \ { echo "[merge] error while calling xgettext. aborting."; exit 1; } @@ -170,60 +170,60 @@ done echo "[merge] Done merging messages" #--- -echo "[merge] Updating .desktop file" - -# Generate LINGUAS for msgfmt -if [ -f "$DIR/LINGUAS" ]; then - rm "$DIR/LINGUAS" -fi -touch "$DIR/LINGUAS" -for cat in $catalogs; do - catLocale=`basename ${cat%.*}` - echo "${catLocale}" >> "$DIR/LINGUAS" -done - -cp -f "$DIR/../metadata.desktop" "$DIR/template.desktop" -sed -i '/^Name\[/ d; /^GenericName\[/ d; /^Comment\[/ d; /^Keywords\[/ d' "$DIR/template.desktop" - -msgfmt \ - --desktop \ - --template="$DIR/template.desktop" \ - -d "$DIR/" \ - -o "$DIR/new.desktop" - -# Delete empty msgid messages that used the po header -if [ ! -z "$(grep '^Name=$' "$DIR/new.desktop")" ]; then - echo "[merge] Name in metadata.desktop is empty!" - sed -i '/^Name\[/ d' "$DIR/new.desktop" -fi -if [ ! -z "$(grep '^GenericName=$' "$DIR/new.desktop")" ]; then - echo "[merge] GenericName in metadata.desktop is empty!" - sed -i '/^GenericName\[/ d' "$DIR/new.desktop" -fi -if [ ! -z "$(grep '^Comment=$' "$DIR/new.desktop")" ]; then - echo "[merge] Comment in metadata.desktop is empty!" - sed -i '/^Comment\[/ d' "$DIR/new.desktop" -fi -if [ ! -z "$(grep '^Keywords=$' "$DIR/new.desktop")" ]; then - echo "[merge] Keywords in metadata.desktop is empty!" - sed -i '/^Keywords\[/ d' "$DIR/new.desktop" -fi - -# Place translations at the bottom of the desktop file. -translatedLines=`cat "$DIR/new.desktop" | grep "]="` -if [ ! -z "${translatedLines}" ]; then - sed -i '/^Name\[/ d; /^GenericName\[/ d; /^Comment\[/ d; /^Keywords\[/ d' "$DIR/new.desktop" - if [ "$(tail -c 2 "$DIR/new.desktop" | wc -l)" != "2" ]; then - # Does not end with 2 empty lines, so add an empty line. - echo "" >> "$DIR/new.desktop" - fi - echo "${translatedLines}" >> "$DIR/new.desktop" -fi - -# Cleanup -mv "$DIR/new.desktop" "$DIR/../metadata.desktop" -rm "$DIR/template.desktop" -rm "$DIR/LINGUAS" +# echo "[merge] Updating .desktop file" + +# # Generate LINGUAS for msgfmt +# if [ -f "$DIR/LINGUAS" ]; then +# rm "$DIR/LINGUAS" +# fi +# touch "$DIR/LINGUAS" +# for cat in $catalogs; do +# catLocale=`basename ${cat%.*}` +# echo "${catLocale}" >> "$DIR/LINGUAS" +# done + +# cp -f "$DIR/../metadata.desktop" "$DIR/template.desktop" +# sed -i '/^Name\[/ d; /^GenericName\[/ d; /^Comment\[/ d; /^Keywords\[/ d' "$DIR/template.desktop" + +# msgfmt \ +# --desktop \ +# --template="$DIR/template.desktop" \ +# -d "$DIR/" \ +# -o "$DIR/new.desktop" + +# # Delete empty msgid messages that used the po header +# if [ ! -z "$(grep '^Name=$' "$DIR/new.desktop")" ]; then +# echo "[merge] Name in metadata.desktop is empty!" +# sed -i '/^Name\[/ d' "$DIR/new.desktop" +# fi +# if [ ! -z "$(grep '^GenericName=$' "$DIR/new.desktop")" ]; then +# echo "[merge] GenericName in metadata.desktop is empty!" +# sed -i '/^GenericName\[/ d' "$DIR/new.desktop" +# fi +# if [ ! -z "$(grep '^Comment=$' "$DIR/new.desktop")" ]; then +# echo "[merge] Comment in metadata.desktop is empty!" +# sed -i '/^Comment\[/ d' "$DIR/new.desktop" +# fi +# if [ ! -z "$(grep '^Keywords=$' "$DIR/new.desktop")" ]; then +# echo "[merge] Keywords in metadata.desktop is empty!" +# sed -i '/^Keywords\[/ d' "$DIR/new.desktop" +# fi + +# # Place translations at the bottom of the desktop file. +# translatedLines=`cat "$DIR/new.desktop" | grep "]="` +# if [ ! -z "${translatedLines}" ]; then +# sed -i '/^Name\[/ d; /^GenericName\[/ d; /^Comment\[/ d; /^Keywords\[/ d' "$DIR/new.desktop" +# if [ "$(tail -c 2 "$DIR/new.desktop" | wc -l)" != "2" ]; then +# # Does not end with 2 empty lines, so add an empty line. +# echo "" >> "$DIR/new.desktop" +# fi +# echo "${translatedLines}" >> "$DIR/new.desktop" +# fi + +# # Cleanup +# mv "$DIR/new.desktop" "$DIR/../metadata.desktop" +# rm "$DIR/template.desktop" +# rm "$DIR/LINGUAS" #--- # Populate ReadMe.md diff --git a/package/translate/nl.po b/package/translate/nl.po new file mode 100644 index 00000000..43ab6ae3 --- /dev/null +++ b/package/translate/nl.po @@ -0,0 +1,712 @@ +# Translation of fancytasks in LANGUAGE +# Copyright (C) 2023 +# This file is distributed under the same license as the fancytasks package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: fancytasks\n" +"Report-Msgid-Bugs-To: https://userbase.kde.org/Plasma/Tasks\n" +"POT-Creation-Date: 2023-08-23 17:30-0600\n" +"PO-Revision-Date: 2023-07-13 22:27+0200\n" +"Last-Translator: Heimen Stoffels \n" +"Language-Team: \n" +"Language: nl\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" + +#: ../contents/config/config.qml +msgid "Appearance" +msgstr "Vormgeving" + +#: ../contents/config/config.qml +msgid "Behavior" +msgstr "Gedrag" + +#: ../contents/config/config.qml +msgid "Indicators" +msgstr "Indicators" + +#: ../contents/ui/Badge.qml +msgctxt "Invalid number of new messages, overlay, keep short" +msgid "—" +msgstr "—" + +#: ../contents/ui/Badge.qml +msgctxt "Over 9999 new messages, overlay, keep short" +msgid "9,999+" +msgstr "9,999+" + +#: ../contents/ui/ConfigAppearance.qml +msgid "General:" +msgstr "Algemeen:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Show tooltips" +msgstr "Vensterminiaturen tonen" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Highlight windows when hovering over task tooltips" +msgstr "Vensters voorvertonen na aanwijzen van vensterminiaturen" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Mark applications that play audio" +msgstr "Programma's die audio afspelen markeren" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Use plasma borders" +msgstr "Plasmakaders gebruiken" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Button Colors:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Using Plasma Style/Accent" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Using Color Overlay" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Use dominant icon color" +msgstr "Dominante pictogramkleur gebruiken" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Custom Color:" +msgstr "Zelfgekozen kleur:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Colorize inactive buttons" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Plasma Button Decorations:" +msgstr "Plasma-knopdecoraties:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Disable" +msgstr "Uitschakelen" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Plasma Button Direction:" +msgstr "Plasma-knoprichting:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Override" +msgstr "Afdwingen" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Be sure to use this when using as a floating widget" +msgstr "Let op: gebruik dit alleen bij gebruik als zwevende widget" + +#: ../contents/ui/ConfigAppearance.qml +msgid "North" +msgstr "Bovenaan" + +#: ../contents/ui/ConfigAppearance.qml +msgid "South" +msgstr "Onderaan" + +#: ../contents/ui/ConfigAppearance.qml +msgid "West" +msgstr "Links" + +#: ../contents/ui/ConfigAppearance.qml +msgid "East" +msgstr "Rechts" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Maximum columns:" +msgstr "Maximaal aantal kolommen:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Maximum rows:" +msgstr "Maximaal aantal rijen:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Always arrange tasks in rows of as many columns" +msgstr "Taken altijd verdelen over zoveel mogelijk kolommen" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Always arrange tasks in columns of as many rows" +msgstr "Taken altijd verdelen over zoveel mogelijk rijen" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Maximum button length (px):" +msgstr "Maximale knopbreedte (in px):" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Space between taskbar items (px):" +msgstr "Ruimte tussen taakbalkitems (in px):" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Press OK to fix layout issues." +msgstr "Klik op oké om indelingsproblemen op te lossen." + +#: ../contents/ui/ConfigAppearance.qml +msgid "Spacing between icons:" +msgstr "Ruimte tussen pictogrammen:" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Small" +msgstr "Klein" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Normal" +msgstr "Normaal" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Large" +msgstr "Groot" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" +msgid "Automatically set to Large when in Touch Mode" +msgstr "Automatisch ingesteld op ‘Groot’ als de aanraakmodus is ingeschakeld" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Display:" +msgstr "Tonen:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Show task names" +msgstr "Pictogrammen en namen" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Show icons only" +msgstr "Alleen pictogrammen" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Group:" +msgstr "Groeperen:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Do not group" +msgstr "Niet groeperen" + +#: ../contents/ui/ConfigBehavior.qml +msgid "By program name" +msgstr "Op programmanaam" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Clicking grouped task:" +msgstr "Actie na aanklikken van gegroepeerde taak:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Completes the sentence 'Clicking grouped task cycles through tasks' " +msgid "Cycles through tasks" +msgstr "Van taak wisselen" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "" +"Completes the sentence 'Clicking grouped task shows tooltip window " +"thumbnails' " +msgid "Shows tooltip window thumbnails" +msgstr "Vensterminiaturen tonen" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "" +"Completes the sentence 'Clicking grouped task shows windows side by side' " +msgid "Shows windows side by side" +msgstr "Vensters naast elkaar tonen" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Completes the sentence 'Clicking grouped task shows textual list' " +msgid "Shows textual list" +msgstr "Vensterlijst tonen" + +#: ../contents/ui/ConfigBehavior.qml +msgid "" +"Tooltips are disabled, so the windows will be displayed side by side instead." +msgstr "" +"Vensterminiaturen zijn uitgeschakeld; vensters worden naast elkaar getoond." + +#: ../contents/ui/ConfigBehavior.qml +msgid "" +"Tooltips are disabled, and the compositor does not support displaying " +"windows side by side, so a textual list will be displayed instead" +msgstr "" +"Vensterminiaturen zijn uitgeschakeld en de compositor heeft geen " +"ondersteuning voor het tonen van vensters naast elkaar. Er wordt in plaats " +"daarvan een lijst getoond." + +#: ../contents/ui/ConfigBehavior.qml +msgid "" +"The compositor does not support displaying windows side by side, so a " +"textual list will be displayed instead." +msgstr "" +"De compositor heeft geen ondersteuning voor het tonen van vensters naast " +"elkaar; er wordt een lijst getoond." + +#: ../contents/ui/ConfigBehavior.qml +msgid "Combine into single button" +msgstr "Combineren tot één knop" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Group only when the Task Manager is full" +msgstr "Alleen groeperen als takenbeheer vol is" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Sort:" +msgstr "Rangschikken:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Do not sort" +msgstr "Niet rangschikken" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Manually" +msgstr "Handmatig" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Alphabetically" +msgstr "Op alfabetische volgorde" + +#: ../contents/ui/ConfigBehavior.qml +msgid "By desktop" +msgstr "Op bureaublad" + +#: ../contents/ui/ConfigBehavior.qml +msgid "By activity" +msgstr "Op activiteit" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Keep launchers separate" +msgstr "Starters gescheiden houden" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgid "Clicking active task:" +msgstr "Actie na aanklikken van actieve taak:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgid "Minimizes the task" +msgstr "Taak minimaliseren" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Middle-clicking any task:" +msgstr "Actie na middelklikken op een taak:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task does nothing'" +msgid "Does nothing" +msgstr "Niets doen" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task closes window or group'" +msgid "Closes window or group" +msgstr "Venster of groep sluiten" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task opens a new window'" +msgid "Opens a new window" +msgstr "Nieuw venster openen" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "" +"Part of a sentence: 'Middle-clicking any task minimizes/restores window or " +"group'" +msgid "Minimizes/Restores window or group" +msgstr "Venster of groep minimaliseren/herstellen" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task toggles grouping'" +msgid "Toggles grouping" +msgstr "Groeperen in-/uitschakelen" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "" +"Part of a sentence: 'Middle-clicking any task brings it to the current " +"virtual desktop'" +msgid "Brings it to the current virtual desktop" +msgstr "Verplaatsen naar huidig virtueel bureaublad" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgid "Mouse wheel:" +msgstr "Muiswiel:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgid "Cycles through tasks" +msgstr "Van taak wisselen" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Skip minimized tasks" +msgstr "Geminimaliseerde taken overslaan" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Show only tasks:" +msgstr "Alleen taken tonen van:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "From current screen" +msgstr "Huidig scherm" + +#: ../contents/ui/ConfigBehavior.qml +msgid "From current desktop" +msgstr "Huidig bureaublad" + +#: ../contents/ui/ConfigBehavior.qml +msgid "From current activity" +msgstr "Huidige activiteit" + +#: ../contents/ui/ConfigBehavior.qml +msgid "That are minimized" +msgstr "Geminimaliseerde vensters" + +#: ../contents/ui/ConfigBehavior.qml +msgid "When panel is hidden:" +msgstr "Als het paneel verborgen is:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Unhide when a window wants attention" +msgstr "Tonen als een venster om aandacht vraagt" + +#: ../contents/ui/ConfigBehavior.qml +msgid "New tasks appear:" +msgstr "Nieuwe taken tonen aan:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "To the right" +msgstr "Rechterkant" + +#: ../contents/ui/ConfigBehavior.qml +msgid "To the left" +msgstr "Linkerkant" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicators:" +msgstr "Indicators:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Disabled" +msgstr "Uitgeschakeld" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Enabled" +msgstr "Ingeschakeld" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Group Overlay:" +msgstr "Groepslaag:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Takes effect on next time plasma groups tasks." +msgstr "Let op: dit wordt toegepast na de volgende groepering." + +#: ../contents/ui/ConfigIndicators.qml +msgid "Animate Indicators:" +msgstr "Indicators voorzien van animaties:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Location:" +msgstr "Indicatorlocatie:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Reverse shown side" +msgstr "Aan andere zijde tonen" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Override location" +msgstr "Locatie afdwingen" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Bottom" +msgstr "Onderaan" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Left" +msgstr "Links" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Right" +msgstr "Rechts" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Top" +msgstr "Bovenaan" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Style:" +msgstr "Indicatorstijl:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Metro" +msgstr "Metro" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Ciliora" +msgstr "Ciliora" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Dashes" +msgstr "Streepjes" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Min Limit:" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Max Limit:" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Minimize Options:" +msgstr "Minimaliseeropties:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Desaturate" +msgstr "Verzadiging verminderen" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Shrink when minimized" +msgstr "Verkleinen" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Growth/Shrink factor:" +msgstr "Vergroot-/Verkleinfactor:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator size (px):" +msgstr "Indicatorgrootte (in px):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator length (px):" +msgstr "Indicatorbreedte (in px):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Radius (%):" +msgstr "Indicatorstraal (in %):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator margin (px):" +msgstr "Indicatormarge (in px):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Color:" +msgstr "Indicatorkleur:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Use plasma accent color" +msgstr "Plasma-accentkleur" + +#: ../contents/ui/ContextMenu.qml +msgid "Places" +msgstr "Locaties" + +#: ../contents/ui/ContextMenu.qml +msgid "Recent Files" +msgstr "Recente bestanden" + +#: ../contents/ui/ContextMenu.qml +msgid "Actions" +msgstr "Acties" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Play previous track" +msgid "Previous Track" +msgstr "Vorig nummer" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Pause playback" +msgid "Pause" +msgstr "Pauzeren" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Start playback" +msgid "Play" +msgstr "Afspelen" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Play next track" +msgid "Next Track" +msgstr "Volgend nummer" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Stop playback" +msgid "Stop" +msgstr "Stoppen" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Quit media player app" +msgid "Quit" +msgstr "Afsluiten" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Open or bring to the front window of media player app" +msgid "Restore" +msgstr "Herstellen" + +#: ../contents/ui/ContextMenu.qml +msgid "Mute" +msgstr "Dempen" + +#: ../contents/ui/ContextMenu.qml +msgid "Open New Window" +msgstr "Nieuw venster openen" + +#: ../contents/ui/ContextMenu.qml +msgid "Move to &Desktop" +msgstr "Verplaatsen naar bureaubla&d" + +#: ../contents/ui/ContextMenu.qml +msgid "Move &To Current Desktop" +msgstr "Verplaa&tsen naar huidig bureaublad" + +#: ../contents/ui/ContextMenu.qml +msgid "&All Desktops" +msgstr "&Alle bureaubladen" + +#: ../contents/ui/ContextMenu.qml +msgctxt "1 = number of desktop, 2 = desktop name" +msgid "&%1 %2" +msgstr "&%1 %2" + +#: ../contents/ui/ContextMenu.qml +msgid "&New Desktop" +msgstr "&Nieuw bureaublad" + +#: ../contents/ui/ContextMenu.qml +msgid "Show in &Activities" +msgstr "Tonen in &activiteiten" + +#: ../contents/ui/ContextMenu.qml +msgid "Add To Current Activity" +msgstr "Toevoegen aan huidige activiteit" + +#: ../contents/ui/ContextMenu.qml +msgid "All Activities" +msgstr "Alle activiteiten" + +#: ../contents/ui/ContextMenu.qml +msgid "Move to %1" +msgstr "Verplaatsen naar %1" + +#: ../contents/ui/ContextMenu.qml +msgid "&Pin to Task Manager" +msgstr "Vastma&ken aan takenbeheer" + +#: ../contents/ui/ContextMenu.qml +msgid "On All Activities" +msgstr "Op alle activiteiten" + +#: ../contents/ui/ContextMenu.qml +msgid "On The Current Activity" +msgstr "Op de huidige activiteit" + +#: ../contents/ui/ContextMenu.qml +msgid "Unpin from Task Manager" +msgstr "Losmaken van takenbeheer" + +#: ../contents/ui/ContextMenu.qml +msgid "More" +msgstr "Meer" + +#: ../contents/ui/ContextMenu.qml +msgid "&Move" +msgstr "Ver&plaatsen" + +#: ../contents/ui/ContextMenu.qml +msgid "Re&size" +msgstr "Grootte aanpa&ssen" + +#: ../contents/ui/ContextMenu.qml +msgid "Ma&ximize" +msgstr "Ma&ximaliseren" + +#: ../contents/ui/ContextMenu.qml +msgid "Mi&nimize" +msgstr "Mi&nimaliseren" + +#: ../contents/ui/ContextMenu.qml +msgid "Keep &Above Others" +msgstr "&Altijd bovenaan" + +#: ../contents/ui/ContextMenu.qml +msgid "Keep &Below Others" +msgstr "Altijd on&deraan" + +#: ../contents/ui/ContextMenu.qml +msgid "&Fullscreen" +msgstr "&Volledig scherm" + +#: ../contents/ui/ContextMenu.qml +msgid "&Shade" +msgstr "Op&rollen" + +#: ../contents/ui/ContextMenu.qml +msgid "Allow this program to be grouped" +msgstr "Groeperen toestaan" + +#: ../contents/ui/ContextMenu.qml +msgid "&Close" +msgstr "&Sluiten" + +#: ../contents/ui/Task.qml +msgid "Activate %1" +msgstr "%1 activeren" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "button to unmute app" +msgid "Unmute %1" +msgstr "%1 ontdempen" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "button to mute app" +msgid "Mute %1" +msgstr "%1 dempen" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Accessibility data on volume slider" +msgid "Adjust volume for %1" +msgstr "Volumeniveau van %1 aanpassen" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "volume percentage" +msgid "%1%" +msgstr "%1%" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "only used for sizing, should be widest possible string" +msgid "100%" +msgstr "100%" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Comma-separated list of desktops" +msgid "On %1" +msgstr "Op %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Comma-separated list of desktops" +msgid "Pinned to all desktops" +msgstr "Vastgemaakt op alle bureaubladen" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Which virtual desktop a window is currently on" +msgid "Available on all activities" +msgstr "Actief op alle activiteiten" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Activities a window is currently on (apart from the current one)" +msgid "Also available on %1" +msgstr "Ook actief op %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Which activities a window is currently on" +msgid "Available on %1" +msgstr "Actief op %1" + +#~ msgid "Colorize buttons" +#~ msgstr "Knoppen verkleuren" + +#~ msgid "Indicator Limit:" +#~ msgstr "Indicatorlimiet:" diff --git a/package/translate/template.pot b/package/translate/template.pot new file mode 100644 index 00000000..e880a2a5 --- /dev/null +++ b/package/translate/template.pot @@ -0,0 +1,688 @@ +# Translation of Fancy Tasks in LANGUAGE +# Copyright (C) 2023 +# This file is distributed under the same license as the Fancy Tasks package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Fancy Tasks\n" +"Report-Msgid-Bugs-To: https://userbase.kde.org/Plasma/Tasks\n" +"POT-Creation-Date: 2023-08-23 17:30-0600\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../contents/config/config.qml +msgid "Appearance" +msgstr "" + +#: ../contents/config/config.qml +msgid "Behavior" +msgstr "" + +#: ../contents/config/config.qml +msgid "Indicators" +msgstr "" + +#: ../contents/ui/Badge.qml +msgctxt "Invalid number of new messages, overlay, keep short" +msgid "—" +msgstr "" + +#: ../contents/ui/Badge.qml +msgctxt "Over 9999 new messages, overlay, keep short" +msgid "9,999+" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "General:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Show tooltips" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Highlight windows when hovering over task tooltips" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Mark applications that play audio" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Use plasma borders" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Button Colors:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Using Plasma Style/Accent" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Using Color Overlay" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Use dominant icon color" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Custom Color:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Colorize inactive buttons" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Plasma Button Decorations:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Disable" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Plasma Button Direction:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Override" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Be sure to use this when using as a floating widget" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "North" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "South" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "West" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "East" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Maximum columns:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Maximum rows:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Always arrange tasks in rows of as many columns" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Always arrange tasks in columns of as many rows" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Maximum button length (px):" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Space between taskbar items (px):" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Press OK to fix layout issues." +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Spacing between icons:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Small" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Normal" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Large" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" +msgid "Automatically set to Large when in Touch Mode" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Display:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Show task names" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Show icons only" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Group:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Do not group" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "By program name" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Clicking grouped task:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Completes the sentence 'Clicking grouped task cycles through tasks' " +msgid "Cycles through tasks" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Completes the sentence 'Clicking grouped task shows tooltip window thumbnails' " +msgid "Shows tooltip window thumbnails" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Completes the sentence 'Clicking grouped task shows windows side by side' " +msgid "Shows windows side by side" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Completes the sentence 'Clicking grouped task shows textual list' " +msgid "Shows textual list" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Tooltips are disabled, so the windows will be displayed side by side instead." +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Tooltips are disabled, and the compositor does not support displaying windows side by side, so a textual list will be displayed instead" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "The compositor does not support displaying windows side by side, so a textual list will be displayed instead." +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Combine into single button" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Group only when the Task Manager is full" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Sort:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Do not sort" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Manually" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Alphabetically" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "By desktop" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "By activity" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Keep launchers separate" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgid "Clicking active task:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgid "Minimizes the task" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Middle-clicking any task:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task does nothing'" +msgid "Does nothing" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task closes window or group'" +msgid "Closes window or group" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task opens a new window'" +msgid "Opens a new window" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" +msgid "Minimizes/Restores window or group" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task toggles grouping'" +msgid "Toggles grouping" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" +msgid "Brings it to the current virtual desktop" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgid "Mouse wheel:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgid "Cycles through tasks" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Skip minimized tasks" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Show only tasks:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "From current screen" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "From current desktop" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "From current activity" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "That are minimized" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "When panel is hidden:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Unhide when a window wants attention" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "New tasks appear:" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "To the right" +msgstr "" + +#: ../contents/ui/ConfigBehavior.qml +msgid "To the left" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicators:" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Disabled" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Enabled" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Group Overlay:" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Takes effect on next time plasma groups tasks." +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Animate Indicators:" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Location:" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Reverse shown side" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Override location" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Bottom" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Left" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Right" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Top" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Style:" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Metro" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Ciliora" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Dashes" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Min Limit:" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Max Limit:" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Minimize Options:" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Desaturate" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Shrink when minimized" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Growth/Shrink factor:" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator size (px):" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator length (px):" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Radius (%):" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator margin (px):" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Color:" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Use plasma accent color" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Places" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Recent Files" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Actions" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Play previous track" +msgid "Previous Track" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Pause playback" +msgid "Pause" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Start playback" +msgid "Play" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Play next track" +msgid "Next Track" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Stop playback" +msgid "Stop" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Quit media player app" +msgid "Quit" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Open or bring to the front window of media player app" +msgid "Restore" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Mute" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Open New Window" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Move to &Desktop" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Move &To Current Desktop" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "&All Desktops" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgctxt "1 = number of desktop, 2 = desktop name" +msgid "&%1 %2" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "&New Desktop" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Show in &Activities" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Add To Current Activity" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "All Activities" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Move to %1" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "&Pin to Task Manager" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "On All Activities" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "On The Current Activity" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Unpin from Task Manager" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "More" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "&Move" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Re&size" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Ma&ximize" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Mi&nimize" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Keep &Above Others" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Keep &Below Others" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "&Fullscreen" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "&Shade" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "Allow this program to be grouped" +msgstr "" + +#: ../contents/ui/ContextMenu.qml +msgid "&Close" +msgstr "" + +#: ../contents/ui/Task.qml +msgid "Activate %1" +msgstr "" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "button to unmute app" +msgid "Unmute %1" +msgstr "" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "button to mute app" +msgid "Mute %1" +msgstr "" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Accessibility data on volume slider" +msgid "Adjust volume for %1" +msgstr "" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "volume percentage" +msgid "%1%" +msgstr "" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "only used for sizing, should be widest possible string" +msgid "100%" +msgstr "" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Comma-separated list of desktops" +msgid "On %1" +msgstr "" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Comma-separated list of desktops" +msgid "Pinned to all desktops" +msgstr "" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Which virtual desktop a window is currently on" +msgid "Available on all activities" +msgstr "" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Activities a window is currently on (apart from the current one)" +msgid "Also available on %1" +msgstr "" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Which activities a window is currently on" +msgid "Available on %1" +msgstr "" diff --git a/package/translate/zh_CN.po b/package/translate/zh_CN.po new file mode 100644 index 00000000..5e28224b --- /dev/null +++ b/package/translate/zh_CN.po @@ -0,0 +1,694 @@ +# Translation of fancytasks in zh_CN +# Copyright (C) 2023 +# This file is distributed under the same license as the fancytasks package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: fancytasks\n" +"Report-Msgid-Bugs-To: https://userbase.kde.org/Plasma/Tasks\n" +"POT-Creation-Date: 2023-08-23 17:30-0600\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../contents/config/config.qml +msgid "Appearance" +msgstr "外观" + +#: ../contents/config/config.qml +msgid "Behavior" +msgstr "行为" + +#: ../contents/config/config.qml +msgid "Indicators" +msgstr "指示器" + +#: ../contents/ui/Badge.qml +msgctxt "Invalid number of new messages, overlay, keep short" +msgid "—" +msgstr "-" + +#: ../contents/ui/Badge.qml +msgctxt "Over 9999 new messages, overlay, keep short" +msgid "9,999+" +msgstr "9,999+" + +#: ../contents/ui/ConfigAppearance.qml +msgid "General:" +msgstr "通用:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Show tooltips" +msgstr "显示窗口预览" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Highlight windows when hovering over task tooltips" +msgstr "悬浮在预览上时高亮对应窗口" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Mark applications that play audio" +msgstr "标记正在播放音频的应用" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Use plasma borders" +msgstr "使用plasma边框" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Button Colors:" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Using Plasma Style/Accent" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Using Color Overlay" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Use dominant icon color" +msgstr "使用图标主体色" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Custom Color:" +msgstr "自定义颜色:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Colorize inactive buttons" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Plasma Button Decorations:" +msgstr "Plasma按钮装饰:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Disable" +msgstr "关闭" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Plasma Button Direction:" +msgstr "Plasma按钮方向" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Override" +msgstr "覆盖" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Be sure to use this when using as a floating widget" +msgstr "作为浮动组件使用时需要设置" + +#: ../contents/ui/ConfigAppearance.qml +msgid "North" +msgstr "北" + +#: ../contents/ui/ConfigAppearance.qml +msgid "South" +msgstr "南" + +#: ../contents/ui/ConfigAppearance.qml +msgid "West" +msgstr "西" + +#: ../contents/ui/ConfigAppearance.qml +msgid "East" +msgstr "东" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Maximum columns:" +msgstr "最大列数" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Maximum rows:" +msgstr "最大行数" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Always arrange tasks in rows of as many columns" +msgstr "始终将任务排列成多列" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Always arrange tasks in columns of as many rows" +msgstr "始终将任务排列成多行" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Maximum button length (px):" +msgstr "最大按钮长度(px)" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Space between taskbar items (px):" +msgstr "任务栏组件间距(px)" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Press OK to fix layout issues." +msgstr "按OK键来修复布局问题。" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Spacing between icons:" +msgstr "图标间距:" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Small" +msgstr "小" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Normal" +msgstr "中" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Large" +msgstr "大" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" +msgid "Automatically set to Large when in Touch Mode" +msgstr "触摸模式下自动设置为大" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Display:" +msgstr "显示:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Show task names" +msgstr "显示任务名称" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Show icons only" +msgstr "只显示图标" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Group:" +msgstr "分组:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Do not group" +msgstr "不分组:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "By program name" +msgstr "以程序名分组" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Clicking grouped task:" +msgstr "点击已分组任务时:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Completes the sentence 'Clicking grouped task cycles through tasks' " +msgid "Cycles through tasks" +msgstr "在任务中循环" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Completes the sentence 'Clicking grouped task shows tooltip window thumbnails' " +msgid "Shows tooltip window thumbnails" +msgstr "展示窗口预览" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Completes the sentence 'Clicking grouped task shows windows side by side' " +msgid "Shows windows side by side" +msgstr "并列显示窗口" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Completes the sentence 'Clicking grouped task shows textual list' " +msgid "Shows textual list" +msgstr "展示文字列表" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Tooltips are disabled, so the windows will be displayed side by side instead." +msgstr "窗口预览已关闭,所有窗口会被并列显示" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Tooltips are disabled, and the compositor does not support displaying windows side by side, so a textual list will be displayed instead" +msgstr "窗口预览已关闭,混成器不支持并列显示窗口,展示文字列表" + +#: ../contents/ui/ConfigBehavior.qml +msgid "The compositor does not support displaying windows side by side, so a textual list will be displayed instead." +msgstr "混成器不支持并列显示窗口,展示文字列表" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Combine into single button" +msgstr "组合到一个按钮中" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Group only when the Task Manager is full" +msgstr "仅在任务栏已满时组合" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Sort:" +msgstr "排序:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Do not sort" +msgstr "不排序" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Manually" +msgstr "手动" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Alphabetically" +msgstr "按字母" + +#: ../contents/ui/ConfigBehavior.qml +msgid "By desktop" +msgstr "按桌面" + +#: ../contents/ui/ConfigBehavior.qml +msgid "By activity" +msgstr "按活动" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Keep launchers separate" +msgstr "与启动器分开" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgid "Clicking active task:" +msgstr "点击活动任务时:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgid "Minimizes the task" +msgstr "最小化" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Middle-clicking any task:" +msgstr "鼠标中键点击活动任务时:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task does nothing'" +msgid "Does nothing" +msgstr "什么都不做" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task closes window or group'" +msgid "Closes window or group" +msgstr "关闭窗口或组" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task opens a new window'" +msgid "Opens a new window" +msgstr "打开新窗口" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" +msgid "Minimizes/Restores window or group" +msgstr "最小化/最大化窗口或组" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task toggles grouping'" +msgid "Toggles grouping" +msgstr "切换组" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" +msgid "Brings it to the current virtual desktop" +msgstr "带到当前虚拟桌面" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgid "Mouse wheel:" +msgstr "鼠标滚轮:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgid "Cycles through tasks" +msgstr "在任务间切换" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Skip minimized tasks" +msgstr "跳过最小化的任务" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Show only tasks:" +msgstr "只展示任务" + +#: ../contents/ui/ConfigBehavior.qml +msgid "From current screen" +msgstr "从当前屏幕" + +#: ../contents/ui/ConfigBehavior.qml +msgid "From current desktop" +msgstr "从当前桌面" + +#: ../contents/ui/ConfigBehavior.qml +msgid "From current activity" +msgstr "从当前活动" + +#: ../contents/ui/ConfigBehavior.qml +msgid "That are minimized" +msgstr "最小化的任务" + +#: ../contents/ui/ConfigBehavior.qml +msgid "When panel is hidden:" +msgstr "面板隐藏时:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Unhide when a window wants attention" +msgstr "当窗口提示时取消隐藏" + +#: ../contents/ui/ConfigBehavior.qml +msgid "New tasks appear:" +msgstr "新任务出现在:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "To the right" +msgstr "右边" + +#: ../contents/ui/ConfigBehavior.qml +msgid "To the left" +msgstr "左边" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicators:" +msgstr "指示器:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Disabled" +msgstr "关闭" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Enabled" +msgstr "打开" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Group Overlay:" +msgstr "分组覆盖" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Takes effect on next time plasma groups tasks." +msgstr "在下一次plasma组合任务时生效" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Animate Indicators:" +msgstr "动态指示器" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Location:" +msgstr "指示器位置:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Reverse shown side" +msgstr "切换显示位置" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Override location" +msgstr "覆盖位置" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Bottom" +msgstr "底部" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Left" +msgstr "左边" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Right" +msgstr "右边" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Top" +msgstr "顶部" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Style:" +msgstr "指示器风格" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Metro" +msgstr "Metro" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Ciliora" +msgstr "Ciliora" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Dashes" +msgstr "Dashes" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Min Limit:" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Max Limit:" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Minimize Options:" +msgstr "最小化选项:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Desaturate" +msgstr "降低饱和度" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Shrink when minimized" +msgstr "最小化时收缩" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Growth/Shrink factor:" +msgstr "增长/收缩因数" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator size (px):" +msgstr "指示器大小(px):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator length (px):" +msgstr "指示器长度(px):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Radius (%):" +msgstr "指示器圆角(%):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator margin (px):" +msgstr "指示器间距(px)" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Color:" +msgstr "指示器颜色:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Use plasma accent color" +msgstr "使用plasma预设" + +#: ../contents/ui/ContextMenu.qml +msgid "Places" +msgstr "位置" + +#: ../contents/ui/ContextMenu.qml +msgid "Recent Files" +msgstr "最近的文件" + +#: ../contents/ui/ContextMenu.qml +msgid "Actions" +msgstr "动作" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Play previous track" +msgid "Previous Track" +msgstr "上一首" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Pause playback" +msgid "Pause" +msgstr "暂停" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Start playback" +msgid "Play" +msgstr "播放" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Play next track" +msgid "Next Track" +msgstr "下一首" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Stop playback" +msgid "Stop" +msgstr "停止" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Quit media player app" +msgid "Quit" +msgstr "退出" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Open or bring to the front window of media player app" +msgid "Restore" +msgstr "恢复" + +#: ../contents/ui/ContextMenu.qml +msgid "Mute" +msgstr "静音" + +#: ../contents/ui/ContextMenu.qml +msgid "Open New Window" +msgstr "打开新窗口" + +#: ../contents/ui/ContextMenu.qml +msgid "Move to &Desktop" +msgstr "移动到桌面" + +#: ../contents/ui/ContextMenu.qml +msgid "Move &To Current Desktop" +msgstr "移动到当前桌面" + +#: ../contents/ui/ContextMenu.qml +msgid "&All Desktops" +msgstr "所有桌面" + +#: ../contents/ui/ContextMenu.qml +msgctxt "1 = number of desktop, 2 = desktop name" +msgid "&%1 %2" +msgstr "&%1 %2" + +#: ../contents/ui/ContextMenu.qml +msgid "&New Desktop" +msgstr "新建桌面" + +#: ../contents/ui/ContextMenu.qml +msgid "Show in &Activities" +msgstr "在活动中展示" + +#: ../contents/ui/ContextMenu.qml +msgid "Add To Current Activity" +msgstr "添加到当前活动" + +#: ../contents/ui/ContextMenu.qml +msgid "All Activities" +msgstr "所有活动" + +#: ../contents/ui/ContextMenu.qml +msgid "Move to %1" +msgstr "移动到%1" + +#: ../contents/ui/ContextMenu.qml +msgid "&Pin to Task Manager" +msgstr "固定到任务栏" + +#: ../contents/ui/ContextMenu.qml +msgid "On All Activities" +msgstr "在所有活动中" + +#: ../contents/ui/ContextMenu.qml +msgid "On The Current Activity" +msgstr "在当前活动中" + +#: ../contents/ui/ContextMenu.qml +msgid "Unpin from Task Manager" +msgstr "从任务栏上解除固定" + +#: ../contents/ui/ContextMenu.qml +msgid "More" +msgstr "更多" + +#: ../contents/ui/ContextMenu.qml +msgid "&Move" +msgstr "移动" + +#: ../contents/ui/ContextMenu.qml +msgid "Re&size" +msgstr "调整大小" + +#: ../contents/ui/ContextMenu.qml +msgid "Ma&ximize" +msgstr "最大化" + +#: ../contents/ui/ContextMenu.qml +msgid "Mi&nimize" +msgstr "最小化" + +#: ../contents/ui/ContextMenu.qml +msgid "Keep &Above Others" +msgstr "置顶" + +#: ../contents/ui/ContextMenu.qml +msgid "Keep &Below Others" +msgstr "置底" + +#: ../contents/ui/ContextMenu.qml +msgid "&Fullscreen" +msgstr "全屏" + +#: ../contents/ui/ContextMenu.qml +msgid "&Shade" +msgstr "折叠" + +#: ../contents/ui/ContextMenu.qml +msgid "Allow this program to be grouped" +msgstr "允许这个程序被分组" + +#: ../contents/ui/ContextMenu.qml +msgid "&Close" +msgstr "关闭" + +#: ../contents/ui/Task.qml +msgid "Activate %1" +msgstr "活动 %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "button to unmute app" +msgid "Unmute %1" +msgstr "取消 %1 的静音" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "button to mute app" +msgid "Mute %1" +msgstr "静音 %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Accessibility data on volume slider" +msgid "Adjust volume for %1" +msgstr "调整 %1 的音量" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "volume percentage" +msgid "%1%" +msgstr "%1%" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "only used for sizing, should be widest possible string" +msgid "100%" +msgstr "100%" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Comma-separated list of desktops" +msgid "On %1" +msgstr "在 %1 上" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Comma-separated list of desktops" +msgid "Pinned to all desktops" +msgstr "固定到所有桌面" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Which virtual desktop a window is currently on" +msgid "Available on all activities" +msgstr "在所有活动上可用" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Activities a window is currently on (apart from the current one)" +msgid "Also available on %1" +msgstr "也在 %1 上可用" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Which activities a window is currently on" +msgid "Available on %1" +msgstr "在 %1 上可用" + +#~ msgid "Colorize buttons" +#~ msgstr "彩色按钮" + +#~ msgid "Indicator Limit:" +#~ msgstr "指示器限制:" From ea2b54d7523fa914c78676fda9196f09a6ecebbe Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 23 Aug 2023 17:35:02 -0600 Subject: [PATCH 056/141] change name to Id --- package/translate/build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/translate/build b/package/translate/build index 3bdb127e..2506e32c 100644 --- a/package/translate/build +++ b/package/translate/build @@ -6,7 +6,7 @@ # Eg: contents/locale/fr_CA/LC_MESSAGES/plasma_applet_org.kde.plasma.eventcalendar.mo DIR=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd` -plasmoidName=`python3 jsonParse.py $DIR/../metadata.json KPlugin.Name` +plasmoidName=`python3 jsonParse.py $DIR/../metadata.json KPlugin.Id` website=`python3 jsonParse.py $DIR/../metadata.json KPlugin.Website` bugAddress="$website" packageRoot=".." # Root of translatable sources From 90a98cb3e039d4de5b182222ad0ef54832096d2f Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 23 Aug 2023 17:39:09 -0600 Subject: [PATCH 057/141] Update website, change to id, purge remnants --- ...> plasma_applet_alexankitty.fancytasks.mo} | Bin 11643 -> 11647 bytes ...> plasma_applet_alexankitty.fancytasks.mo} | Bin 10785 -> 10789 bytes package/metadata.json | 2 +- package/translate/nl.po | 4 ++-- package/translate/template.pot | 4 ++-- package/translate/zh_CN.po | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) rename package/contents/locale/nl/LC_MESSAGES/{plasma_applet_Fancy Tasks.mo => plasma_applet_alexankitty.fancytasks.mo} (88%) rename package/contents/locale/zh_CN/LC_MESSAGES/{plasma_applet_Fancy Tasks.mo => plasma_applet_alexankitty.fancytasks.mo} (86%) diff --git a/package/contents/locale/nl/LC_MESSAGES/plasma_applet_Fancy Tasks.mo b/package/contents/locale/nl/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo similarity index 88% rename from package/contents/locale/nl/LC_MESSAGES/plasma_applet_Fancy Tasks.mo rename to package/contents/locale/nl/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo index e5a4db92b6701bf61d7a2898deec51fef873bd21..f7a0aa011ed51c6e33f4672509079e5167dc6fcd 100644 GIT binary patch delta 1277 zcmXZbPe@cz6vy!s>FAh^|C-9u9H+ly)&#{A#jKQyk`@sWCfO*WW2O}*nZ*;5D2Q4_ zZHgcllE^?X15pqXg^OIcvB*sY6_vDzc9B%y-^>N^bMJZYoqNu`cm6d0YkvGW&pW)x zELdY!Zf0E}vqBugQXIizyn|&pimNb#ew;xc&f$Lii1`?)H7mdxK9KwEMj*(IC63Y@__{N&=_T)dd9Rm4N+!#Jw5M%0vMUAkY;TJ zbtEa|2WM0Db|~B7cLM5c0d<)ww&c#Z5{sF~P=z(1A6s2KiMk^Ls7pGO9`}z2t2&eY iUFX}jw)dTmCVDz9BzjLJ`}+r@dlS9wgX!*?vcP`>5{FL! delta 1273 zcmXZbPe@cz6vy$Ce`iJ;n`+8`>1f#>$5a$5+b9Gf1R@b6TEUc43rB+)$|B)O6htke zHbsz&h-6kXAO#^&xX6VYjb>9pL?$hwT_6?I_cwDv{M>imyXT&B@11|ce}=QGCEmaW zvv8x?W-}X&nE7xLH{mo^;yn!E4Ax>6{kVi>n8SYjgr(ThWLAz*)N?oPz#i21CsBFN zG?|xQXpBIFz!Yks$EbobSd9zVi65~WE1S*uvp)U>@Ejh-3Dg27vsMN_3DjWCPFFETcj@Jf!oo;I(*>bbEqA8>)tP;I{c0*;1{Z};$3Dz z450GXcntI+iki@cTBz53a2%Cj6tzGSD{u<;;4Rb+WKj*w;~~sp6$V=h3pJn$??lD> zQQvz*?nTlCZle-DMJ<%UVw^{9-D~GE>Mnf2Qv8eRtY~+k&=9J?I@H-8K`j`=ZFmit z=h=M*n)ndeC7Z=9xP&G6*~M2~+(*`W;`LaDJ*dw5P-i}bTQP>ZJD1(_UCcLznwLR8 z>)Q(kI*T_*6ZQ^u1nU^ZioJzI2T=(IaUYJL7P^VriAShB&rwIUh(26#en55p6*ccS z23g;#$fmPzK;7~vD#0mKA?Hzvuc8v%L3Qv1wNq&qe}&qK_ZY?>?zyP7POQjcO;3rq?2=Le>z-!DHTti cjiuu4W25o*i^&TegNaybJk~Kc(HIK;2YGgb>i_@% diff --git a/package/contents/locale/zh_CN/LC_MESSAGES/plasma_applet_Fancy Tasks.mo b/package/contents/locale/zh_CN/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo similarity index 86% rename from package/contents/locale/zh_CN/LC_MESSAGES/plasma_applet_Fancy Tasks.mo rename to package/contents/locale/zh_CN/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo index 13d35cebeae3fda9dbcb8dc2f086a58699e15bd6..89afefdbee214f1a79980dd703928eafdd04af2c 100644 GIT binary patch delta 1277 zcmXZbPe@cz6vy!^Gfp#O(ci)Tn9f-K>z_mrXp3xPkQEHM2*hBrp{8t#8YzjG48l#( zB1DiN3>tDk3WTCyAZcMxq>G}BxS0%^O-X@^O8WkMXZ3mK+1j{fxgFOmIqx~V4GJUj4H6! zjG22;1rDJKbf9kJq~))nu6O`-6GNzt7t9&lL|jDG|A(6~yK1|0l{_?}5^bnPU8qJ$ zEW<0P6K2dCs0Oz!9zv~qXmJj?WjBthJB_MWG8eI&{?1?LEes<$w*ghS1=a8<>Q$V; z3QVC+&}ZX!Z2T_z$UjD{&zY}K^FN^K&6>q!dH*FIw6g`&H?V{{NoBnk$4~`ZQH72n zKaA_P_$F%pJ=DBm%jYpb{MwvE9poKq-W-PL?-ulce=v&Wyubj~qc*l1)wmV4@Q96f zTmFpYGZqh8JZ$F80_uP>sD9rut1J7(!&Y2GHHtKP8>lmPAwzB-Y6D%^f@vFnYCgj_ z`4_k!gH2wYgQ$9!tTaUKE!B_jAm9bh&5FH z7lzT#GVR=oTd@l@?+|Xo0doX55Z^)VcOSd3Xz>U06KefJ%;oEYFC^6R4{XAJs6tI~ z=OWmF&De)(s2?@|l$kXr&1tiYYUDMlv9}g~HW%Z0uahMbI^lOzXMa$4w5G$`Ab{Fn zy%{xkq2?bzt?x(ONXqg#)J;yHZej}6c*UI0GuT3+iYo9ITQS(_+-B@V#eJwkgQ!Aj z^x-J#gjw?{s=y74r%>zeSzJUe*OgKG=I0n_!FA;(}R{)OQsII^jI3@Hfv4!{}s_`WZ;wtKE_wVF~5!AZq mOgUH%N3P^D<7d*jOz*|BnclJSbBW_4>D;AsVrI1MRr7z(pn*^T diff --git a/package/metadata.json b/package/metadata.json index 87f410d3..1202cce4 100644 --- a/package/metadata.json +++ b/package/metadata.json @@ -171,7 +171,7 @@ "Plasma/Applet" ], "Version": "4.0", - "Website": "https://userbase.kde.org/Plasma/Tasks" + "Website": "https://github.com/alexankitty/FancyTasks" }, "X-Plasma-API": "declarativeappletscript", "X-Plasma-MainScript": "ui/main.qml", diff --git a/package/translate/nl.po b/package/translate/nl.po index 43ab6ae3..7806975c 100644 --- a/package/translate/nl.po +++ b/package/translate/nl.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" -"Report-Msgid-Bugs-To: https://userbase.kde.org/Plasma/Tasks\n" -"POT-Creation-Date: 2023-08-23 17:30-0600\n" +"Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" +"POT-Creation-Date: 2023-08-23 17:38-0600\n" "PO-Revision-Date: 2023-07-13 22:27+0200\n" "Last-Translator: Heimen Stoffels \n" "Language-Team: \n" diff --git a/package/translate/template.pot b/package/translate/template.pot index e880a2a5..80af319a 100644 --- a/package/translate/template.pot +++ b/package/translate/template.pot @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: Fancy Tasks\n" -"Report-Msgid-Bugs-To: https://userbase.kde.org/Plasma/Tasks\n" -"POT-Creation-Date: 2023-08-23 17:30-0600\n" +"Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" +"POT-Creation-Date: 2023-08-23 17:38-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/package/translate/zh_CN.po b/package/translate/zh_CN.po index 5e28224b..4f91696e 100644 --- a/package/translate/zh_CN.po +++ b/package/translate/zh_CN.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" -"Report-Msgid-Bugs-To: https://userbase.kde.org/Plasma/Tasks\n" -"POT-Creation-Date: 2023-08-23 17:30-0600\n" +"Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" +"POT-Creation-Date: 2023-08-23 17:38-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" From c4ea97f5df203a6625a42d1ca39f051db5977419 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Wed, 23 Aug 2023 17:42:59 -0600 Subject: [PATCH 058/141] Update README.MD --- README.MD | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.MD b/README.MD index 2f789168..20cfd7b5 100644 --- a/README.MD +++ b/README.MD @@ -45,7 +45,10 @@ Features improvements tweaks and options to the original task manager plasmoid m * Allow changing of animation duration, and possibly animating of button color and frame transitions. * Change styles (Metro, Ciliora, Dashes) to presets, switch preset to custom when modifying settings. Add in Dots as a preset. * Fix naming conventions to be more clear to users. -* Translations. + +## Translation Help Wanted! +Information regarding submitting translations is available [here](https://github.com/alexankitty/FancyTasks/blob/main/package/translate/ReadMe.md). +Important note: Any time an update to strings is made, the translations need to be merged and a new po template needs to be created. ## Pictures Colorful Tasks From d3749791aba8261a892729797266ded392bfbf3b Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Wed, 23 Aug 2023 17:48:32 -0600 Subject: [PATCH 059/141] metadata.json translate info --- README.MD | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.MD b/README.MD index 20cfd7b5..c11a1b41 100644 --- a/README.MD +++ b/README.MD @@ -48,7 +48,8 @@ Features improvements tweaks and options to the original task manager plasmoid m ## Translation Help Wanted! Information regarding submitting translations is available [here](https://github.com/alexankitty/FancyTasks/blob/main/package/translate/ReadMe.md). -Important note: Any time an update to strings is made, the translations need to be merged and a new po template needs to be created. +Important note: Any time an update to strings is made, the translations need to be merged and a new po template needs to be created. +Finally, the metadata.json is done separately. ## Pictures Colorful Tasks From 4422ebb8cde8fda0ae726def9e881ef5a82d9bdc Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 23 Aug 2023 17:50:55 -0600 Subject: [PATCH 060/141] fix comment on nl.po --- package/translate/nl.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/translate/nl.po b/package/translate/nl.po index 7806975c..7ade54d4 100644 --- a/package/translate/nl.po +++ b/package/translate/nl.po @@ -1,4 +1,4 @@ -# Translation of fancytasks in LANGUAGE +# Translation of fancytasks in nl # Copyright (C) 2023 # This file is distributed under the same license as the fancytasks package. # FIRST AUTHOR , YEAR. From beed41ae3660eda696536f79b94dd08e7e98c529 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 23 Aug 2023 18:13:44 -0600 Subject: [PATCH 061/141] Update scripts --- install.sh | 2 ++ package/translate/build | 4 ++-- package/translate/merge | 4 ++-- update.sh | 6 +++++- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/install.sh b/install.sh index 25b52eea..2d1ffc85 100755 --- a/install.sh +++ b/install.sh @@ -1,5 +1,7 @@ #!/bin/sh SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +sh $SCRIPT_DIR/package/translate/merge +sh $SCRIPT_DIR/package/translate/build kpackagetool5 -i $SCRIPT_DIR/package mkdir -p ~/.local/share/icons/hicolor/256x256/apps/ cp ./FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png diff --git a/package/translate/build b/package/translate/build index 2506e32c..93c29fa9 100644 --- a/package/translate/build +++ b/package/translate/build @@ -6,8 +6,8 @@ # Eg: contents/locale/fr_CA/LC_MESSAGES/plasma_applet_org.kde.plasma.eventcalendar.mo DIR=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd` -plasmoidName=`python3 jsonParse.py $DIR/../metadata.json KPlugin.Id` -website=`python3 jsonParse.py $DIR/../metadata.json KPlugin.Website` +plasmoidName=`python3 $DIR/jsonParse.py $DIR/../metadata.json KPlugin.Id` +website=`python3 $DIR/jsonParse.py $DIR/../metadata.json KPlugin.Website` bugAddress="$website" packageRoot=".." # Root of translatable sources projectName="plasma_applet_${plasmoidName}" # project name diff --git a/package/translate/merge b/package/translate/merge index 4f03c601..7aa879ba 100644 --- a/package/translate/merge +++ b/package/translate/merge @@ -6,9 +6,9 @@ # https://invent.kde.org/sysadmin/l10n-scripty/-/blob/master/extract-messages.sh DIR=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd` -plasmoidName=`python3 jsonParse.py $DIR/../metadata.json KPlugin.Name` +plasmoidName=`python3 $DIR/jsonParse.py $DIR/../metadata.json KPlugin.Name` widgetName="${plasmoidName##*.}" # Strip namespace -website=`python3 jsonParse.py $DIR/../metadata.json KPlugin.Website` +website=`python3 $DIR/jsonParse.py $DIR/../metadata.json KPlugin.Website` bugAddress="$website" packageRoot=".." # Root of translatable sources projectName="plasma_applet_${plasmoidName}" # project name diff --git a/update.sh b/update.sh index b17db48f..6a61a375 100755 --- a/update.sh +++ b/update.sh @@ -1,6 +1,10 @@ #!/bin/sh SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +cd $SCRIPT_DIR/package/translate/ +sh ./merge +sh ./build +cd $SCRIPT_DIR kpackagetool5 -u $SCRIPT_DIR/package -kquitapp5 plasmashell +killall plasmashell kstart5 plasmashell cp ./FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png \ No newline at end of file From e1b6f5f163a4eb7e2c11a75122c70f24e4d1d5e1 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Wed, 23 Aug 2023 18:33:51 -0600 Subject: [PATCH 062/141] Update README.MD --- README.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.MD b/README.MD index c11a1b41..27afe613 100644 --- a/README.MD +++ b/README.MD @@ -7,7 +7,7 @@ Development of this project has more or less resumed. Help is always wanted and ## Installing -If your distro does not include kirigami2, install it now. It's required for the settings, and used for the dominant icon color effect. +If your distro does not include kirigami2, install it now. It's required for the settings, and used for the dominant icon color effect. Python3 is required for installing. 1. Clone this repository with the following command `git clone https://github.com/alexankitty/FancyTasks` 2. CD into the folder and run the script `install.sh`, you may need to chmod +x or prepend your shell before the script in order to run it From a4581895a593fa08a0a06418dc1ae556caaaad4d Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 23 Aug 2023 18:36:04 -0600 Subject: [PATCH 063/141] add plasmoidlocaletest --- package/translate/plasmoidlocaletest | 181 +++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 package/translate/plasmoidlocaletest diff --git a/package/translate/plasmoidlocaletest b/package/translate/plasmoidlocaletest new file mode 100644 index 00000000..5cd76a21 --- /dev/null +++ b/package/translate/plasmoidlocaletest @@ -0,0 +1,181 @@ +#!/bin/bash +# Version 9 +# Requires plasmoidviewer v5.13.0 + +function checkIfLangInstalled { + if [ -x "$(command -v dpkg)" ]; then + dpkg -l ${1} >/dev/null 2>&1 || ( \ + echo -e "${1} not installed.\nInstalling now before continuing.\n" \ + ; sudo apt install ${1} \ + ) || ( \ + echo -e "\nError trying to install ${1}\nPlease run 'sudo apt install ${1}'\n" \ + ; exit 1 \ + ) + elif [ -x "$(command -v pacman)" ]; then + # TODO: run `locale -a` and check if the locale is enabled. + if false; then + # https://wiki.archlinux.org/index.php/Locale + # Uncomment the locale in /etc/locale.gen + # Then run `locale-gen` + echo -e "\nPlease install this locale in System Settings first.\n" + exit 1 + else + echo "" + fi + else + echo -e "\nPackage manager not recognized. If the widget is not translated, please install the package '${1}'\n" + fi +} + +langInput="${1}" +lang="" +languagePack="" + +if [[ "$langInput" =~ ":" ]]; then # String contains a colon so assume it's a locale code. + lang="${langInput}" + IFS=: read -r l1 l2 <<< "${lang}" + languagePack="language-pack-${l2}" +fi + +# https://stackoverflow.com/questions/3191664/list-of-all-locales-and-their-short-codes/28357857#28357857 +declare -a langArr=( + "af_ZA:af:Afrikaans (South Africa)" + "ak_GH:ak:Akan (Ghana)" + "am_ET:am:Amharic (Ethiopia)" + "ar_EG:ar:Arabic (Egypt)" + "as_IN:as:Assamese (India)" + "az_AZ:az:Azerbaijani (Azerbaijan)" + "be_BY:be:Belarusian (Belarus)" + "bem_ZM:bem:Bemba (Zambia)" + "bg_BG:bg:Bulgarian (Bulgaria)" + "bo_IN:bo:Tibetan (India)" + "bs_BA:bs:Bosnian (Bosnia and Herzegovina)" + "ca_ES:ca:Catalan (Spain)" + "chr_US:ch:Cherokee (United States)" + "cs_CZ:cs:Czech (Czech Republic)" + "cy_GB:cy:Welsh (United Kingdom)" + "da_DK:da:Danish (Denmark)" + "de_DE:de:German (Germany)" + "el_GR:el:Greek (Greece)" + "es_MX:es:Spanish (Mexico)" + "et_EE:et:Estonian (Estonia)" + "eu_ES:eu:Basque (Spain)" + "fa_IR:fa:Persian (Iran)" + "ff_SN:ff:Fulah (Senegal)" + "fi_FI:fi:Finnish (Finland)" + "fo_FO:fo:Faroese (Faroe Islands)" + "fr_CA:fr:French (Canada)" + "ga_IE:ga:Irish (Ireland)" + "gl_ES:gl:Galician (Spain)" + "gu_IN:gu:Gujarati (India)" + "gv_GB:gv:Manx (United Kingdom)" + "ha_NG:ha:Hausa (Nigeria)" + "he_IL:he:Hebrew (Israel)" + "hi_IN:hi:Hindi (India)" + "hr_HR:hr:Croatian (Croatia)" + "hu_HU:hu:Hungarian (Hungary)" + "hy_AM:hy:Armenian (Armenia)" + "id_ID:id:Indonesian (Indonesia)" + "ig_NG:ig:Igbo (Nigeria)" + "is_IS:is:Icelandic (Iceland)" + "it_IT:it:Italian (Italy)" + "ja_JP:ja:Japanese (Japan)" + "ka_GE:ka:Georgian (Georgia)" + "kk_KZ:kk:Kazakh (Kazakhstan)" + "kl_GL:kl:Kalaallisut (Greenland)" + "km_KH:km:Khmer (Cambodia)" + "kn_IN:kn:Kannada (India)" + "ko_KR:ko:Korean (South Korea)" + "ko_KR:ko:Korean (South Korea)" + "lg_UG:lg:Ganda (Uganda)" + "lt_LT:lt:Lithuanian (Lithuania)" + "lv_LV:lv:Latvian (Latvia)" + "mg_MG:mg:Malagasy (Madagascar)" + "mk_MK:mk:Macedonian (Macedonia)" + "ml_IN:ml:Malayalam (India)" + "mr_IN:mr:Marathi (India)" + "ms_MY:ms:Malay (Malaysia)" + "mt_MT:mt:Maltese (Malta)" + "my_MM:my:Burmese (Myanmar [Burma])" + "nb_NO:nb:Norwegian Bokmål (Norway)" + "ne_NP:ne:Nepali (Nepal)" + "nl_NL:nl:Dutch (Netherlands)" + "nn_NO:nn:Norwegian Nynorsk (Norway)" + "om_ET:om:Oromo (Ethiopia)" + "or_IN:or:Oriya (India)" + "pa_PK:pa:Punjabi (Pakistan)" + "pl_PL:pl:Polish (Poland)" + "ps_AF:ps:Pashto (Afghanistan)" + "pt_BR:pt:Portuguese (Brazil)" + "ro_RO:ro:Romanian (Romania)" + "ru_RU:ru:Russian (Russia)" + "rw_RW:rw:Kinyarwanda (Rwanda)" + "si_LK:si:Sinhala (Sri Lanka)" + "sk_SK:sk:Slovak (Slovakia)" + "sl_SI:sl:Slovenian (Slovenia)" + "so_SO:so:Somali (Somalia)" + "sq_AL:sq:Albanian (Albania)" + "sr_RS:sr:Serbian (Serbia)" + "sv_SE:sv:Swedish (Sweden)" + "sw_KE:sw:Swahili (Kenya)" + "ta_IN:ta:Tamil (India)" + "te_IN:te:Telugu (India)" + "th_TH:th:Thai (Thailand)" + "ti_ER:ti:Tigrinya (Eritrea)" + "to_TO:to:Tonga (Tonga)" + "tr_TR:tr:Turkish (Turkey)" + "uk_UA:uk:Ukrainian (Ukraine)" + "ur_IN:ur:Urdu (India)" + "uz_UZ:uz:Uzbek (Uzbekistan)" + "vi_VN:vi:Vietnamese (Vietnam)" + "yo_NG:yo:Yoruba (Nigeria)" + "yo_NG:yo:Yoruba (Nigeria)" + "yue_HK:yu:Cantonese (Hong Kong)" + "zh_CN:zh:Chinese (China)" + "zu_ZA:zu:Zulu (South Africa)" +) + +for i in "${langArr[@]}"; do + IFS=: read -r l1 l2 l3 <<< "$i" + if [ "$langInput" == "$l2" ]; then + lang="${l1}:${l2}" + languagePack="language-pack-${l2}" + fi +done + +if [ -z "$lang" ]; then + echo "plasmoidlocaletest doesn't recognize the language '$lang'" + echo "Eg:" + scriptcmd='sh ./plasmoidlocaletest' + for i in "${langArr[@]}"; do + IFS=: read -r l1 l2 l3 <<< "$i" + echo " ${scriptcmd} ${l2} | ${l3}" + done + echo "" + echo "Or use a the full locale code:" + echo " ${scriptcmd} ar_EG:ar" + exit 1 +fi + +IFS=: read -r l1 l2 <<< "${lang}" +l1="${l1}.UTF-8" + +# Check if language is installed +if [ ! -z "$languagePack" ]; then + if [ "$lang" == "zh_CN:zh" ]; then languagePack="language-pack-zh-hans" + fi + + checkIfLangInstalled "$languagePack" || exit 1 +fi + + +echo "LANGUAGE=\"${lang}\"" +echo "LANG=\"${l1}\"" + +scriptDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +packageDir="${scriptDir}/.." + +# Build local translations for plasmoidviewer +sh "${scriptDir}/build" + +LANGUAGE="${lang}" LANG="${l1}" LC_TIME="${l1}" QML_DISABLE_DISK_CACHE=true plasmoidviewer -a "$packageDir" -l topedge -f horizontal -x 0 -y 0 \ No newline at end of file From 53abab82b1018db24962b9deb6eef8b55be5a189 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 23 Aug 2023 18:52:06 -0600 Subject: [PATCH 064/141] Set indicator min limit default to 0 --- package/contents/config/main.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index a2191c7b..36476100 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -154,7 +154,7 @@ - 1 + 0 From 7c8dd021304aee60b5afe97d635e60de733d6c67 Mon Sep 17 00:00:00 2001 From: Luis Bocanegra Date: Wed, 23 Aug 2023 20:20:47 -0600 Subject: [PATCH 065/141] Improve indicator and overlay contrast color Tints them using background color from color scheme. Caveats: * Requires a Plasma theme that uses color schemes * For some reason indicator color requires closing task to update correctly, not sure if was like this before and this just made it more prominent --- package/contents/ui/Task.qml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index fc9b65a0..6ba80fd5 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -74,6 +74,10 @@ MouseArea { || (task.contextMenu && task.contextMenu.status === PlasmaComponents.DialogStatus.Open) || (!!tasks.groupDialog && tasks.groupDialog.visualParent === task) + property string tintColor: Kirigami.ColorUtils.brightnessForColor(Kirigami.Theme.backgroundColor) === + Kirigami.ColorUtils.Dark ? + "#ffffff" : "#000000" + Accessible.name: model.display Accessible.description: model.display ? i18n("Activate %1", model.display) : "" Accessible.role: Accessible.Button @@ -364,6 +368,7 @@ MouseArea { source: model.decoration } property color dominantColor: imageColors.dominant + property color indicatorColor: Kirigami.ColorUtils.tintWithAlpha(frame.dominantColor, tintColor, .38) anchors { fill: parent @@ -385,7 +390,9 @@ MouseArea { id: colorOverride anchors.fill: frame source: frame - color: plasmoid.configuration.buttonColorizeDominant ? frame.dominantColor : plasmoid.configuration.buttonColorizeCustom + color: plasmoid.configuration.buttonColorizeDominant ? + frame.indicatorColor : + plasmoid.configuration.buttonColorizeCustom visible: plasmoid.configuration.buttonColorize ? true : false } @@ -420,7 +427,7 @@ MouseArea { Behavior on width { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } Behavior on color { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } Behavior on radius { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } - readonly property color decoColor: frame.dominantColor + readonly property color decoColor: frame.indicatorColor readonly property int maxStates: plasmoid.configuration.indicatorMaxLimit readonly property bool isFirst: index === 0 readonly property int adjust: plasmoid.configuration.indicatorShrink @@ -490,7 +497,7 @@ MouseArea { } if(plasmoid.configuration.indicatorDesaturate && task.state === "minimized") { var colorHSL = hexToHSL(colorEval) - colorCalc = Qt.hsla(colorHSL.h, 0.2, colorHSL.l, 1) + colorCalc = Qt.hsla(colorHSL.h, colorHSL.s*0.5, colorHSL.l*.8, 1) } else if(!isFirst && plasmoid.configuration.indicatorStyle === 0 && task.state !== "minimized") {//Metro specific handling colorCalc = Qt.darker(colorEval, 1.2) @@ -823,7 +830,7 @@ MouseArea { Binding { target: audioStreamIconLoader.item property: "dominantIconColor" - value: frame.dominantColor + value: frame.indicatorColor } anchors { From b8b624b49fcdab1781c9cd8f3b84640d84bf133c Mon Sep 17 00:00:00 2001 From: Luis Bocanegra Date: Wed, 23 Aug 2023 23:34:29 -0600 Subject: [PATCH 066/141] Swtich from Kirigami to PlasmaCore theme This actually matches the plasma theme which is what we need --- package/contents/ui/Task.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 6ba80fd5..c247fa50 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -74,7 +74,7 @@ MouseArea { || (task.contextMenu && task.contextMenu.status === PlasmaComponents.DialogStatus.Open) || (!!tasks.groupDialog && tasks.groupDialog.visualParent === task) - property string tintColor: Kirigami.ColorUtils.brightnessForColor(Kirigami.Theme.backgroundColor) === + property string tintColor: Kirigami.ColorUtils.brightnessForColor(PlasmaCore.Theme.backgroundColor) === Kirigami.ColorUtils.Dark ? "#ffffff" : "#000000" From fe2d4103f1c117a65cbb1bfd3b256e6ba39d6aee Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 31 Aug 2023 21:49:11 -0600 Subject: [PATCH 067/141] Clean up floating cases --- package/contents/ui/Task.qml | 86 +++--------------------------------- 1 file changed, 7 insertions(+), 79 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index c247fa50..b5427cf1 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -436,10 +436,8 @@ MouseArea { readonly property bool isVertical: { if(plasmoid.formFactor === PlasmaCore.Types.Vertical && !plasmoid.configuration.indicatorOverride) return true; - if(plasmoid.formFactor == PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 1 || plasmoid.configuration.indicatorLocation === 2) + if(plasmoid.formFactor == PlasmaCore.Types.Floating && plasmoid.configuration.indicatorOverride && (plasmoid.configuration.indicatorLocation === 1 || plasmoid.configuration.indicatorLocation === 2)) return true; - if(plasmoid.configuration.indicatorLocation === 1 || plasmoid.configuration.indicatorLocation === 2) - return true; else{ return false; } @@ -515,86 +513,13 @@ MouseArea { } states:[ - State {//safety case - use bottom when not override - name: "floating-fallback" - when: (plasmoid.location === PlasmaCore.Types.Floating && !plasmoid.configuration.indicatorOverride) - - AnchorChanges { - target: indicator - anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; - horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} - } - PropertyChanges { - target: indicator - width: undefined - height: plasmoid.configuration.indicatorSize - } - }, - State { - name: "floating-bottom" - when: (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) - - AnchorChanges { - target: indicator - anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; - horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} - } - PropertyChanges { - target: indicator - width: undefined - height: plasmoid.configuration.indicatorSize - } - }, - State { - name: "floating-left" - when: (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) - - AnchorChanges { - target: indicator - anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; - horizontalCenter:undefined; verticalCenter:parent.verticalCenter} - } - PropertyChanges { - target: indicator - height: undefined - width: plasmoid.configuration.indicatorSize - } - }, - State { - name: "floating-right" - when: (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) - - AnchorChanges { - target: indicator - anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; - horizontalCenter:undefined; verticalCenter:parent.verticalCenter} - } - PropertyChanges { - target: indicator - height: undefined - width: plasmoid.configuration.indicatorSize - } - }, - State { - name: "floating-top" - when: (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) - - AnchorChanges { - target: indicator - anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; - horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} - } - PropertyChanges { - target: indicator - width: undefined - height: plasmoid.configuration.indicatorSize - } - }, State { name: "bottom" when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 0) || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.BottomEdge && !plasmoid.configuration.indicatorReverse) || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.TopEdge && plasmoid.configuration.indicatorReverse) + || (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 0) + || (plasmoid.location === PlasmaCore.Types.Floating && !plasmoid.configuration.indicatorOverride && !plasmoid.configuration.indicatorReverse) AnchorChanges { target: indicator @@ -612,7 +537,7 @@ MouseArea { when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 1) || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.LeftEdge && !plasmoid.configuration.indicatorReverse) || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.RightEdge && plasmoid.configuration.indicatorReverse) - + || (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 1 && plasmoid.configuration.indicatorOverride) AnchorChanges { target: indicator @@ -630,6 +555,7 @@ MouseArea { when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 2) || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.RightEdge && !plasmoid.configuration.indicatorReverse) || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.LeftEdge && plasmoid.configuration.indicatorReverse) + || (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 2 && plasmoid.configuration.indicatorOverride) AnchorChanges { target: indicator @@ -647,6 +573,8 @@ MouseArea { when: (plasmoid.configuration.indicatorOverride && plasmoid.configuration.indicatorLocation === 3) || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.TopEdge && !plasmoid.configuration.indicatorReverse) || (!plasmoid.configuration.indicatorOverride && plasmoid.location === PlasmaCore.Types.BottomEdge && plasmoid.configuration.indicatorReverse) + || (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorLocation === 3 && plasmoid.configuration.indicatorOverride) + || (plasmoid.location === PlasmaCore.Types.Floating && plasmoid.configuration.indicatorReverse && !plasmoid.configuration.indicatorOverride) AnchorChanges { target: indicator From 03ffa965f909d8094c8e24d7ddd93b0160b09359 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 31 Aug 2023 22:31:45 -0600 Subject: [PATCH 068/141] Add options for inactive decorations. Fixes #14 --- package/contents/config/main.xml | 10 ++- .../plasma_applet_alexankitty.fancytasks.mo | Bin 11647 -> 11610 bytes .../plasma_applet_alexankitty.fancytasks.mo | Bin 10789 -> 10758 bytes package/contents/ui/ConfigAppearance.qml | 9 ++- package/contents/ui/ConfigIndicators.qml | 8 +++ package/contents/ui/Task.qml | 58 ++++++++++++++++-- package/translate/ReadMe.md | 6 +- package/translate/nl.po | 17 ++++- package/translate/template.pot | 12 +++- package/translate/zh_CN.po | 17 ++++- 10 files changed, 118 insertions(+), 19 deletions(-) diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index 36476100..204a172d 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -136,6 +136,10 @@ 0 + + + false + true @@ -224,10 +228,14 @@ #FFFFFF - + false + + + false + false diff --git a/package/contents/locale/nl/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo b/package/contents/locale/nl/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo index f7a0aa011ed51c6e33f4672509079e5167dc6fcd..7ead9117e7617e171c4a4b793ecfbe17168fb9e2 100644 GIT binary patch delta 3228 zcmYk;drZ}39LMp;Jc#Fj7eF~$0Y?$MB$!emh?hXjR8&+1kERxysCc1FGQ*#WannFO zV$4YATCU}07H!ShEYp^oTg!4;W|=kTWnuo|mgcSZ=lmX9&-|X(^E|)bd4A93`#X3) zcsA(#8tZ8`losMq;+)5r@3Ga(2jz0KFT1kzI&v`**P{h z@E~U3VeE{5p(c0}ql{zBeJZ*!s=F~%O+0EMsThyx_%P;UD$d7Dti@UQIclQ4W89Ul zz=gEWBa1ZovF-z>qn;B)O=O|u`DQs4ZDA#9<(rUGFk4X*X~v%T4r+_rP%Auv8t5Eq zXD;FZyn$L_0ypV<{csp&BXc#&kbh4Lku^#NdW^|qoZPj&DQr$y+(ZlR|V^?H1%>dNE z+1Lw5qb62@8mH7=Uxm7V4Qjm2w!IBC!FN$deYhw4Ka$ExIi%||h@)6V9yTCrGvA<&=nsdAlItpJMG-XAPUJ(c zOBN>L9NWJZl@mKrIkOve1p84dJ%U=_ zdQd%v_YQT~2k>$H8Z+=_AJS2$K9~>X^%Ts;AnF0lsPt?_o#K1eHq--;q9*tq4#KlY zVwnhjal;eF0PPgigvOyJRDwE#r4AJi&{W$Cdr&*_vAy9l)Pql>CiFY%r{@Z4z?-(; z$I)shVo(oAL|q?>`hFg2+(J~g%*OucETW>7H=$;}3y0$;sJw1R4RjYZ<8CQ#e}B~d znW+9k+g^+suNw8BM(l{YP&>BU`XQ17j`@O01Q&irt?UA7rq@w3{0DXBeN){BjzPU2 zL5#o()b}cp%`i2n_vQoi;1Sz@%=TYGUI}v>JL%6+FP@?mB%#ha6ZL|QK_yL*Z7;|0 z%CHmtji`w>qjqQyGFS5v>Ilx@V|W!cPW%A(`$KRb?QHC!KSv9w=yh0w8fXV<;CPqj#}9nR8Cw&o$(Ef#+WpBVu|RbosH@ro5rtz zlBAFhW$8@pfU5~jsD|i5j3!1BD!HLk-nh_jUQfbnwAP0EShIBpRuNB!I{5s~0%|LW zSBM8?E|sB#c0@lyMMMd~T+J3DhuA=<=oA(b)6}385-$@oh@FJWSeNi0gH66ABP`l6XRi>#t6Y3I`$goui)rm2tNIEKaudI(&gpZoWk*wUkyIe)!K1f5uFR2oTEWb%fGUrIe^A^g@*p zN~8GjNK~E(4UP6Y+o;tNK|*D@OZfjI`PAPevWYArm3UC*QQ2%8ET A6951J delta 3252 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 GG5-Slh$cS( delta 3244 zcmYk-dra0<9LMpaKEMOw6_ip`9xo_)AtmvysCh+85WHjFurx2Ecqz3XXo#jp_JpK! zb6PQDT5c>iYm|;H+iYpG?2pv7kxp65ES)t|dw-ta*VY-I=XK8S`TfrCobx-shwXVE z=6P4!1}Yt8KS?IP1f08w$71=Q{1xw93;Y|SF@{ESY>83W0r|?MU?TQKoi_&i;Urv* z8?h_iz;4*QWu)!7bSi^6kc%<63w47q=Hnqu!n??yYtf3EVKS;c0@HDdxfv5^AHz62 zjTv|jgZKzFz+h|L$8)X~6`j}-`Oc-H29k;GaU^!Yd`!h69E4Rk8_%N#n%2gjsfUHM zZy}R)`EC6hE=JvFIjaA4807wLiz>JswUia86*!1I4R;iE!EtPdpQ4uf9BQUNqprV$ zT9F6X3*-4xGaZP!Za5CWTx86y3_arZ@u3rH?2FT=nSW>AK;7^WY6gikG{7#XmFSJ! z(=9gFqaN8#)C3Nrwo^4~peHbdrxIEJj#Pf)fJSr=wPZm?qs`SGbzw3-iK)n{x-3-3 zx%dRmL=CJ6)z2pTemCm;y{P`)xAsS<0e;?2&!5Ug4vfGC)Dnf5zDAmd>YxCp<7%9S z^;m+5^fC`CaU%YK#W;*n<>3j``B98M8)x8HJc7*CUH7Qy8Qn*1vZj1!Mx9XYOg{A5 zD{5u5+&bO{wbEXQ3X^u}s1c1rbuhr1God=oXq-*5;9Scu6u5}B6UiCUWv_!x%usPiAG-Gq7fo|@9W{a9QM;oVTSqr)j@nf{QSV6> zYCzej^B0=Mo>j`t1LkqmKu)6ucGlWInpaT+xrUnIEo=XSTCwPE{`GMf*?wlo?2o$M z8%;$WWTRGMmVL1SwUni(m8e9Gyw1FUyh5%4b%O_}z0rcLr9IUP)y_iQXfEnLh1dkw zAQSXlv0rhUP&e3W?Ml>z2d!O=tg<_f>i9gW!$$KS>OBhd@UM$Q4!J~Bze7+fItBG8 zreoya(K0HU!8$vk%ud*i%{YDp)j_p+3U&TBs17fi4Q3;1V7F0w;2~-vNvVE2gz9f7 zwqpOesZ@AlT!9YY7SsiMP$yQ|@fwV#{h4_NHIuJV=UqizciX&=DYT<_e$kkU8dzV{ zeTJf^3n$wN1@^@f)bV0#ms`8atTF3QGrWMh@lDi<{fYc^xO=D@wd0?o2GGOogM8&O zdfEFwmjn8tS!E|2H9x@|j-SL#45s-VjY4hK@u=6W5VaDe7+Ep11~s5MYo9^=D1VO{ z__egL{>UG4K)XHol>ZBujJhy{+N~Rieq76me#NuMNTM<}d?q#_d?7Z_X%nr@kz>v+ zGAr?QGA4XGHpwfbRz%j5$K?eo1IQrq44FY@lfGmR89}xZ6-{y}nXU#UmlTtHQbkn8 zkv?PB{CGQfd3WHfn=q>=7KWfo~lGHb8IS47n=X}hR(?U!9A G#QY1UdL=6W diff --git a/package/contents/ui/ConfigAppearance.qml b/package/contents/ui/ConfigAppearance.qml index ba4d0588..cdf87baf 100644 --- a/package/contents/ui/ConfigAppearance.qml +++ b/package/contents/ui/ConfigAppearance.qml @@ -39,6 +39,7 @@ Kirigami.FormLayout { property alias cfg_buttonColorizeCustom: buttonColorizeCustom.color property alias cfg_disableButtonSvg: disableButtonSvg.checked + property alias cfg_disableButtonInactiveSvg: disableButtonInactiveSvg.checked property alias cfg_overridePlasmaButtonDirection: overridePlasmaButtonDirection.checked property alias cfg_plasmaButtonDirection: plasmaButtonDirection.currentIndex @@ -116,6 +117,7 @@ Kirigami.FormLayout { id: buttonColorizeInactive text: i18n("Colorize inactive buttons") visible: buttonColorize.checked + enabled: !disableButtonInactiveSvg.checked } Item { @@ -125,7 +127,12 @@ Kirigami.FormLayout { CheckBox { id: disableButtonSvg Kirigami.FormData.label: i18n("Plasma Button Decorations:") - text: i18n("Disable") + text: i18n("Disable All") + } + CheckBox { + id: disableButtonInactiveSvg + text: i18n("Disable Inactive Buttons") + enabled: !disableButtonSvg.checked } CheckBox { diff --git a/package/contents/ui/ConfigIndicators.qml b/package/contents/ui/ConfigIndicators.qml index 028ee5b4..c6808e1c 100644 --- a/package/contents/ui/ConfigIndicators.qml +++ b/package/contents/ui/ConfigIndicators.qml @@ -14,6 +14,7 @@ Kirigami.FormLayout { property alias cfg_indicatorsEnabled: indicatorsEnabled.currentIndex property alias cfg_groupIconEnabled: groupIconEnabled.currentIndex + property alias cfg_disableInactiveIndicators: disableInactiveIndicators.checked property alias cfg_indicatorsAnimated: indicatorsAnimated.checked property alias cfg_indicatorLocation: indicatorLocation.currentIndex property alias cfg_indicatorReverse: indicatorReverse.checked @@ -38,6 +39,13 @@ Kirigami.FormLayout { model: [i18n("Disabled"), i18n("Enabled")] } + CheckBox { + enabled: indicatorsEnabled.currentIndex + visible: indicatorsEnabled.currentIndex + id: disableInactiveIndicators + text: i18n("Disable for Inactive Windows") + } + ComboBox { id: groupIconEnabled Kirigami.FormData.label: i18n("Group Overlay:") diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index b5427cf1..9dacf741 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -829,17 +829,39 @@ MouseArea { } }, State { - name: "minimized" - when: model.IsMinimized === true && !frame.isHovered + name: "minimizedNormal" + when: model.IsMinimized === true && !frame.isHovered && !plasmoid.configuration.disableButtonInactiveSvg PropertyChanges { target: frame basePrefix: "minimized" - visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? false : true + visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? false : true } PropertyChanges { target: colorOverride - visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? true : false + visible: (plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive) ? true : false + } + PropertyChanges{ + target: indicator + visible: plasmoid.configuration.disableInactiveIndicators ? false : true + } + }, + State { + name: "minimizedNodecoration" + when: (model.IsMinimized === true && !frame.isHovered) && plasmoid.configuration.disableButtonInactiveSvg + + PropertyChanges { + target: frame + basePrefix: "minimized" + visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true + } + PropertyChanges { + target: colorOverride + visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true + } + PropertyChanges{ + target: indicator + visible: plasmoid.configuration.disableInactiveIndicators ? false : true } }, State { @@ -854,10 +876,14 @@ MouseArea { target: colorOverride visible: plasmoid.configuration.buttonColorize ? true : false } + PropertyChanges{ + target: indicator + visible: plasmoid.configuration.indicatorsEnabled ? true : false + } }, State { - name: "inactive" - when: model.IsActive === false && !frame.isHovered + name: "inactiveNormal" + when: model.IsActive === false && !frame.isHovered && !plasmoid.configuration.disableButtonInactiveSvg PropertyChanges { target: colorOverride visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? true : false @@ -866,6 +892,26 @@ MouseArea { target: frame visible: plasmoid.configuration.buttonColorize && plasmoid.configuration.buttonColorizeInactive ? false : true } + PropertyChanges{ + target: indicator + visible: plasmoid.configuration.disableInactiveIndicators ? false : true + } + }, + State { + name: "inactiveNoDecoration" + when: (model.IsActive === false && !frame.isHovered) && plasmoid.configuration.disableButtonInactiveSvg + PropertyChanges { + target: colorOverride + visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true + } + PropertyChanges { + target: frame + visible: plasmoid.configuration.disableButtonInactiveSvg ? false : true + } + PropertyChanges{ + target: indicator + visible: plasmoid.configuration.disableInactiveIndicators ? false : true + } }, State { name: "hover" diff --git a/package/translate/ReadMe.md b/package/translate/ReadMe.md index 06bca620..22777d68 100644 --- a/package/translate/ReadMe.md +++ b/package/translate/ReadMe.md @@ -35,6 +35,6 @@ Or if you know how to make a pull request ## Status | Locale | Lines | % Done| |----------|---------|-------| -| Template | 158 | | -| nl | 152/158 | 96% | -| zh_CN | 152/158 | 96% | +| Template | 160 | | +| nl | 151/160 | 94% | +| zh_CN | 151/160 | 94% | diff --git a/package/translate/nl.po b/package/translate/nl.po index 7ade54d4..13cfa7f2 100644 --- a/package/translate/nl.po +++ b/package/translate/nl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-08-23 17:38-0600\n" +"POT-Creation-Date: 2023-08-31 22:24-0600\n" "PO-Revision-Date: 2023-07-13 22:27+0200\n" "Last-Translator: Heimen Stoffels \n" "Language-Team: \n" @@ -88,8 +88,12 @@ msgid "Plasma Button Decorations:" msgstr "Plasma-knopdecoraties:" #: ../contents/ui/ConfigAppearance.qml -msgid "Disable" -msgstr "Uitschakelen" +msgid "Disable All" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Disable Inactive Buttons" +msgstr "" #: ../contents/ui/ConfigAppearance.qml msgid "Plasma Button Direction:" @@ -395,6 +399,10 @@ msgstr "Uitgeschakeld" msgid "Enabled" msgstr "Ingeschakeld" +#: ../contents/ui/ConfigIndicators.qml +msgid "Disable for Inactive Windows" +msgstr "" + #: ../contents/ui/ConfigIndicators.qml msgid "Group Overlay:" msgstr "Groepslaag:" @@ -705,6 +713,9 @@ msgctxt "Which activities a window is currently on" msgid "Available on %1" msgstr "Actief op %1" +#~ msgid "Disable" +#~ msgstr "Uitschakelen" + #~ msgid "Colorize buttons" #~ msgstr "Knoppen verkleuren" diff --git a/package/translate/template.pot b/package/translate/template.pot index 80af319a..ced47dff 100644 --- a/package/translate/template.pot +++ b/package/translate/template.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Fancy Tasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-08-23 17:38-0600\n" +"POT-Creation-Date: 2023-08-31 22:24-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -88,7 +88,11 @@ msgid "Plasma Button Decorations:" msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Disable" +msgid "Disable All" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Disable Inactive Buttons" msgstr "" #: ../contents/ui/ConfigAppearance.qml @@ -377,6 +381,10 @@ msgstr "" msgid "Enabled" msgstr "" +#: ../contents/ui/ConfigIndicators.qml +msgid "Disable for Inactive Windows" +msgstr "" + #: ../contents/ui/ConfigIndicators.qml msgid "Group Overlay:" msgstr "" diff --git a/package/translate/zh_CN.po b/package/translate/zh_CN.po index 4f91696e..3fb8bf23 100644 --- a/package/translate/zh_CN.po +++ b/package/translate/zh_CN.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-08-23 17:38-0600\n" +"POT-Creation-Date: 2023-08-31 22:24-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -88,8 +88,12 @@ msgid "Plasma Button Decorations:" msgstr "Plasma按钮装饰:" #: ../contents/ui/ConfigAppearance.qml -msgid "Disable" -msgstr "关闭" +msgid "Disable All" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Disable Inactive Buttons" +msgstr "" #: ../contents/ui/ConfigAppearance.qml msgid "Plasma Button Direction:" @@ -377,6 +381,10 @@ msgstr "关闭" msgid "Enabled" msgstr "打开" +#: ../contents/ui/ConfigIndicators.qml +msgid "Disable for Inactive Windows" +msgstr "" + #: ../contents/ui/ConfigIndicators.qml msgid "Group Overlay:" msgstr "分组覆盖" @@ -687,6 +695,9 @@ msgctxt "Which activities a window is currently on" msgid "Available on %1" msgstr "在 %1 上可用" +#~ msgid "Disable" +#~ msgstr "关闭" + #~ msgid "Colorize buttons" #~ msgstr "彩色按钮" From fb2dc03799342918609bfc5411992f09c33fa0a6 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 31 Aug 2023 22:40:37 -0600 Subject: [PATCH 069/141] add inactive indicator case for hover --- package/contents/ui/Task.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 9dacf741..0890183c 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -924,6 +924,10 @@ MouseArea { target: frame visible: plasmoid.configuration.buttonColorize ? false : true } + PropertyChanges{ + target: indicator + visible: plasmoid.configuration.disableInactiveIndicators ? false : true + } } ] From 7862cd40fadc0120a6af9bbaa73a73e487ed29ef Mon Sep 17 00:00:00 2001 From: Alexandra Date: Fri, 1 Sep 2023 00:14:17 -0600 Subject: [PATCH 070/141] Create build script to make a neat package --- .gitignore | 1 + build.sh | 15 +++++++++++++++ install.sh | 8 +++++--- FancyTasks.png => package/FancyTasks.png | Bin update.sh | 2 +- 5 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 .gitignore create mode 100644 build.sh rename FancyTasks.png => package/FancyTasks.png (100%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..ae02570c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +release/ \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 00000000..c38ac511 --- /dev/null +++ b/build.sh @@ -0,0 +1,15 @@ +#!/bin/sh +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +cd $SCRIPT_DIR/package/translate/ +sh ./merge +sh ./build +cd $SCRIPT_DIR +mkdir $SCRIPT_DIR/build +mkdir $SCRIPT_DIR/release +cp -r $SCRIPT_DIR/package/contents $SCRIPT_DIR/build +cp $SCRIPT_DIR/package/metadata.json $SCRIPT_DIR/build +cp $SCRIPT_DIR/package/FancyTasks.png $SCRIPT_DIR/build +cd $SCRIPT_DIR/build +tar cf $SCRIPT_DIR/release/FancyTasks.tar.gz . +cd $SCRIPT_DIR +rm -rf $SCRIPT_DIR/build \ No newline at end of file diff --git a/install.sh b/install.sh index 2d1ffc85..0e848bab 100755 --- a/install.sh +++ b/install.sh @@ -1,7 +1,9 @@ #!/bin/sh SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -sh $SCRIPT_DIR/package/translate/merge -sh $SCRIPT_DIR/package/translate/build +cd $SCRIPT_DIR/package/translate/ +sh ./merge +sh ./build +cd $SCRIPT_DIR kpackagetool5 -i $SCRIPT_DIR/package mkdir -p ~/.local/share/icons/hicolor/256x256/apps/ -cp ./FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png +cp ./package/FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png diff --git a/FancyTasks.png b/package/FancyTasks.png similarity index 100% rename from FancyTasks.png rename to package/FancyTasks.png diff --git a/update.sh b/update.sh index 6a61a375..7608084b 100755 --- a/update.sh +++ b/update.sh @@ -7,4 +7,4 @@ cd $SCRIPT_DIR kpackagetool5 -u $SCRIPT_DIR/package killall plasmashell kstart5 plasmashell -cp ./FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png \ No newline at end of file +cp ./package/FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png From 0abc3d0905f5b54d39abaf4736db92d4c98e8fa3 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Fri, 1 Sep 2023 00:36:54 -0600 Subject: [PATCH 071/141] Add build script, fix icon --- build.sh | 1 + install.sh | 9 ++------- package/contents/ui/main.qml | 13 +++++++++++++ update.sh | 7 ++----- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/build.sh b/build.sh index c38ac511..95f3ab43 100644 --- a/build.sh +++ b/build.sh @@ -4,6 +4,7 @@ cd $SCRIPT_DIR/package/translate/ sh ./merge sh ./build cd $SCRIPT_DIR +rm -rf $SCRIPT_DIR/release mkdir $SCRIPT_DIR/build mkdir $SCRIPT_DIR/release cp -r $SCRIPT_DIR/package/contents $SCRIPT_DIR/build diff --git a/install.sh b/install.sh index 0e848bab..d182179f 100755 --- a/install.sh +++ b/install.sh @@ -1,9 +1,4 @@ #!/bin/sh SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -cd $SCRIPT_DIR/package/translate/ -sh ./merge -sh ./build -cd $SCRIPT_DIR -kpackagetool5 -i $SCRIPT_DIR/package -mkdir -p ~/.local/share/icons/hicolor/256x256/apps/ -cp ./package/FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png +sh $SCRIPT_DIR/build.sh +kpackagetool5 -i $SCRIPT_DIR/release/FancyTasks.tar.gz diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index ff699a39..50f0532f 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -17,7 +17,20 @@ import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet import "code/layout.js" as LayoutManager import "code/tools.js" as TaskTools + MouseArea { + + Item { + Plasmoid.preferredRepresentation: Plasmoid.compactRepresentation + Plasmoid.compactRepresentation: Item{ + Image { + id: myIcon + source: "FancyTasks.png" + anchors.fill: parent + } + } + } + id: tasks anchors.fill: parent diff --git a/update.sh b/update.sh index 7608084b..1257744d 100755 --- a/update.sh +++ b/update.sh @@ -1,10 +1,7 @@ #!/bin/sh SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -cd $SCRIPT_DIR/package/translate/ -sh ./merge -sh ./build -cd $SCRIPT_DIR -kpackagetool5 -u $SCRIPT_DIR/package +sh $SCRIPT_DIR/build.sh +kpackagetool5 -u $SCRIPT_DIR/release/FancyTasks.tar.gz killall plasmashell kstart5 plasmashell cp ./package/FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png From e1f6c73df4926916812c724f3e16947a5cb53d62 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Fri, 1 Sep 2023 00:37:21 -0600 Subject: [PATCH 072/141] update icon id --- package/contents/ui/main.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 50f0532f..0a2f8e83 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -24,7 +24,7 @@ MouseArea { Plasmoid.preferredRepresentation: Plasmoid.compactRepresentation Plasmoid.compactRepresentation: Item{ Image { - id: myIcon + id: fancyTasksIcon source: "FancyTasks.png" anchors.fill: parent } From b0024eb4005321d79d601b670cd5a31e88ca8379 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Fri, 1 Sep 2023 00:41:12 -0600 Subject: [PATCH 073/141] revert icon --- package/metadata.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package/metadata.json b/package/metadata.json index 1202cce4..8cff7612 100644 --- a/package/metadata.json +++ b/package/metadata.json @@ -80,7 +80,8 @@ "Description[x-test]": "xxClassic taskbar-style window switcher displaying icons and textxx", "Description[zh_CN]": "经典风格的同时显示图标和文本的任务栏式窗口切换器", "EnabledByDefault": true, - "Icon": "FancyTasks", + "Icon": "FancyTasks.png", + "Id": "alexankitty.fancytasks", "License": "GPL-2.0+", "Name": "Fancy Tasks", From c3c26d1e4989f4c50989a7cacd8b44d26e909740 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Fri, 1 Sep 2023 00:41:17 -0600 Subject: [PATCH 074/141] revert icons --- package/contents/ui/main.qml | 12 ------------ update.sh | 2 +- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 0a2f8e83..fc6e82a9 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -19,18 +19,6 @@ import "code/tools.js" as TaskTools MouseArea { - - Item { - Plasmoid.preferredRepresentation: Plasmoid.compactRepresentation - Plasmoid.compactRepresentation: Item{ - Image { - id: fancyTasksIcon - source: "FancyTasks.png" - anchors.fill: parent - } - } - } - id: tasks anchors.fill: parent diff --git a/update.sh b/update.sh index 1257744d..5e44fe41 100755 --- a/update.sh +++ b/update.sh @@ -4,4 +4,4 @@ sh $SCRIPT_DIR/build.sh kpackagetool5 -u $SCRIPT_DIR/release/FancyTasks.tar.gz killall plasmashell kstart5 plasmashell -cp ./package/FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png +#cp ./package/FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png From 44bf6bbfd5a242ae8919b58e9a57e9e2197886a8 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Fri, 1 Sep 2023 00:44:00 -0600 Subject: [PATCH 075/141] restore icon installation --- update.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update.sh b/update.sh index 5e44fe41..1257744d 100755 --- a/update.sh +++ b/update.sh @@ -4,4 +4,4 @@ sh $SCRIPT_DIR/build.sh kpackagetool5 -u $SCRIPT_DIR/release/FancyTasks.tar.gz killall plasmashell kstart5 plasmashell -#cp ./package/FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png +cp ./package/FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png From e49ed7f1914fda058de16b40528cbdb19861f438 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Fri, 1 Sep 2023 00:44:03 -0600 Subject: [PATCH 076/141] restore icon installation --- install.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/install.sh b/install.sh index d182179f..fd7e11d9 100755 --- a/install.sh +++ b/install.sh @@ -2,3 +2,4 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) sh $SCRIPT_DIR/build.sh kpackagetool5 -i $SCRIPT_DIR/release/FancyTasks.tar.gz +cp ./package/FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png From 2b87861644a79f9ba1fb381ff9c9ecb86907acf3 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Fri, 1 Sep 2023 00:56:21 -0600 Subject: [PATCH 077/141] Create icon installer --- iconinstall.sh | 1 + install.sh | 2 +- update.sh | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 iconinstall.sh diff --git a/iconinstall.sh b/iconinstall.sh new file mode 100644 index 00000000..1b666271 --- /dev/null +++ b/iconinstall.sh @@ -0,0 +1 @@ +cp ./package/FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png \ No newline at end of file diff --git a/install.sh b/install.sh index fd7e11d9..0423af63 100755 --- a/install.sh +++ b/install.sh @@ -2,4 +2,4 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) sh $SCRIPT_DIR/build.sh kpackagetool5 -i $SCRIPT_DIR/release/FancyTasks.tar.gz -cp ./package/FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png +sh ./iconinstall.sh \ No newline at end of file diff --git a/update.sh b/update.sh index 1257744d..ec956000 100755 --- a/update.sh +++ b/update.sh @@ -4,4 +4,4 @@ sh $SCRIPT_DIR/build.sh kpackagetool5 -u $SCRIPT_DIR/release/FancyTasks.tar.gz killall plasmashell kstart5 plasmashell -cp ./package/FancyTasks.png ~/.local/share/icons/hicolor/256x256/apps/FancyTasks.png +sh ./iconinstall.sh \ No newline at end of file From 7092ba7710fa0584835eee2555df36eb7446529d Mon Sep 17 00:00:00 2001 From: Alexandra Date: Fri, 1 Sep 2023 01:10:47 -0600 Subject: [PATCH 078/141] Fix desaturate --- package/contents/ui/Task.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 0890183c..1d1d53ac 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -493,11 +493,11 @@ MouseArea { width = plasmoid.configuration.indicatorSize height = indicatorComputedSize } - if(plasmoid.configuration.indicatorDesaturate && task.state === "minimized") { + if(plasmoid.configuration.indicatorDesaturate && task.state === "minimizedNormal") { var colorHSL = hexToHSL(colorEval) colorCalc = Qt.hsla(colorHSL.h, colorHSL.s*0.5, colorHSL.l*.8, 1) } - else if(!isFirst && plasmoid.configuration.indicatorStyle === 0 && task.state !== "minimized") {//Metro specific handling + else if(!isFirst && plasmoid.configuration.indicatorStyle === 0 && task.state !== "minimizedNormal") {//Metro specific handling colorCalc = Qt.darker(colorEval, 1.2) } else { From 1caccb0a47b1d10aa0b28d712422044f74e5ba12 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Fri, 1 Sep 2023 01:17:21 -0600 Subject: [PATCH 079/141] Update README.MD --- README.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.MD b/README.MD index 27afe613..ffbed2d2 100644 --- a/README.MD +++ b/README.MD @@ -3,7 +3,7 @@ Development of this project has more or less resumed. Help is always wanted and # FancyTasks -![Fancy Tasks Icon](https://github.com/alexankitty/Plasma-Customizable-TaskManager/blob/main/FancyTasks.png?raw=true) +![Fancy Tasks Icon](https://github.com/alexankitty/FancyTasks/blob/main/package/FancyTasks.png?raw=true) ## Installing From 0ac00312bf717ca42b1215705f31420313ce1675 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 6 Sep 2023 18:03:20 -0600 Subject: [PATCH 080/141] Implement Icon Scaling. #39 --- package/contents/config/main.xml | 4 ++++ package/contents/ui/ConfigAppearance.qml | 14 +++++++++++++- package/contents/ui/Task.qml | 8 +++++--- package/translate/ReadMe.md | 6 +++--- package/translate/nl.po | 6 +++++- package/translate/template.pot | 6 +++++- package/translate/zh_CN.po | 6 +++++- 7 files changed, 40 insertions(+), 10 deletions(-) diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index 204a172d..dde58401 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -112,6 +112,10 @@ true + + + 100 + true diff --git a/package/contents/ui/ConfigAppearance.qml b/package/contents/ui/ConfigAppearance.qml index cdf87baf..d752fb1d 100644 --- a/package/contents/ui/ConfigAppearance.qml +++ b/package/contents/ui/ConfigAppearance.qml @@ -25,6 +25,7 @@ Kirigami.FormLayout { property alias cfg_showToolTips: showToolTips.checked property alias cfg_highlightWindows: highlightWindows.checked property bool cfg_indicateAudioStreams + property alias cfg_iconScale: iconScale.value property alias cfg_maxStripes: maxStripes.value property bool cfg_forceStripes property alias cfg_maxLength: maxLength.value @@ -77,6 +78,18 @@ Kirigami.FormLayout { Kirigami.FormData.isSection: true } + Slider { + id: iconScale + from: 0 + to: 300 + stepSize: 25.0 + Kirigami.FormData.label: i18n("Icon Scale ") + iconScale.valueAt(iconScale.position) + "%" + } + + Item { + Kirigami.FormData.isSection: true + } + ButtonGroup { id: colorizeButtonGroup } @@ -149,7 +162,6 @@ Kirigami.FormLayout { ComboBox { id: plasmaButtonDirection visible: overridePlasmaButtonDirection.checked - //Kirigami.FormData.label: i18n("Indicator Location:") model: [ i18n("North"), i18n("South"), diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 1d1d53ac..dae39ac1 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -687,13 +687,15 @@ MouseArea { PlasmaCore.IconItem { id: icon - - anchors.fill: parent - + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter active: task.highlighted enabled: true usesPlasmaTheme: false + height: parent.height * (plasmoid.configuration.iconScale / 100) + width: parent.width * (plasmoid.configuration.iconScale / 100) + source: model.decoration } diff --git a/package/translate/ReadMe.md b/package/translate/ReadMe.md index 22777d68..a02bf72a 100644 --- a/package/translate/ReadMe.md +++ b/package/translate/ReadMe.md @@ -35,6 +35,6 @@ Or if you know how to make a pull request ## Status | Locale | Lines | % Done| |----------|---------|-------| -| Template | 160 | | -| nl | 151/160 | 94% | -| zh_CN | 151/160 | 94% | +| Template | 161 | | +| nl | 151/161 | 93% | +| zh_CN | 151/161 | 93% | diff --git a/package/translate/nl.po b/package/translate/nl.po index 13cfa7f2..83a2ef67 100644 --- a/package/translate/nl.po +++ b/package/translate/nl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-08-31 22:24-0600\n" +"POT-Creation-Date: 2023-09-06 17:56-0600\n" "PO-Revision-Date: 2023-07-13 22:27+0200\n" "Last-Translator: Heimen Stoffels \n" "Language-Team: \n" @@ -59,6 +59,10 @@ msgstr "Programma's die audio afspelen markeren" msgid "Use plasma borders" msgstr "Plasmakaders gebruiken" +#: ../contents/ui/ConfigAppearance.qml +msgid "Icon Scale " +msgstr "" + #: ../contents/ui/ConfigAppearance.qml msgid "Button Colors:" msgstr "" diff --git a/package/translate/template.pot b/package/translate/template.pot index ced47dff..80ecab1b 100644 --- a/package/translate/template.pot +++ b/package/translate/template.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Fancy Tasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-08-31 22:24-0600\n" +"POT-Creation-Date: 2023-09-06 17:56-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -59,6 +59,10 @@ msgstr "" msgid "Use plasma borders" msgstr "" +#: ../contents/ui/ConfigAppearance.qml +msgid "Icon Scale " +msgstr "" + #: ../contents/ui/ConfigAppearance.qml msgid "Button Colors:" msgstr "" diff --git a/package/translate/zh_CN.po b/package/translate/zh_CN.po index 3fb8bf23..8296353b 100644 --- a/package/translate/zh_CN.po +++ b/package/translate/zh_CN.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-08-31 22:24-0600\n" +"POT-Creation-Date: 2023-09-06 17:56-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -59,6 +59,10 @@ msgstr "标记正在播放音频的应用" msgid "Use plasma borders" msgstr "使用plasma边框" +#: ../contents/ui/ConfigAppearance.qml +msgid "Icon Scale " +msgstr "" + #: ../contents/ui/ConfigAppearance.qml msgid "Button Colors:" msgstr "" From 643b1f9c0d8af089274a6538222115ce520c3d66 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 6 Sep 2023 18:07:01 -0600 Subject: [PATCH 081/141] Remove space from translated string --- package/contents/ui/ConfigAppearance.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/contents/ui/ConfigAppearance.qml b/package/contents/ui/ConfigAppearance.qml index d752fb1d..2d33eea8 100644 --- a/package/contents/ui/ConfigAppearance.qml +++ b/package/contents/ui/ConfigAppearance.qml @@ -83,7 +83,7 @@ Kirigami.FormLayout { from: 0 to: 300 stepSize: 25.0 - Kirigami.FormData.label: i18n("Icon Scale ") + iconScale.valueAt(iconScale.position) + "%" + Kirigami.FormData.label: i18n("Icon Scale") " " + iconScale.valueAt(iconScale.position) + "%" } Item { From ed45649c696b0a580ca03699c85119c7ad4882a8 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Wed, 6 Sep 2023 18:21:10 -0600 Subject: [PATCH 082/141] Update README.MD --- README.MD | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.MD b/README.MD index ffbed2d2..55e71135 100644 --- a/README.MD +++ b/README.MD @@ -1,6 +1,9 @@ # Notice Development of this project has more or less resumed. Help is always wanted and appreciated, however. +# Contact +You can reach me at ideas@alexankitty.com, by putting an issue on this github, by commenting on the [AUR package](https://aur.archlinux.org/packages/fancytasks), by commenting on the kde-look page, or on the [FancyTasks KDE Reddit community](https://www.reddit.com/r/fancytaskskde/). + # FancyTasks ![Fancy Tasks Icon](https://github.com/alexankitty/FancyTasks/blob/main/package/FancyTasks.png?raw=true) From 239e7ad3ac31f683bb876a6254969e8c64bbea33 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 6 Sep 2023 19:04:13 -0600 Subject: [PATCH 083/141] fix missing concatenation --- package/contents/ui/ConfigAppearance.qml | 2 +- package/translate/nl.po | 4 ++-- package/translate/template.pot | 4 ++-- package/translate/zh_CN.po | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package/contents/ui/ConfigAppearance.qml b/package/contents/ui/ConfigAppearance.qml index 2d33eea8..9f41f933 100644 --- a/package/contents/ui/ConfigAppearance.qml +++ b/package/contents/ui/ConfigAppearance.qml @@ -83,7 +83,7 @@ Kirigami.FormLayout { from: 0 to: 300 stepSize: 25.0 - Kirigami.FormData.label: i18n("Icon Scale") " " + iconScale.valueAt(iconScale.position) + "%" + Kirigami.FormData.label: i18n("Icon Scale") + " " + iconScale.valueAt(iconScale.position) + "%" } Item { diff --git a/package/translate/nl.po b/package/translate/nl.po index 83a2ef67..d4f74c3f 100644 --- a/package/translate/nl.po +++ b/package/translate/nl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-06 17:56-0600\n" +"POT-Creation-Date: 2023-09-06 18:36-0600\n" "PO-Revision-Date: 2023-07-13 22:27+0200\n" "Last-Translator: Heimen Stoffels \n" "Language-Team: \n" @@ -60,7 +60,7 @@ msgid "Use plasma borders" msgstr "Plasmakaders gebruiken" #: ../contents/ui/ConfigAppearance.qml -msgid "Icon Scale " +msgid "Icon Scale" msgstr "" #: ../contents/ui/ConfigAppearance.qml diff --git a/package/translate/template.pot b/package/translate/template.pot index 80ecab1b..a91f0092 100644 --- a/package/translate/template.pot +++ b/package/translate/template.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Fancy Tasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-06 17:56-0600\n" +"POT-Creation-Date: 2023-09-06 18:36-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -60,7 +60,7 @@ msgid "Use plasma borders" msgstr "" #: ../contents/ui/ConfigAppearance.qml -msgid "Icon Scale " +msgid "Icon Scale" msgstr "" #: ../contents/ui/ConfigAppearance.qml diff --git a/package/translate/zh_CN.po b/package/translate/zh_CN.po index 8296353b..2fe6f942 100644 --- a/package/translate/zh_CN.po +++ b/package/translate/zh_CN.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-06 17:56-0600\n" +"POT-Creation-Date: 2023-09-06 18:36-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -60,7 +60,7 @@ msgid "Use plasma borders" msgstr "使用plasma边框" #: ../contents/ui/ConfigAppearance.qml -msgid "Icon Scale " +msgid "Icon Scale" msgstr "" #: ../contents/ui/ConfigAppearance.qml From f09ce9c1403ecd38ee8e532d59cce498214109d3 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 6 Sep 2023 22:00:47 -0600 Subject: [PATCH 084/141] Layout now runs when clicking apply Fixes #45 --- package/contents/config/config.qml | 7 +++++++ package/contents/config/main.xml | 2 +- .../plasma_applet_alexankitty.fancytasks.mo | Bin 11610 -> 11514 bytes .../plasma_applet_alexankitty.fancytasks.mo | Bin 10758 -> 10678 bytes package/contents/ui/ConfigAppearance.qml | 8 ++------ package/contents/ui/code/layout.js | 2 +- package/contents/ui/main.qml | 16 ++++++++++++++-- package/translate/ReadMe.md | 6 +++--- package/translate/nl.po | 9 ++++----- package/translate/template.pot | 6 +----- package/translate/zh_CN.po | 9 ++++----- 11 files changed, 37 insertions(+), 28 deletions(-) diff --git a/package/contents/config/config.qml b/package/contents/config/config.qml index 5d2042f5..3897fb65 100644 --- a/package/contents/config/config.qml +++ b/package/contents/config/config.qml @@ -24,4 +24,11 @@ ConfigModel { icon: "preferences-desktop-navigation" source: "ConfigIndicators.qml" } + property int test: { + for(var key in parent){ + console.log(key) + console.log(parent[key]) + } + return 0 + } } diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index dde58401..161c8d8e 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -67,7 +67,7 @@ 2 1 - + 200 1 diff --git a/package/contents/locale/nl/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo b/package/contents/locale/nl/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo index 7ead9117e7617e171c4a4b793ecfbe17168fb9e2..7fa395ea288a090df7dd8e67f2f50a3f01884087 100644 GIT binary patch delta 2848 zcmXxleN0zX9LMoPJjm|>4M7EoM+JEjnnt0(3T=~tISX838d{=rKv%c_qyla`#a}*zUSN@qZ@9O zT0hJV=rJ6<#9hRf0mh7An~M*QZ@k8Y;I|lrSJ8vlF%WMdf71_z3m(>U37CN?SdHs3 z0YAe9_=~S?nOQT9$>zcmoPian0e0a!v~V6?K>o}%KH~6iryV`Zm`vK~jvFzIb{o3! zHC&2)7>qxn5*$O1v5dLFi5~n5`7=Rx`VyIob7{xme9XcmT#NT%EtcYYs6<_%zL}O` zIqmbvBu&3iY01XGb*%_ii}JjI8l2b!E4M^H09;rJI29u> z6O~v2s-I%#{#MlUJ5c@AIqgPNf;MWY`{q#pJWft=K_&VVm1#O6Y`45F53#NtGoYZNu3Kb-bVF6wnjLET@? zhxWpD)LyAZmA)P|!w%GpdXUvI$59pe(7ApVRpC)&j%Ey%h;^G2br8ma$Vk*0#Uhh5 z`KS)pqXw+R478l~yI4j0G-_{T@*|=IbFc*q@FDyH{V^umn1z^t6wNZLd?%*Nu@*H@ z2WqWfM`ipLF2j$p5T}sb&59U0#Z7$VU_I*j0er;Im|;|Z@o~PTy$4m9JoM`QU&D#k z`Y}|8RjAF^idv&C)EXZ}Rp>HmDaM@k1d@xHL_Hr)`BZ@@)IiC|EwcY^QkKj@qLaqHjsNEe$V>zaw2H1w$q*bUj-R*b)HDDJi!DE<;eaN;lU!f*2fpIvA zmNJ^h53({!LDt0NBFkw?oa;ML71{6HZ$}M$9FIdi}RDVOx^^2%VTt@YO!?}M4 z8$jO=Ur7DcaRL{#dD3waW}{}l8I^ejW@9sImk*)_8b&32$+>aUVjb3rzs_CO~F;yb9BeSk{zG%CT*QEUDiYJkur-`kRgfwWhkzE^-u z+B}MSi|Q}{JDls?mUCkOc|*)O48osLGn+uIbugpqeGNtZP9!<)`*C_^sPC1b65WQX z&`u;r(}Y@rw=oS*q583|a-t6OpCbi4sDZLjl_*4YRF3Mn7K5?T@et~F!bW}XBx>fL zpw@mE^}UOz1b#yGcN6)ZW!#La%;QldN=9{g2|>V2+o+Ks4$k769Yf!a)GFc?RW zZD77bZDPMv-}PvmK|2ZW#SDzp`(MsUB^NAo<2Y)QOyQg8PrZupBx-<3Bzf~Ms)Whu zzSlJ$HN&l_3DlzY!eP|XcB2>HM9++?Q5Qedy(r!+POr7o$roHe1@|UqKDA&ppWUF?fsl{4%3^da5m zs3e+*-9$XmOYE{cyt=9fCd_J delta 2944 zcmXxkd2EzL7{~ExXeqm0j&eh7`*O6Dqvc8jN>#2Jq##u8N)RY3ENr`!EtHC7!6M}> z$4j9?g%BfANf52Z5Dbc7Bq1>#M6`kg4dI9&e~`$H-(TPH&CY&i=6!eOnP=wR2eX@s zVt=%cuQOcrlxHXx_-bli?z@G9~#kNI*i(AH~b<3QSZ)-ZOU-GF{P zhC}fLw!(i<0p7zT6Eo&16+M{L&KRnuGb)fw?2I|s9rH00=ixA{!P)o~D$s7p-by1F zq1zL|i@DQfp>5k-I5nZN3sk(zYR8LSpj3>Ho*apd_$wCdBi(T;r zRA94E;}qNb<*4T?QR8i~?VYFq-$QNniB9DIIV$JqP>OskUyETve2?0qzhYE$xNf3Wlt4r6G`{q@jKDOU zWBXU5&cq(nnK^*kf+MJvo}Vkrz0_$4Ak>uQR7ZPZNW@*a4~A0P1s)V z|9&dk`=dArzr&$;4|N6x@TF5e8FR4+H9;Nfur{Ff^nGh1YQj^f0Dr=M*n}K2lfeIP zbHEsL=*Xa=h+agcXclTqmLl6}s%`&4R7O6v_rF9$3hpQt~g8>sQ_*?vD8txP1N z#!o}tAKaV#Yk;wIXy8KB;dvGN;3Cw@x1%E8hr{tR)G5D(8t5@9;Ik0)dH#%X)w8uEsihu9LkGK*G_j@s*CsMmEA>dZ{H?NV%B8R~bn zs6gvb89Io>YCb`2!3FG(v71yhQ0FXffPvVTb}nk7g{Vwaq6XTH8u&1_!eiFssFi<% z`rU7+mET6~{bSVO_A|JCKN1NfX7Z_M;8~~vmY`O!4wb5nw!Zk!8 zya{F?i!-mGGPx0X)65}Ms?VSnb^&!JZlkvNE(Y?bBxie(rJ;{@E(UNM>W~zo4(SYx z!<7^Tw84GH*T35v)K*h;&G#_7vC6&V>lL@cjq~^MZKbW5*13cIDH%~}(6 zc2cWxvjZt{+uWA|DXCj@n=4GIrc_XRQ0gh=?z%vS9&4$ED7uDI-lizuvnit}m5rYV z_O?!&vOE}#I+F{W@`&?#Xq6M5Um00Z?u4Sz6~SmuV?p;FZ3Y#DLra~=GAFY1^oLHQ n#0ixy42DCci=xYxM;3&GCBahNEe|^3NHiKO&1r1Pa^n93US>Ss diff --git a/package/contents/locale/zh_CN/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo b/package/contents/locale/zh_CN/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo index 93e243358f0d307310db90a34aba40e7c764af74..b22c7c292f3c7e53e5ddf7e9ea0cf9f2c6634f03 100644 GIT binary patch delta 2848 zcmXZd4@^~M7{~FK_@no7kpvZl1m&+N$fl7xvLM?aHKu_ZG>xdtIWbp|CXxqCg-QiG z5xH#rVbz#JTWmxNEtj>lmTu%MTIH5oZlZ0KIs1csf86Jc=YHPz-1ofi^FHUC%bu!% zO7EwHs4mCRP25I&8|B;bSKLYyBDV&K1(nH`iby{k<5( zH*opbUvqoINSAb&3A)^H-za2owIOu-_|!IiiWw_*(*MI{=T9NuXy zuA_ej*`zB<2rsx4wazkBBC93qyN76~gzHf|Z$$2bYe7|HH%`TUs1o;}b~uQd=xbDE z&f#plh}vNsgLK^#oR4#mT-{pa&ppA1rvW?di&s%Q?lnI}EqET4`6w#E>!=Du@+E7z zVzUButLji2*oJzHcAye%$60s)Q?Y*v^;bq`IH6KqKs{7fQ5XJ+({T)`rb{MUO*{va zu@IG5IclCt`~ET1_zkG}wp+gym7tHh)rY52|0Og&=7dUg1C?n$WzYmgSczr05?{j> z9K|)biP_5WG&W))Syf>>YW$D59Oto%rPze*#T`f8qG6AQ9jM5-0V#s2z5ocGQL39rq5ZA|KiL)2IrMAbWI|P>FbBG&DgXH$+ZH-J^75 zldcpsVKr*OdYp%z^^f2t`X^A&Mj<~UO0XE)upIBlvlxkKGn~u945VnDD+@PVt+^Go zPzUN>zm3ZHJzR{(a2Z}la(DNnF)6O)qZpe};|JA`aPAvaLcy8gk|&vI<8uGAX=p$` zYT?DGd$Yo7IPP>LhY#Q4xt|29@P0hR6-|E>zqf5Af^y399F8|XznD?_M-PNJTz3#hl{1}dQ_9xzWAq|lHBW{Fv8 zK8{Lc8!E9D>vy6O=tk}AE$bgaRca7*-4N=!&&*--mkjQ|CisIBn&3YiuS8~e;yhFd z7oaLohDvm^xf6L|To-DAqo`-%6V!V?V*TGy>%{ToX`LjDz^p9luMBfIAq!9o+;06c z)P)t+uSTlpYEcWdq9#0K_M+aR0n~Lv$e;Uy56ycSwayso7DRj5;nyY=wS!#LfQ6_5 zcVQ$}p(dy{H=@SxK#kvTcA1AziS?lF{rjkdPFa5#HJ>+1LlfP^bd1jl_X|-M+>IJ| zpPgTWG4$)r22`R=sBxXB>w3&SjG_M_Dxu@3^}a&Jd+rAsF`T$+Ut9}+;i9?W8kmfl zc(z$=R-krPhgz@+RjFObPlIbmUH>j>{sHqC^5;(Sk-++Hl!ks-ZlVS*=6|Rx!Btp> zci=%ge-`zSo=3f2f1xUnkY|aS#i)cTtp5P&CwUzz@huq0r_n(}Px(QN!amf6AE2Jn zrwRSE?)G~FbEj{k)kNs13*&rj_OApoBO3k5!Q8-$^zS5E{L)}*_EWUerp3tHC z>;2TRmDumU9y_KqzsRerq=nIu;ST2-UlWC?THd|2)(k*S|ew MW2k>Z?#)~N2ad25Q2+n{ delta 2927 zcmXZdeN5F=9LMp4B6#8Ykob_^kgF(S1}<$SMwS*%B~yo%7IQufrwt_p0VBN#<_$r7 zxFVFwmR7T|P{*{KQ~rp#7MnA3jWv`%43+G`^{C5--k*EFzj5yCoO6G_bH3+$&hK(M zXUF2ewIR{Ugrj2FUH`%7>^IJAI9+|RW}%iVj}9kDVUBK zSb%GBEOuft{ugNnT+%@2rqMAAW3e1HK@~2+-8ce!kU#f;4?lVbMcQdNnRcd`j|sF7 zVH}>osdyIqZU`fx`R4Y4^aD|z?P!MS#94Jqwe2~8n4FMdr<)%MQ!!jVdVb>DjjqvMIM%~NHb9bWMK}zfeW!2 zEAT$%;uc1mgFj+1CKJ_SY((AvD`w*iR`D|KMAqgmqPFOIfQk;+&!`pkqoMX_KJ>a| z;AqUX{&LirIDk4cO{gtsMy>QbYGv)nZn-O{%-pj6d#Fr%$Ukd#fe};`Q5tH1S>_zn zUcH7a*1dxoFo>G)Af{uBwXfoO+ILWAWH~=33h-?VVkyqYN7xtVCvq^E-z}n|Jt;Bk z%+F90ok#8Ycc_SezzqBa=V1!zVNtFSm8n`jp2ud?{WsN);&%fTP=-H}`q^RG|M}Lj z7%z(3hy^I#7rBGOE7|70?~jJTVOB)BB%5MK?}H zf^-??Qq*3Sq6Q4&1gx|6Y4aTF`F8UnY5|?7vvM2R7569Vj1A&o>8(k{@cTcNiXND2 z=9&d&rCE;(aIK$e@ zQ4efDO}|SoV>?0&XA`P3%KGI0<#b4C~Lb z{w3C4Ywa?##%w~Z@FZ&DZ&4Y$g8WptPSiaApvI3$mF)ijD)hObr~ooiKQIfzH}Jlj zdvFo`4frhfTEBl{MxFLvjK&A3 z2m3r3IjkkrbyjwSKJ-i)`7X6`imsIr+wKV@U6FfM809{Z*cwG>^iQtBwlYS>j7IujR++83G`pOp3cKL%ZT9&HRAcDoQM+fkIxx`AEY#6#Wu}D1M3(yp^JVs=8KF zszdkUC->V+Ef`Ak`l5D)=6ZdJHTs$>pHf9BrRbGyq!fp?c@xG|P+LdQHI4E\n" "Language-Team: \n" @@ -151,10 +151,6 @@ msgstr "Maximale knopbreedte (in px):" msgid "Space between taskbar items (px):" msgstr "Ruimte tussen taakbalkitems (in px):" -#: ../contents/ui/ConfigAppearance.qml -msgid "Press OK to fix layout issues." -msgstr "Klik op oké om indelingsproblemen op te lossen." - #: ../contents/ui/ConfigAppearance.qml msgid "Spacing between icons:" msgstr "Ruimte tussen pictogrammen:" @@ -717,6 +713,9 @@ msgctxt "Which activities a window is currently on" msgid "Available on %1" msgstr "Actief op %1" +#~ msgid "Press OK to fix layout issues." +#~ msgstr "Klik op oké om indelingsproblemen op te lossen." + #~ msgid "Disable" #~ msgstr "Uitschakelen" diff --git a/package/translate/template.pot b/package/translate/template.pot index a91f0092..d2afb21e 100644 --- a/package/translate/template.pot +++ b/package/translate/template.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Fancy Tasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-06 18:36-0600\n" +"POT-Creation-Date: 2023-09-06 21:59-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -151,10 +151,6 @@ msgstr "" msgid "Space between taskbar items (px):" msgstr "" -#: ../contents/ui/ConfigAppearance.qml -msgid "Press OK to fix layout issues." -msgstr "" - #: ../contents/ui/ConfigAppearance.qml msgid "Spacing between icons:" msgstr "" diff --git a/package/translate/zh_CN.po b/package/translate/zh_CN.po index 2fe6f942..b9b94407 100644 --- a/package/translate/zh_CN.po +++ b/package/translate/zh_CN.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-06 18:36-0600\n" +"POT-Creation-Date: 2023-09-06 21:59-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -151,10 +151,6 @@ msgstr "最大按钮长度(px)" msgid "Space between taskbar items (px):" msgstr "任务栏组件间距(px)" -#: ../contents/ui/ConfigAppearance.qml -msgid "Press OK to fix layout issues." -msgstr "按OK键来修复布局问题。" - #: ../contents/ui/ConfigAppearance.qml msgid "Spacing between icons:" msgstr "图标间距:" @@ -699,6 +695,9 @@ msgctxt "Which activities a window is currently on" msgid "Available on %1" msgstr "在 %1 上可用" +#~ msgid "Press OK to fix layout issues." +#~ msgstr "按OK键来修复布局问题。" + #~ msgid "Disable" #~ msgstr "关闭" From 869c5645397884d13dbf8361414dae2016cbcaeb Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 6 Sep 2023 23:25:49 -0600 Subject: [PATCH 085/141] Display progress on indicator. Fixes #43 --- package/contents/config/main.xml | 8 ++++++++ package/contents/ui/ConfigIndicators.qml | 17 +++++++++++++++++ package/contents/ui/Task.qml | 21 ++++++++++++++++++++- package/contents/ui/TaskProgressOverlay.qml | 1 - package/translate/ReadMe.md | 6 +++--- package/translate/nl.po | 10 +++++++++- package/translate/template.pot | 10 +++++++++- package/translate/zh_CN.po | 10 +++++++++- 8 files changed, 75 insertions(+), 8 deletions(-) diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index 161c8d8e..f99e6c7c 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -140,6 +140,14 @@ 0 + + + false + + + + #00FF00 + false diff --git a/package/contents/ui/ConfigIndicators.qml b/package/contents/ui/ConfigIndicators.qml index c6808e1c..9cf952f9 100644 --- a/package/contents/ui/ConfigIndicators.qml +++ b/package/contents/ui/ConfigIndicators.qml @@ -14,6 +14,8 @@ Kirigami.FormLayout { property alias cfg_indicatorsEnabled: indicatorsEnabled.currentIndex property alias cfg_groupIconEnabled: groupIconEnabled.currentIndex + property alias cfg_indicatorProgress: indicatorProgress.checked + property alias cfg_indicatorProgressColor: indicatorProgressColor.color property alias cfg_disableInactiveIndicators: disableInactiveIndicators.checked property alias cfg_indicatorsAnimated: indicatorsAnimated.checked property alias cfg_indicatorLocation: indicatorLocation.currentIndex @@ -39,6 +41,21 @@ Kirigami.FormLayout { model: [i18n("Disabled"), i18n("Enabled")] } + CheckBox { + id: indicatorProgress + enabled: indicatorsEnabled.currentIndex + visible: indicatorsEnabled.currentIndex + text: i18n("Display Progress on Indicator") + } + + KQControls.ColorButton { + enabled: indicatorsEnabled.currentIndex + visible: indicatorProgress.checked + id: indicatorProgressColor + Kirigami.FormData.label: i18n("Progress Color:") + showAlphaChannel: true + } + CheckBox { enabled: indicatorsEnabled.currentIndex visible: indicatorsEnabled.currentIndex diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index dae39ac1..5c599cb3 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -438,6 +438,8 @@ MouseArea { return true; if(plasmoid.formFactor == PlasmaCore.Types.Floating && plasmoid.configuration.indicatorOverride && (plasmoid.configuration.indicatorLocation === 1 || plasmoid.configuration.indicatorLocation === 2)) return true; + if(plasmoid.configuration.indicatorOverride && (plasmoid.configuration.indicatorLocation === 1 || plasmoid.configuration.indicatorLocation === 2)) + return true; else{ return false; } @@ -509,6 +511,23 @@ MouseArea { height: computedVar.height color: computedVar.colorCalc radius: (Math.max(width, height) / Math.min(width, height)) * (plasmoid.configuration.indicatorRadius / 100) + Rectangle{ + Behavior on height { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } + Behavior on width { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } + Behavior on color { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } + Behavior on radius { PropertyAnimation {duration: plasmoid.configuration.indicatorsAnimated ? 250 : 0} } + visible: task.isWindow && task.smartLauncherItem && task.smartLauncherItem.progressVisible && isFirst && plasmoid.configuration.indicatorProgress + anchors{ + top: isVertical ? undefined : parent.top + bottom: isVertical ? undefined : parent.bottom + left: isVertical ? parent.left : undefined + right: isVertical ? parent.right : undefined + } + width: isVertical ? parent.width : parent.width * (task.smartLauncherItem.progress / 100) + height: isVertical ? parent.height * (task.smartLauncherItem.progress / 100) : parent.height + radius: parent.radius + color: plasmoid.configuration.indicatorProgressColor + } } } @@ -652,7 +671,7 @@ MouseArea { anchors.fill: frame asynchronous: true source: "TaskProgressOverlay.qml" - active: task.isWindow && task.smartLauncherItem && task.smartLauncherItem.progressVisible + active: task.isWindow && task.smartLauncherItem && task.smartLauncherItem.progressVisible && !plasmoid.configuration.indicatorProgress } Item { diff --git a/package/contents/ui/TaskProgressOverlay.qml b/package/contents/ui/TaskProgressOverlay.qml index 94fdbe4e..13dd9fc6 100644 --- a/package/contents/ui/TaskProgressOverlay.qml +++ b/package/contents/ui/TaskProgressOverlay.qml @@ -28,7 +28,6 @@ Item { id: progressFrame width: background.width height: background.height - imagePath: "widgets/tasks" prefix: TaskTools.taskPrefix("progress").concat(TaskTools.taskPrefix("hover")) } diff --git a/package/translate/ReadMe.md b/package/translate/ReadMe.md index 621ff0ec..3db54d04 100644 --- a/package/translate/ReadMe.md +++ b/package/translate/ReadMe.md @@ -35,6 +35,6 @@ Or if you know how to make a pull request ## Status | Locale | Lines | % Done| |----------|---------|-------| -| Template | 160 | | -| nl | 150/160 | 93% | -| zh_CN | 150/160 | 93% | +| Template | 162 | | +| nl | 150/162 | 92% | +| zh_CN | 150/162 | 92% | diff --git a/package/translate/nl.po b/package/translate/nl.po index 6ce00e56..1df68299 100644 --- a/package/translate/nl.po +++ b/package/translate/nl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-06 21:59-0600\n" +"POT-Creation-Date: 2023-09-06 23:19-0600\n" "PO-Revision-Date: 2023-07-13 22:27+0200\n" "Last-Translator: Heimen Stoffels \n" "Language-Team: \n" @@ -399,6 +399,14 @@ msgstr "Uitgeschakeld" msgid "Enabled" msgstr "Ingeschakeld" +#: ../contents/ui/ConfigIndicators.qml +msgid "Display Progress on Indicator" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Progress Color:" +msgstr "" + #: ../contents/ui/ConfigIndicators.qml msgid "Disable for Inactive Windows" msgstr "" diff --git a/package/translate/template.pot b/package/translate/template.pot index d2afb21e..92ff6c89 100644 --- a/package/translate/template.pot +++ b/package/translate/template.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Fancy Tasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-06 21:59-0600\n" +"POT-Creation-Date: 2023-09-06 23:19-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -381,6 +381,14 @@ msgstr "" msgid "Enabled" msgstr "" +#: ../contents/ui/ConfigIndicators.qml +msgid "Display Progress on Indicator" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Progress Color:" +msgstr "" + #: ../contents/ui/ConfigIndicators.qml msgid "Disable for Inactive Windows" msgstr "" diff --git a/package/translate/zh_CN.po b/package/translate/zh_CN.po index b9b94407..58836a7f 100644 --- a/package/translate/zh_CN.po +++ b/package/translate/zh_CN.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-06 21:59-0600\n" +"POT-Creation-Date: 2023-09-06 23:19-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -381,6 +381,14 @@ msgstr "关闭" msgid "Enabled" msgstr "打开" +#: ../contents/ui/ConfigIndicators.qml +msgid "Display Progress on Indicator" +msgstr "" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Progress Color:" +msgstr "" + #: ../contents/ui/ConfigIndicators.qml msgid "Disable for Inactive Windows" msgstr "" From ad5d97d6f648b5b6dd86469ef8fb04f6c9a8d43a Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 6 Sep 2023 23:27:13 -0600 Subject: [PATCH 086/141] Disable borders consistently for task overlay --- package/contents/ui/TaskProgressOverlay.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/package/contents/ui/TaskProgressOverlay.qml b/package/contents/ui/TaskProgressOverlay.qml index 13dd9fc6..d834fd0c 100644 --- a/package/contents/ui/TaskProgressOverlay.qml +++ b/package/contents/ui/TaskProgressOverlay.qml @@ -25,6 +25,7 @@ Item { clip: true PlasmaCore.FrameSvgItem { + enabledBorders: plasmoid.configuration.useBorders ? 1 | 2 | 4 | 8 : 0 id: progressFrame width: background.width height: background.height From 7d2a3f6f3eaef4dce03e191125160d245fed644a Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 7 Sep 2023 00:39:18 -0600 Subject: [PATCH 087/141] Reverse mode layout fix. Fixes #44 --- package/contents/ui/main.qml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 50704722..527acb9d 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -440,6 +440,7 @@ MouseArea { anchors { left: parent.left + leftMargin: plasmoid.configuration.reverseMode && !vertical ? (LayoutManager.logicalTaskCount() + tasksModel.logicalLauncherCount) * plasmoid.configuration.taskSpacingSize : 0 top: parent.top } @@ -463,6 +464,7 @@ MouseArea { taskList.width = LayoutManager.layoutWidth(); taskList.height = LayoutManager.layoutHeight(); LayoutManager.layout(taskRepeater); + LayoutManager } Timer { @@ -478,7 +480,10 @@ MouseArea { id: taskRepeater delegate: Task {} - onItemAdded: taskList.layout() + onItemAdded: { + taskList.layout() + + } onItemRemoved: { if (tasks.containsMouse && index != taskRepeater.count && item.winIdList && item.winIdList.length > 0 && From cef115fcb92b9629b159c8dd47847258d5a9bf04 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 7 Sep 2023 01:19:10 -0600 Subject: [PATCH 088/141] Implement indicator edge offset, fixes #37 --- package/contents/config/main.xml | 4 ++++ package/contents/ui/ConfigIndicators.qml | 10 ++++++++++ package/contents/ui/Task.qml | 19 ++++++++++++++++++- package/translate/ReadMe.md | 6 +++--- package/translate/nl.po | 6 +++++- package/translate/template.pot | 6 +++++- package/translate/zh_CN.po | 6 +++++- 7 files changed, 50 insertions(+), 7 deletions(-) diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index f99e6c7c..18585ce4 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -188,6 +188,10 @@ 100 + + + 0 + 4 diff --git a/package/contents/ui/ConfigIndicators.qml b/package/contents/ui/ConfigIndicators.qml index 9cf952f9..e90ad4f5 100644 --- a/package/contents/ui/ConfigIndicators.qml +++ b/package/contents/ui/ConfigIndicators.qml @@ -21,6 +21,7 @@ Kirigami.FormLayout { property alias cfg_indicatorLocation: indicatorLocation.currentIndex property alias cfg_indicatorReverse: indicatorReverse.checked property alias cfg_indicatorOverride: indicatorOverride.checked + property alias cfg_indicatorEdgeOffset: indicatorEdgeOffset.value property alias cfg_indicatorStyle: indicatorStyle.currentIndex property alias cfg_indicatorMinLimit: indicatorMinLimit.value property alias cfg_indicatorMaxLimit: indicatorMaxLimit.value @@ -107,6 +108,15 @@ Kirigami.FormLayout { font: Kirigami.Theme.smallFont } + SpinBox { + enabled: indicatorsEnabled.currentIndex + id: indicatorEdgeOffset + Kirigami.FormData.label: i18n("Indicator Edge Offset (px):") + from: 0 + to: 999 + } + + ComboBox { enabled: indicatorsEnabled.currentIndex visible: indicatorOverride.checked diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 5c599cb3..575faa7f 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -400,6 +400,7 @@ MouseArea { id: indicator flow: Flow.LeftToRight spacing: PlasmaCore.Units.smallSpacing + clip: true Repeater { model: { @@ -544,11 +545,15 @@ MouseArea { target: indicator anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} - } + } PropertyChanges { target: indicator width: undefined height: plasmoid.configuration.indicatorSize + anchors.topMargin: 0; + anchors.bottomMargin: plasmoid.configuration.indicatorEdgeOffset; + anchors.leftMargin: 0; + anchors.rightMargin: 0; } }, State { @@ -567,6 +572,10 @@ MouseArea { target: indicator height: undefined width: plasmoid.configuration.indicatorSize + anchors.topMargin: 0; + anchors.bottomMargin: 0; + anchors.leftMargin: plasmoid.configuration.indicatorEdgeOffset; + anchors.rightMargin: 0; } }, State { @@ -585,6 +594,10 @@ MouseArea { target: indicator height: undefined width: plasmoid.configuration.indicatorSize + anchors.topMargin: 0; + anchors.bottomMargin: 0; + anchors.leftMargin: 0; + anchors.rightMargin: plasmoid.configuration.indicatorEdgeOffset; } }, State { @@ -604,6 +617,10 @@ MouseArea { target: indicator width: undefined height: plasmoid.configuration.indicatorSize + anchors.topMargin: plasmoid.configuration.indicatorEdgeOffset; + anchors.bottomMargin: 0; + anchors.leftMargin: 0; + anchors.rightMargin: 0; } } ] diff --git a/package/translate/ReadMe.md b/package/translate/ReadMe.md index 3db54d04..d3ca4d00 100644 --- a/package/translate/ReadMe.md +++ b/package/translate/ReadMe.md @@ -35,6 +35,6 @@ Or if you know how to make a pull request ## Status | Locale | Lines | % Done| |----------|---------|-------| -| Template | 162 | | -| nl | 150/162 | 92% | -| zh_CN | 150/162 | 92% | +| Template | 163 | | +| nl | 150/163 | 92% | +| zh_CN | 150/163 | 92% | diff --git a/package/translate/nl.po b/package/translate/nl.po index 1df68299..d632b8f2 100644 --- a/package/translate/nl.po +++ b/package/translate/nl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-06 23:19-0600\n" +"POT-Creation-Date: 2023-09-07 01:07-0600\n" "PO-Revision-Date: 2023-07-13 22:27+0200\n" "Last-Translator: Heimen Stoffels \n" "Language-Team: \n" @@ -435,6 +435,10 @@ msgstr "Aan andere zijde tonen" msgid "Override location" msgstr "Locatie afdwingen" +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Edge Offset (px):" +msgstr "" + #: ../contents/ui/ConfigIndicators.qml msgid "Bottom" msgstr "Onderaan" diff --git a/package/translate/template.pot b/package/translate/template.pot index 92ff6c89..229e544d 100644 --- a/package/translate/template.pot +++ b/package/translate/template.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Fancy Tasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-06 23:19-0600\n" +"POT-Creation-Date: 2023-09-07 01:07-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -417,6 +417,10 @@ msgstr "" msgid "Override location" msgstr "" +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Edge Offset (px):" +msgstr "" + #: ../contents/ui/ConfigIndicators.qml msgid "Bottom" msgstr "" diff --git a/package/translate/zh_CN.po b/package/translate/zh_CN.po index 58836a7f..28b17024 100644 --- a/package/translate/zh_CN.po +++ b/package/translate/zh_CN.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-06 23:19-0600\n" +"POT-Creation-Date: 2023-09-07 01:07-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -417,6 +417,10 @@ msgstr "切换显示位置" msgid "Override location" msgstr "覆盖位置" +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Edge Offset (px):" +msgstr "" + #: ../contents/ui/ConfigIndicators.qml msgid "Bottom" msgstr "底部" From a1e99a96082cf5599cd54f3c2e3e17b7a0843d18 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 7 Sep 2023 01:58:51 -0600 Subject: [PATCH 089/141] Icon scale now adjusts the labels. --- package/contents/ui/Task.qml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 575faa7f..070a82e1 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -701,9 +701,9 @@ MouseArea { topMargin: adjustMargin(false, parent.height, taskFrame.margins.top) } - width: height + width: height * (plasmoid.configuration.iconScale / 100) height: (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - - adjustMargin(false, parent.height, taskFrame.margins.bottom)) + - adjustMargin(false, parent.height, taskFrame.margins.bottom)) function adjustMargin(vert, size, margin) { if (!size) { @@ -723,14 +723,20 @@ MouseArea { PlasmaCore.IconItem { id: icon - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter active: task.highlighted + anchors.centerIn: parent enabled: true usesPlasmaTheme: false + roundToIconSize: false - height: parent.height * (plasmoid.configuration.iconScale / 100) - width: parent.width * (plasmoid.configuration.iconScale / 100) + //height: parent.height * (plasmoid.configuration.iconScale / 100) + //width: height + width: parent.width + height: width + property int dummy: { + console.log(parent.height * plasmoid.configuration.iconScale / 100) + return 0 + } source: model.decoration } From d1f88425b27fe6a279221edfc0816f1969c45882 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 7 Sep 2023 10:42:14 -0600 Subject: [PATCH 090/141] Badges respect icon scaling --- package/contents/ui/Task.qml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 070a82e1..f2af4501 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -729,8 +729,6 @@ MouseArea { usesPlasmaTheme: false roundToIconSize: false - //height: parent.height * (plasmoid.configuration.iconScale / 100) - //width: height width: parent.width height: width property int dummy: { @@ -745,8 +743,9 @@ MouseArea { // QTBUG anchors.fill in conjunction with the Loader doesn't reliably work on creation: // have a window with a badge, move it from one screen to another, the new task item on the // other screen will now have a glitched out badge mask. - width: parent.width - height: parent.height + width: icon.paintedWidth + height: icon.paintedHeight + anchors.centerIn: icon asynchronous: true source: "TaskBadgeOverlay.qml" active: height >= PlasmaCore.Units.iconSizes.small From 779f31f173198e5dbec1febb7f5903a4336c3037 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 7 Sep 2023 11:13:11 -0600 Subject: [PATCH 091/141] Move indicator direction setting --- package/contents/ui/ConfigIndicators.qml | 25 ++++++++++++------------ 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/package/contents/ui/ConfigIndicators.qml b/package/contents/ui/ConfigIndicators.qml index e90ad4f5..0cb9632c 100644 --- a/package/contents/ui/ConfigIndicators.qml +++ b/package/contents/ui/ConfigIndicators.qml @@ -103,6 +103,18 @@ Kirigami.FormLayout { text: i18n("Override location") } + ComboBox { + enabled: indicatorsEnabled.currentIndex + visible: indicatorOverride.checked + id: indicatorLocation + model: [ + i18n("Bottom"), + i18n("Left"), + i18n("Right"), + i18n("Top") + ] + } + Label { text: i18n("Be sure to use this when using as a floating widget") font: Kirigami.Theme.smallFont @@ -116,19 +128,6 @@ Kirigami.FormLayout { to: 999 } - - ComboBox { - enabled: indicatorsEnabled.currentIndex - visible: indicatorOverride.checked - id: indicatorLocation - model: [ - i18n("Bottom"), - i18n("Left"), - i18n("Right"), - i18n("Top") - ] - } - Item { Kirigami.FormData.isSection: true } From f2c957f5c24d7a3bd296c3a1722c7adc3d49c9a8 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 7 Sep 2023 11:43:59 -0600 Subject: [PATCH 092/141] Remove debug code --- package/contents/ui/Task.qml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index f2af4501..0c5f4eb1 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -731,10 +731,6 @@ MouseArea { width: parent.width height: width - property int dummy: { - console.log(parent.height * plasmoid.configuration.iconScale / 100) - return 0 - } source: model.decoration } From 06388e5d836c12d3393127e3dd3af8390991d9ff Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sun, 10 Sep 2023 16:23:53 -0600 Subject: [PATCH 093/141] Icon only now takes icon scaling. Fixes #47 --- package/contents/ui/Task.qml | 5 ++--- package/translate/nl.po | 10 +++++----- package/translate/template.pot | 10 +++++----- package/translate/zh_CN.po | 10 +++++----- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 0c5f4eb1..15a6a147 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -703,8 +703,7 @@ MouseArea { width: height * (plasmoid.configuration.iconScale / 100) height: (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - - adjustMargin(false, parent.height, taskFrame.margins.bottom)) - + - adjustMargin(false, parent.height, taskFrame.margins.bottom)) function adjustMargin(vert, size, margin) { if (!size) { return margin; @@ -729,7 +728,7 @@ MouseArea { usesPlasmaTheme: false roundToIconSize: false - width: parent.width + width: iconsOnly ? parent.width * (plasmoid.configuration.iconScale / 100) : parent.width height: width source: model.decoration diff --git a/package/translate/nl.po b/package/translate/nl.po index d632b8f2..6b48787d 100644 --- a/package/translate/nl.po +++ b/package/translate/nl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-07 01:07-0600\n" +"POT-Creation-Date: 2023-09-10 16:11-0600\n" "PO-Revision-Date: 2023-07-13 22:27+0200\n" "Last-Translator: Heimen Stoffels \n" "Language-Team: \n" @@ -435,10 +435,6 @@ msgstr "Aan andere zijde tonen" msgid "Override location" msgstr "Locatie afdwingen" -#: ../contents/ui/ConfigIndicators.qml -msgid "Indicator Edge Offset (px):" -msgstr "" - #: ../contents/ui/ConfigIndicators.qml msgid "Bottom" msgstr "Onderaan" @@ -455,6 +451,10 @@ msgstr "Rechts" msgid "Top" msgstr "Bovenaan" +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Edge Offset (px):" +msgstr "" + #: ../contents/ui/ConfigIndicators.qml msgid "Indicator Style:" msgstr "Indicatorstijl:" diff --git a/package/translate/template.pot b/package/translate/template.pot index 229e544d..aeaaef27 100644 --- a/package/translate/template.pot +++ b/package/translate/template.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Fancy Tasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-07 01:07-0600\n" +"POT-Creation-Date: 2023-09-10 16:11-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -417,10 +417,6 @@ msgstr "" msgid "Override location" msgstr "" -#: ../contents/ui/ConfigIndicators.qml -msgid "Indicator Edge Offset (px):" -msgstr "" - #: ../contents/ui/ConfigIndicators.qml msgid "Bottom" msgstr "" @@ -437,6 +433,10 @@ msgstr "" msgid "Top" msgstr "" +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Edge Offset (px):" +msgstr "" + #: ../contents/ui/ConfigIndicators.qml msgid "Indicator Style:" msgstr "" diff --git a/package/translate/zh_CN.po b/package/translate/zh_CN.po index 28b17024..3873e529 100644 --- a/package/translate/zh_CN.po +++ b/package/translate/zh_CN.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-07 01:07-0600\n" +"POT-Creation-Date: 2023-09-10 16:11-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -417,10 +417,6 @@ msgstr "切换显示位置" msgid "Override location" msgstr "覆盖位置" -#: ../contents/ui/ConfigIndicators.qml -msgid "Indicator Edge Offset (px):" -msgstr "" - #: ../contents/ui/ConfigIndicators.qml msgid "Bottom" msgstr "底部" @@ -437,6 +433,10 @@ msgstr "右边" msgid "Top" msgstr "顶部" +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Edge Offset (px):" +msgstr "" + #: ../contents/ui/ConfigIndicators.qml msgid "Indicator Style:" msgstr "指示器风格" From e13de3f6ac37f916439e936f7efa815ee6a1817d Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sun, 10 Sep 2023 16:32:28 -0600 Subject: [PATCH 094/141] Fix error flood when starting tasks --- package/contents/ui/Task.qml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 15a6a147..414164de 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -524,8 +524,14 @@ MouseArea { left: isVertical ? parent.left : undefined right: isVertical ? parent.right : undefined } - width: isVertical ? parent.width : parent.width * (task.smartLauncherItem.progress / 100) - height: isVertical ? parent.height * (task.smartLauncherItem.progress / 100) : parent.height + readonly property var progress: { + if(task.smartLauncherItem && task.smartLauncherItem.progressVisible && task.smartLauncherItem.progress){ + return task.smartLauncherItem.progress / 100 + } + return 0 + } + width: isVertical ? parent.width : parent.width * progress + height: isVertical ? parent.height * progress : parent.height radius: parent.radius color: plasmoid.configuration.indicatorProgressColor } From 567025a246eebe7383c5513729d638ffb9964d86 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sun, 10 Sep 2023 16:37:32 -0600 Subject: [PATCH 095/141] Add default visibility indicators. Might fix #46 --- package/contents/ui/Task.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 414164de..8796078e 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -398,6 +398,7 @@ MouseArea { Flow { id: indicator + visible: plasmoid.configuration.indicatorsEnabled ? true : false flow: Flow.LeftToRight spacing: PlasmaCore.Units.smallSpacing clip: true From 04006cc7212fcb55ebbb451f453708b7b2186937 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sun, 10 Sep 2023 17:29:13 -0600 Subject: [PATCH 096/141] Improved subtask indicator checking --- package/contents/ui/GroupDialog.qml | 1 + package/contents/ui/Task.qml | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/package/contents/ui/GroupDialog.qml b/package/contents/ui/GroupDialog.qml index 539de70a..7bccbc46 100644 --- a/package/contents/ui/GroupDialog.qml +++ b/package/contents/ui/GroupDialog.qml @@ -88,6 +88,7 @@ PlasmaCore.Dialog { width: groupListView.width visible: true inPopup: true + readonly property bool isSubTask: true ListView.onRemove: Qt.callLater(groupFilter.updateMaxTextWidth) Connections { diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 8796078e..728a109c 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -410,12 +410,8 @@ MouseArea { return 0; if(task.childCount < plasmoid.configuration.indicatorMinLimit) return 0; - if(task.parent.toString().includes('QQuickItem'))//Target only the main task items. + if(task.isSubTask)//Target only the main task items. return 0; - /*for(var key in task) { - console.log(key) - console.log(task[key]) - }*/ //Kept for debugging if(task.state === 'launcher') { return 0; } From 3558c93198a147ff3b8d6299cb5a04116f4b810e Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sun, 10 Sep 2023 17:30:44 -0600 Subject: [PATCH 097/141] Add isSubTask to main task item --- package/contents/ui/main.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 527acb9d..dabca3b9 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -479,7 +479,9 @@ MouseArea { Repeater { id: taskRepeater - delegate: Task {} + delegate: Task { + readonly property bool isSubTask: false + } onItemAdded: { taskList.layout() From e001bb2cbce969062245a7e728bf657a757bee22 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sun, 10 Sep 2023 21:11:40 -0600 Subject: [PATCH 098/141] icon scaling improvements in icon only --- package/contents/ui/Task.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 728a109c..35fb52ae 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -704,7 +704,7 @@ MouseArea { topMargin: adjustMargin(false, parent.height, taskFrame.margins.top) } - width: height * (plasmoid.configuration.iconScale / 100) + width: iconsOnly ? height : height * (plasmoid.configuration.iconScale / 100) height: (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - adjustMargin(false, parent.height, taskFrame.margins.bottom)) function adjustMargin(vert, size, margin) { @@ -731,7 +731,7 @@ MouseArea { usesPlasmaTheme: false roundToIconSize: false - width: iconsOnly ? parent.width * (plasmoid.configuration.iconScale / 100) : parent.width + width: iconsOnly ? parent.height * (plasmoid.configuration.iconScale / 100) : parent.width height: width source: model.decoration From f3d631bef880fafc98ba6c7878be49b674a90d35 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sun, 10 Sep 2023 23:40:32 -0600 Subject: [PATCH 099/141] Fix attention state and only color on hover --- package/contents/ui/Task.qml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 35fb52ae..3f44fc64 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -377,7 +377,10 @@ MouseArea { leftMargin: ((inPopup || tasks.vertical) && taskList.columns > 1) ? LayoutManager.iconMargin : 0 rightMargin: ((inPopup || tasks.vertical) && taskList.columns > 1) ? LayoutManager.iconMargin : 0 } - + property int test: { + console.log(task.state); + return 0 + } imagePath: plasmoid.configuration.disableButtonSvg ? "" : "widgets/tasks" enabledBorders: plasmoid.configuration.useBorders ? 1 | 2 | 4 | 8 : 0 property bool isHovered: task.highlighted && plasmoid.configuration.taskHoverEffect @@ -863,10 +866,11 @@ MouseArea { PropertyChanges { target: frame basePrefix: "attention" + visible: (plasmoid.configuration.buttonColorize && !frame.isHovered) || !plasmoid.configuration.buttonColorize } PropertyChanges { target: colorOverride - visible: plasmoid.configuration.buttonColorize ? frame.isHovered ? true : false : false + visible: (plasmoid.configuration.buttonColorize && frame.isHovered) } }, State { From fe72cfc424db6cf40474513ea476d2bd7c8fe206 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Tue, 12 Sep 2023 02:03:09 -0600 Subject: [PATCH 100/141] Make Tooltips more legible. Fix Firefox media info --- package/contents/config/config.qml | 7 ----- package/contents/ui/PlayerController.qml | 4 ++- package/contents/ui/Task.qml | 4 --- package/contents/ui/ToolTipInstance.qml | 36 ++++++++++++------------ package/contents/ui/main.qml | 13 +++++++-- 5 files changed, 31 insertions(+), 33 deletions(-) diff --git a/package/contents/config/config.qml b/package/contents/config/config.qml index 3897fb65..5d2042f5 100644 --- a/package/contents/config/config.qml +++ b/package/contents/config/config.qml @@ -24,11 +24,4 @@ ConfigModel { icon: "preferences-desktop-navigation" source: "ConfigIndicators.qml" } - property int test: { - for(var key in parent){ - console.log(key) - console.log(parent[key]) - } - return 0 - } } diff --git a/package/contents/ui/PlayerController.qml b/package/contents/ui/PlayerController.qml index 61dc8688..9e4419cc 100644 --- a/package/contents/ui/PlayerController.qml +++ b/package/contents/ui/PlayerController.qml @@ -21,8 +21,9 @@ RowLayout { readonly property string mprisSourceName: mpris2Source.sourceNameForLauncherUrl(launcherUrl, appPid) readonly property var playerData: mprisSourceName != "" ? mpris2Source.data[mprisSourceName] : 0 readonly property bool playing: !!(playerData.PlaybackStatus === "Playing") + property string parentTitle - readonly property var currentMetadata: !!playerData ? playerData.Metadata : "" + property var currentMetadata: !!playerData ? playerData.Metadata : "" readonly property string track: { const xesamTitle = currentMetadata["xesam:title"] @@ -68,6 +69,7 @@ RowLayout { wrapMode: Text.NoWrap elide: parent.state ? Text.ElideNone : Text.ElideRight text: track + visible: !parentTitle.includes(track) textFormat: Text.PlainText } } diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 3f44fc64..3477acaa 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -377,10 +377,6 @@ MouseArea { leftMargin: ((inPopup || tasks.vertical) && taskList.columns > 1) ? LayoutManager.iconMargin : 0 rightMargin: ((inPopup || tasks.vertical) && taskList.columns > 1) ? LayoutManager.iconMargin : 0 } - property int test: { - console.log(task.state); - return 0 - } imagePath: plasmoid.configuration.disableButtonSvg ? "" : "widgets/tasks" enabledBorders: plasmoid.configuration.useBorders ? 1 | 2 | 4 | 8 : 0 property bool isHovered: task.highlighted && plasmoid.configuration.taskHoverEffect diff --git a/package/contents/ui/ToolTipInstance.qml b/package/contents/ui/ToolTipInstance.qml index 48cb5f9e..9fe78154 100644 --- a/package/contents/ui/ToolTipInstance.qml +++ b/package/contents/ui/ToolTipInstance.qml @@ -39,12 +39,7 @@ ColumnLayout { } else { text = displayParent; } - - // KWin appends increasing integers in between pointy brackets to otherwise equal window titles. - // In this case save <#number> as counter and delete it at the end of text. - text = `${(text.match(/.*(?=\s*(—|-))/) || [""])[0]}${(text.match(/<\d+>/) || [""]).pop()}`; - - // In case the window title had only redundant information (i.e. appName), text is now empty. + // KWin only appends brackets to names that are duplicated, therefore this feature has been removed as unnecessary and probably self-obsoleted, and only worked in reverse. // Add a hyphen to indicate that and avoid empty space. if (text === "") { text = "—"; @@ -72,28 +67,29 @@ ColumnLayout { // all textlabels ColumnLayout { spacing: 0 - // app name + + + // window title PlasmaExtras.Heading { - id: appNameHeading + id: winTitle level: 3 maximumLineCount: 1 lineHeight: isWin ? 1 : appNameHeading.lineHeight Layout.fillWidth: true elide: Text.ElideRight - text: appName - opacity: flatIndex == 0 - visible: text.length !== 0 + text: title + visible: title.length !== 0 textFormat: Text.PlainText } - // window title + // app name PlasmaComponents3.Label { - id: winTitle + id: appNameHeading maximumLineCount: 1 Layout.fillWidth: true elide: Text.ElideRight - text: titleIncludesTrack ? "" : title + text: appName opacity: 0.75 - visible: title.length !== 0 && title !== appNameHeading.text + visible: text.length !== 0 && appNameHeading.text !== title textFormat: Text.PlainText } // subtext @@ -102,7 +98,7 @@ ColumnLayout { maximumLineCount: 1 Layout.fillWidth: true elide: Text.ElideRight - text: isWin ? generateSubText() : "" + text: generateSubText() opacity: 0.6 visible: text.length !== 0 && text !== appNameHeading.text textFormat: Text.PlainText @@ -253,14 +249,13 @@ ColumnLayout { // in all other cases we can safely show the album art without checking the title readonly property bool available: (status === Image.Ready || status === Image.Loading) && (!(isGroup || backend.applicationCategories(launcherUrl).includes("WebBrowser")) || titleIncludesTrack) - anchors.fill: hoverHandler // Indent by one pixel to make sure we never cover up the entire highlight anchors.margins: 1 sourceSize: Qt.size(parent.width, parent.height) asynchronous: true - source: playerController.item ? playerController.item.albumArt : "" + source: playerController.item ? playerController.item.albumArt.split("?")[0] : "" fillMode: Image.PreserveAspectFit visible: available } @@ -284,6 +279,11 @@ ColumnLayout { active: hasPlayer && flatIndex !== -1 // Avoid loading when the instance is going to be destroyed asynchronous: true visible: active + Binding { + target: playerController.item + property: "parentTitle" + value: title + } Layout.fillWidth: true Layout.maximumWidth: header.Layout.maximumWidth Layout.leftMargin: header.Layout.margins diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index dabca3b9..0a60431b 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -216,6 +216,7 @@ MouseArea { PlasmaCore.DataSource { id: mpris2Source engine: "mpris2" + interval: 100 // update ondemand connectedSources: sources onSourceAdded: { connectSource(source); @@ -243,12 +244,18 @@ MouseArea { if (source === "@multiplex") { continue; } - + var sourceData = data[source]; - if (!sourceData) { + if (!sourceData && mpris2Source.data[source]['Metadata']["xesam:artist"] != "" ) { continue; } - + if(desktopFileName === "firefox"){//Hack to replace firefox with the plasma browser integration if it's availalbe. + for (var x = 0, length = connectedSources.length; x < length; ++x) { + if(connectedSources[x] === "plasma-browser-integration"){ + return connectedSources[x] + } + } + } /** * If the task is in a group, we can't use desktopFileName to match the task. * but in case PID match fails, use the match result from desktopFileName. From 10a6619e9912c12586afe13328b30a8d238903ca Mon Sep 17 00:00:00 2001 From: Alexandra Date: Tue, 12 Sep 2023 02:04:28 -0600 Subject: [PATCH 101/141] Change interval to half a second --- package/contents/ui/main.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 0a60431b..7aa5ce62 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -216,7 +216,7 @@ MouseArea { PlasmaCore.DataSource { id: mpris2Source engine: "mpris2" - interval: 100 // update ondemand + interval: 500 // update every half second connectedSources: sources onSourceAdded: { connectSource(source); From 07e1e9eceddc25ab4e636c4ad892251f7e70a81f Mon Sep 17 00:00:00 2001 From: Alexandra Date: Tue, 12 Sep 2023 02:25:00 -0600 Subject: [PATCH 102/141] ignore icon installer package --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ae02570c..ad1404ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -release/ \ No newline at end of file +release/ +iconinstaller.tar.gz From 087e84a3f34c4ab8c0e965d2c84585c23fb02739 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Tue, 12 Sep 2023 02:33:51 -0600 Subject: [PATCH 103/141] make thumbnails always display under wl --- package/contents/ui/PipeWireThumbnail.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/contents/ui/PipeWireThumbnail.qml b/package/contents/ui/PipeWireThumbnail.qml index fbc94236..5dcc79c8 100644 --- a/package/contents/ui/PipeWireThumbnail.qml +++ b/package/contents/ui/PipeWireThumbnail.qml @@ -18,7 +18,7 @@ Item { id: pipeWireSourceItem enabled: false // Must be set in pipewiresourceitem.cpp so opacity animation can work - visible: waylandItem.nodeId > 0 + visible: true nodeId: waylandItem.nodeId anchors.fill: parent From 9ff7528d1746bd24654efcc10fb54d3000391a41 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Tue, 12 Sep 2023 19:24:48 -0600 Subject: [PATCH 104/141] Adjust certain enums to int. Fix plasma btn east --- package/contents/config/main.xml | 32 ++++++++----------------------- package/contents/ui/code/tools.js | 2 +- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index 18585ce4..2b696f75 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -136,7 +136,7 @@ 1 - + 0 @@ -156,15 +156,15 @@ true - + 1 - + 0 - + 0 @@ -253,29 +253,13 @@ false - + false - - - - - - - - + + 0 - - - - - - - - - - 0 - + false diff --git a/package/contents/ui/code/tools.js b/package/contents/ui/code/tools.js index ecebacc2..cdf7e6bf 100644 --- a/package/contents/ui/code/tools.js +++ b/package/contents/ui/code/tools.js @@ -245,7 +245,7 @@ function taskPrefix(prefix) { case 1: effectivePrefix = "north-" + prefix; break; - case 4: + case 3: effectivePrefix = "east-" + prefix; break; default: From 8a8af257c09fd6278c5f16e0c3f12fe197d40404 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Wed, 13 Sep 2023 23:01:11 -0600 Subject: [PATCH 105/141] Implement icon size px option. Fixes #48 --- package/contents/config/main.xml | 8 ++++++++ package/contents/ui/ConfigAppearance.qml | 16 ++++++++++++++++ package/contents/ui/Task.qml | 20 ++++++++++++++++++-- package/translate/ReadMe.md | 6 +++--- package/translate/nl.po | 10 +++++++++- package/translate/template.pot | 10 +++++++++- package/translate/zh_CN.po | 10 +++++++++- 7 files changed, 72 insertions(+), 8 deletions(-) diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index 2b696f75..8f212db0 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -116,6 +116,14 @@ 100 + + + 32 + + + + false + true diff --git a/package/contents/ui/ConfigAppearance.qml b/package/contents/ui/ConfigAppearance.qml index 69da796e..12e403a6 100644 --- a/package/contents/ui/ConfigAppearance.qml +++ b/package/contents/ui/ConfigAppearance.qml @@ -26,6 +26,8 @@ Kirigami.FormLayout { property alias cfg_highlightWindows: highlightWindows.checked property bool cfg_indicateAudioStreams property alias cfg_iconScale: iconScale.value + property alias cfg_iconSizePx: iconSizePx.value + property alias cfg_iconSizeOverride: iconSizeOverride.checked property alias cfg_maxStripes: maxStripes.value property bool cfg_forceStripes property alias cfg_maxButtonLength: maxButtonLength.value @@ -84,6 +86,20 @@ Kirigami.FormLayout { to: 300 stepSize: 25.0 Kirigami.FormData.label: i18n("Icon Scale") + " " + iconScale.valueAt(iconScale.position) + "%" + visible: !iconSizeOverride.checked + } + + SpinBox { + id: iconSizePx + Kirigami.FormData.label: i18n("Icon Size (px):") + from: 0 + to: 999 + visible: iconSizeOverride.checked + } + + CheckBox { + id: iconSizeOverride + text: i18n("Set icon size instead of scaling") } Item { diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 3477acaa..4abb98fd 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -703,7 +703,15 @@ MouseArea { topMargin: adjustMargin(false, parent.height, taskFrame.margins.top) } - width: iconsOnly ? height : height * (plasmoid.configuration.iconScale / 100) + width: { + if(iconsOnly){ + return height; + } + if(!iconsOnly && plasmoid.configuration.iconSizeOverride){ + return plasmoid.configuration.iconSizePx + } + return height * (plasmoid.configuration.iconScale / 100) + } height: (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - adjustMargin(false, parent.height, taskFrame.margins.bottom)) function adjustMargin(vert, size, margin) { @@ -730,7 +738,15 @@ MouseArea { usesPlasmaTheme: false roundToIconSize: false - width: iconsOnly ? parent.height * (plasmoid.configuration.iconScale / 100) : parent.width + width: { + if(iconsOnly && !plasmoid.configuration.iconSizeOverride){ + return parent.height * (plasmoid.configuration.iconScale / 100) + } + if(iconsOnly && plasmoid.configuration.iconSizeOverride){ + return plasmoid.configuration.iconSizePx + } + return parent.width + } height: width source: model.decoration diff --git a/package/translate/ReadMe.md b/package/translate/ReadMe.md index d3ca4d00..37ae79a1 100644 --- a/package/translate/ReadMe.md +++ b/package/translate/ReadMe.md @@ -35,6 +35,6 @@ Or if you know how to make a pull request ## Status | Locale | Lines | % Done| |----------|---------|-------| -| Template | 163 | | -| nl | 150/163 | 92% | -| zh_CN | 150/163 | 92% | +| Template | 165 | | +| nl | 150/165 | 90% | +| zh_CN | 150/165 | 90% | diff --git a/package/translate/nl.po b/package/translate/nl.po index 6b48787d..1adaf9ea 100644 --- a/package/translate/nl.po +++ b/package/translate/nl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-10 16:11-0600\n" +"POT-Creation-Date: 2023-09-13 22:51-0600\n" "PO-Revision-Date: 2023-07-13 22:27+0200\n" "Last-Translator: Heimen Stoffels \n" "Language-Team: \n" @@ -63,6 +63,14 @@ msgstr "Plasmakaders gebruiken" msgid "Icon Scale" msgstr "" +#: ../contents/ui/ConfigAppearance.qml +msgid "Icon Size (px):" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Set icon size instead of scaling" +msgstr "" + #: ../contents/ui/ConfigAppearance.qml msgid "Button Colors:" msgstr "" diff --git a/package/translate/template.pot b/package/translate/template.pot index aeaaef27..c07803f3 100644 --- a/package/translate/template.pot +++ b/package/translate/template.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Fancy Tasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-10 16:11-0600\n" +"POT-Creation-Date: 2023-09-13 22:51-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -63,6 +63,14 @@ msgstr "" msgid "Icon Scale" msgstr "" +#: ../contents/ui/ConfigAppearance.qml +msgid "Icon Size (px):" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Set icon size instead of scaling" +msgstr "" + #: ../contents/ui/ConfigAppearance.qml msgid "Button Colors:" msgstr "" diff --git a/package/translate/zh_CN.po b/package/translate/zh_CN.po index 3873e529..cae2834b 100644 --- a/package/translate/zh_CN.po +++ b/package/translate/zh_CN.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: fancytasks\n" "Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" -"POT-Creation-Date: 2023-09-10 16:11-0600\n" +"POT-Creation-Date: 2023-09-13 22:51-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -63,6 +63,14 @@ msgstr "使用plasma边框" msgid "Icon Scale" msgstr "" +#: ../contents/ui/ConfigAppearance.qml +msgid "Icon Size (px):" +msgstr "" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Set icon size instead of scaling" +msgstr "" + #: ../contents/ui/ConfigAppearance.qml msgid "Button Colors:" msgstr "" From f7f93f738eeff32b90fd65063952466b1b2540ba Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 14 Sep 2023 06:41:55 -0600 Subject: [PATCH 106/141] add testing script --- README.MD | 1 + testing.sh | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 testing.sh diff --git a/README.MD b/README.MD index 55e71135..caf89337 100644 --- a/README.MD +++ b/README.MD @@ -24,6 +24,7 @@ If your distro does not include kirigami2, install it now. It's required for the ## Updating 1. Run the update.sh script, it will automatically stop and restart plasma to make sure the new changes get loaded in. +2. It is recommended you log out and back into your session. plasmashell seems to exhibit some odd behaviors if the plasmoid is updated without clearing the session. ## Features diff --git a/testing.sh b/testing.sh new file mode 100644 index 00000000..736e35ef --- /dev/null +++ b/testing.sh @@ -0,0 +1,5 @@ +#!/bin/sh +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +sh $SCRIPT_DIR/build.sh +kpackagetool5 -u $SCRIPT_DIR/release/FancyTasks.tar.gz +QML_DISABLE_DISK_CACHE=true plasmoidwindowed -a alexankitty.fancytasks \ No newline at end of file From 918671277bd23def1858df9f09553fc4c0102aae Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 14 Sep 2023 06:50:28 -0600 Subject: [PATCH 107/141] Make icon scaling factor in width if smaller --- package/contents/ui/Task.qml | 11 +++++++---- testing.sh | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) mode change 100644 => 100755 testing.sh diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 4abb98fd..5e6ed246 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -704,13 +704,14 @@ MouseArea { } width: { + let isWider = parent.width > height if(iconsOnly){ - return height; + return isWider ? height : parent.width; } if(!iconsOnly && plasmoid.configuration.iconSizeOverride){ return plasmoid.configuration.iconSizePx } - return height * (plasmoid.configuration.iconScale / 100) + return isWider ? parent.height * (plasmoid.configuration.iconScale / 100) : height * (plasmoid.configuration.iconScale / 100) } height: (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - adjustMargin(false, parent.height, taskFrame.margins.bottom)) @@ -726,6 +727,7 @@ MouseArea { } return margin; + } //width: inPopup ? PlasmaCore.Units.iconSizes.small : Math.min(height, parent.width - LayoutManager.horizontalMargins()) @@ -739,13 +741,14 @@ MouseArea { roundToIconSize: false width: { + let isWider = parent.width > parent.height if(iconsOnly && !plasmoid.configuration.iconSizeOverride){ - return parent.height * (plasmoid.configuration.iconScale / 100) + return isWider ? parent.height * (plasmoid.configuration.iconScale / 100) : parent.width * (plasmoid.configuration.iconScale / 100) } if(iconsOnly && plasmoid.configuration.iconSizeOverride){ return plasmoid.configuration.iconSizePx } - return parent.width + return isWider ? parent.height : parent.width } height: width diff --git a/testing.sh b/testing.sh old mode 100644 new mode 100755 index 736e35ef..e2b55fc8 --- a/testing.sh +++ b/testing.sh @@ -2,4 +2,4 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) sh $SCRIPT_DIR/build.sh kpackagetool5 -u $SCRIPT_DIR/release/FancyTasks.tar.gz -QML_DISABLE_DISK_CACHE=true plasmoidwindowed -a alexankitty.fancytasks \ No newline at end of file +QML_DISABLE_DISK_CACHE=true plasmawindowed alexankitty.fancytasks \ No newline at end of file From b35800850b4c293bc4f9d3934f06c9155997fc2c Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 14 Sep 2023 07:17:25 -0600 Subject: [PATCH 108/141] affix group expander to icon instead of task --- package/contents/ui/GroupExpanderOverlay.qml | 10 +++++----- package/contents/ui/Task.qml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package/contents/ui/GroupExpanderOverlay.qml b/package/contents/ui/GroupExpanderOverlay.qml index d90b0b03..dcd58652 100644 --- a/package/contents/ui/GroupExpanderOverlay.qml +++ b/package/contents/ui/GroupExpanderOverlay.qml @@ -12,11 +12,11 @@ PlasmaCore.SvgItem { id: arrow anchors { - bottom: arrow.parent.bottom + bottom: icon.bottom horizontalCenter: iconBox.horizontalCenter } - visible: parent.m.IsGroupParent === true + visible: task.m.IsGroupParent === true states: [ State { @@ -24,7 +24,7 @@ PlasmaCore.SvgItem { when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges { target: arrow - anchors.top: arrow.parent.top + anchors.top: icon.top anchors.left: undefined anchors.right: undefined anchors.bottom: undefined @@ -38,7 +38,7 @@ PlasmaCore.SvgItem { AnchorChanges { target: arrow anchors.top: undefined - anchors.left: arrow.parent.left + anchors.left: icon.left anchors.right: undefined anchors.bottom: undefined anchors.horizontalCenter: undefined @@ -52,7 +52,7 @@ PlasmaCore.SvgItem { target: arrow anchors.top: undefined anchors.left: undefined - anchors.right: arrow.parent.right + anchors.right: icon.right anchors.bottom: undefined anchors.horizontalCenter: undefined anchors.verticalCenter: iconBox.verticalCenter diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 5e6ed246..b22b4d11 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -995,7 +995,7 @@ MouseArea { if (!inPopup && model.IsWindow === true) { if(plasmoid.configuration.groupIconEnabled){ var component = Qt.createComponent("GroupExpanderOverlay.qml"); - component.createObject(task); + component.createObject(iconBox); } } From a0de9c4e6f0e338d2f9c0b59825d98110ac400e6 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Thu, 14 Sep 2023 08:02:16 -0600 Subject: [PATCH 109/141] Fix icon size regression in show task names --- package/contents/ui/Task.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index b22b4d11..a8ac23d7 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -704,14 +704,14 @@ MouseArea { } width: { - let isWider = parent.width > height + let isWider = parent.width > parent.height if(iconsOnly){ return isWider ? height : parent.width; } if(!iconsOnly && plasmoid.configuration.iconSizeOverride){ return plasmoid.configuration.iconSizePx } - return isWider ? parent.height * (plasmoid.configuration.iconScale / 100) : height * (plasmoid.configuration.iconScale / 100) + return height * (plasmoid.configuration.iconScale / 100) } height: (parent.height - adjustMargin(false, parent.height, taskFrame.margins.top) - adjustMargin(false, parent.height, taskFrame.margins.bottom)) @@ -748,7 +748,7 @@ MouseArea { if(iconsOnly && plasmoid.configuration.iconSizeOverride){ return plasmoid.configuration.iconSizePx } - return isWider ? parent.height : parent.width + return parent.width } height: width From 2dbc99f4714af352fca4924f66f37e68233fb4c7 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sat, 16 Sep 2023 10:34:17 -0600 Subject: [PATCH 110/141] Expand plasma integration to other browsers --- package/contents/ui/main.qml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 7aa5ce62..052c1ee2 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -244,18 +244,17 @@ MouseArea { if (source === "@multiplex") { continue; } - - var sourceData = data[source]; - if (!sourceData && mpris2Source.data[source]['Metadata']["xesam:artist"] != "" ) { - continue; - } - if(desktopFileName === "firefox"){//Hack to replace firefox with the plasma browser integration if it's availalbe. + var sourceData + var browserIntegrationArray = ["firefox", "chrome", "chromium", "vivaldi", "brave", "opera", "microsoft-edge"] + if(browserIntegrationArray.findIndex(browser => browser.includes(desktopFileName)) !== -1){//Hack to replace any plasma browser integration compatible browser for (var x = 0, length = connectedSources.length; x < length; ++x) { - if(connectedSources[x] === "plasma-browser-integration"){ + sourceData = data[connectedSources[x]] + if(connectedSources[x] === "plasma-browser-integration" && sourceData.DesktopEntry == desktopFileName){ //Sanity check to ensure we can replace it return connectedSources[x] } } } + sourceData = data[source]; /** * If the task is in a group, we can't use desktopFileName to match the task. * but in case PID match fails, use the match result from desktopFileName. From 45ad7f870cdc31bc0099ae4c28eb4d1c4301ccd2 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sat, 16 Sep 2023 11:22:09 -0600 Subject: [PATCH 111/141] Additional checking on plasma integration --- package/contents/ui/main.qml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 052c1ee2..5682cf83 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -249,7 +249,12 @@ MouseArea { if(browserIntegrationArray.findIndex(browser => browser.includes(desktopFileName)) !== -1){//Hack to replace any plasma browser integration compatible browser for (var x = 0, length = connectedSources.length; x < length; ++x) { sourceData = data[connectedSources[x]] - if(connectedSources[x] === "plasma-browser-integration" && sourceData.DesktopEntry == desktopFileName){ //Sanity check to ensure we can replace it + if(connectedSources[x] === "plasma-browser-integration" && (sourceData.Metadata["kde:pid"] == pid || sourceData.DesktopEntry == desktopFileName)){ //Sanity check to ensure we can replace it + for(var key in sourceData){ + console.log(`${key}: ${sourceData[key]}`) + } + for (var key in sourceData.Metadata) + console.log(`${key}: ${sourceData.Metadata[key]}`) return connectedSources[x] } } From 4871def158cf555d8a5d7402cfa116d554a75f66 Mon Sep 17 00:00:00 2001 From: Alexandra Date: Sat, 16 Sep 2023 11:24:56 -0600 Subject: [PATCH 112/141] Remove debug code --- package/contents/ui/main.qml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 5682cf83..84e28f03 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -250,11 +250,6 @@ MouseArea { for (var x = 0, length = connectedSources.length; x < length; ++x) { sourceData = data[connectedSources[x]] if(connectedSources[x] === "plasma-browser-integration" && (sourceData.Metadata["kde:pid"] == pid || sourceData.DesktopEntry == desktopFileName)){ //Sanity check to ensure we can replace it - for(var key in sourceData){ - console.log(`${key}: ${sourceData[key]}`) - } - for (var key in sourceData.Metadata) - console.log(`${key}: ${sourceData.Metadata[key]}`) return connectedSources[x] } } From d55da1db775eb943f80b425135197cd34df8fcdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Douglas=20Guimar=C3=A3es?= Date: Thu, 21 Sep 2023 18:51:26 -0300 Subject: [PATCH 113/141] add brazilian portuguese .po translation --- package/translate/pt_BR.po | 716 +++++++++++++++++++++++++++++++++++++ 1 file changed, 716 insertions(+) create mode 100644 package/translate/pt_BR.po diff --git a/package/translate/pt_BR.po b/package/translate/pt_BR.po new file mode 100644 index 00000000..8b429286 --- /dev/null +++ b/package/translate/pt_BR.po @@ -0,0 +1,716 @@ +# Translation of Fancy Tasks in pt_BR +# Copyright (C) 2023 +# This file is distributed under the same license as the Fancy Tasks package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Fancy Tasks\n" +"Report-Msgid-Bugs-To: https://github.com/alexankitty/FancyTasks\n" +"POT-Creation-Date: 2023-09-13 22:51-0600\n" +"PO-Revision-Date: 2023-09-21 16:18-0300\n" +"Last-Translator: Douglas Guimarães <>\n" +"Language-Team: \n" +"Language: pt_BR \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../contents/config/config.qml +msgid "Appearance" +msgstr "Aparência" + +#: ../contents/config/config.qml +msgid "Behavior" +msgstr "Comportamento" + +#: ../contents/config/config.qml +msgid "Indicators" +msgstr "Indicadores" + +#: ../contents/ui/Badge.qml +msgctxt "Invalid number of new messages, overlay, keep short" +msgid "—" +msgstr "_" + +#: ../contents/ui/Badge.qml +msgctxt "Over 9999 new messages, overlay, keep short" +msgid "9,999+" +msgstr "9,999+" + +#: ../contents/ui/ConfigAppearance.qml +msgid "General:" +msgstr "Geral" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Show tooltips" +msgstr "Mostrar visualizações" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Highlight windows when hovering over task tooltips" +msgstr "Destacar janelas quando passar o cursor sobre as visualizações" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Mark applications that play audio" +msgstr "Marque os programas que estiverem tocando áudio" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Use plasma borders" +msgstr "Usar bordas do plasma" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Icon Scale" +msgstr "Escala do ícone" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Icon Size (px):" +msgstr "Tamanho do ícone (px):" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Set icon size instead of scaling" +msgstr "Definir pelo tamanho do ícone ao invés da escala" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Button Colors:" +msgstr "Cores do botão:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Using Plasma Style/Accent" +msgstr "Usar estilo/Acentuação do Plasma" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Using Color Overlay" +msgstr "Usar cor sobreposição" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Use dominant icon color" +msgstr "Usar cor predominante do ícone" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Custom Color:" +msgstr "Cor customizada." + +#: ../contents/ui/ConfigAppearance.qml +msgid "Colorize inactive buttons" +msgstr "Colorir botões inativos" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Plasma Button Decorations:" +msgstr "Decoração dos botões do Plasma" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Disable All" +msgstr "Desabilitar todos" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Disable Inactive Buttons" +msgstr "Desabilitar botões inativos" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Plasma Button Direction:" +msgstr "Direção dos botões do Plasma" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Override" +msgstr "Sobrescrever" + +#: ../contents/ui/ConfigAppearance.qml ../contents/ui/ConfigIndicators.qml +msgid "Be sure to use this when using as a floating widget" +msgstr "Tenha certeza que está usando como um widget flutuante" + +#: ../contents/ui/ConfigAppearance.qml +msgid "North" +msgstr "Norte" + +#: ../contents/ui/ConfigAppearance.qml +msgid "South" +msgstr "Sul" + +#: ../contents/ui/ConfigAppearance.qml +msgid "West" +msgstr "Oeste" + +#: ../contents/ui/ConfigAppearance.qml +msgid "East" +msgstr "Leste" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Maximum columns:" +msgstr "Máximo de colunas:" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Maximum rows:" +msgstr "Máximo de linhas" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Always arrange tasks in rows of as many columns" +msgstr "Sempre organize as tarefas em linhas com o máximo de colunas" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Always arrange tasks in columns of as many rows" +msgstr "Sempre organize as tarefas em colunas com o máximo de linhas" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Maximum button length (px):" +msgstr "Comprimento máximo do botão (px):" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Space between taskbar items (px):" +msgstr "Espaço entre os itens da barra de tarefas (px):" + +#: ../contents/ui/ConfigAppearance.qml +msgid "Spacing between icons:" +msgstr "Espaço entre os ícones:" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Small" +msgstr "Pequeno" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Normal" +msgstr "Normal" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@item:inlistbox Icon spacing" +msgid "Large" +msgstr "Grande" + +#: ../contents/ui/ConfigAppearance.qml +msgctxt "@info:usagetip under a set of radio buttons when Touch Mode is on" +msgid "Automatically set to Large when in Touch Mode" +msgstr "Definir automaticamente para grande no \"Touch Mode\"" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Display:" +msgstr "Exibir:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Show task names" +msgstr "Exibir o nome das tarefas" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Show icons only" +msgstr "Exibir apenas os ícones" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Group:" +msgstr "Agrupar pelo:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Do not group" +msgstr "Não agrupe" + +#: ../contents/ui/ConfigBehavior.qml +msgid "By program name" +msgstr "Nome do programa" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Clicking grouped task:" +msgstr "Ao clicar em tarefas agrupadas:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Completes the sentence 'Clicking grouped task cycles through tasks' " +msgid "Cycles through tasks" +msgstr "Percorra entre as tarefas" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Completes the sentence 'Clicking grouped task shows tooltip window thumbnails' " +msgid "Shows tooltip window thumbnails" +msgstr "Mostre as visualizações da janela" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Completes the sentence 'Clicking grouped task shows windows side by side' " +msgid "Shows windows side by side" +msgstr "Mostre as janelas lado a lado" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Completes the sentence 'Clicking grouped task shows textual list' " +msgid "Shows textual list" +msgstr "Mostre uma lista com seus títulos" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Tooltips are disabled, so the windows will be displayed side by side instead." +msgstr "As visualizações estão desativada, portanto as janelas serão exibidas lado a lado" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Tooltips are disabled, and the compositor does not support displaying windows side by side, so a textual list will be displayed instead" +msgstr "As visualizações estão desativada e o compositor não suporta exibir as janelas lado a lado, portanto as janelas serão exibidas atráves da lista de títulos" + +#: ../contents/ui/ConfigBehavior.qml +msgid "The compositor does not support displaying windows side by side, so a textual list will be displayed instead." +msgstr "O compositor não suporta exibir as janelas lado a lado, portanto as janelas serão exibidas atráves da lista de títulos" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Combine into single button" +msgstr "Combine em um único botão" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Group only when the Task Manager is full" +msgstr "Agrupe apenas quando o gerenciador de tarefas estiver cheio" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Sort:" +msgstr "Organizar:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Do not sort" +msgstr "Não organize" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Manually" +msgstr "Manualmente" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Alphabetically" +msgstr "Alfabeticamente" + +#: ../contents/ui/ConfigBehavior.qml +msgid "By desktop" +msgstr "Por área de trabalho" + +#: ../contents/ui/ConfigBehavior.qml +msgid "By activity" +msgstr "Por Atividade" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Keep launchers separate" +msgstr "Manter launchers separados " + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgid "Clicking active task:" +msgstr "Clicando em tarefas abertas:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Clicking active task minimizes the task'" +msgid "Minimizes the task" +msgstr "Minimize a tarefa" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Middle-clicking any task:" +msgstr "Clicando no botão do scroll em qualquer tarefa:" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task does nothing'" +msgid "Does nothing" +msgstr "Não faz nada" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task closes window or group'" +msgid "Closes window or group" +msgstr "Fecha a janela ou o grupo de janelas" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task opens a new window'" +msgid "Opens a new window" +msgstr "Abre uma nova janela" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task minimizes/restores window or group'" +msgid "Minimizes/Restores window or group" +msgstr "Minimiza/restaura a janela ou grupo de janelas" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task toggles grouping'" +msgid "Toggles grouping" +msgstr "Agrupa/desagrupa janelas" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Middle-clicking any task brings it to the current virtual desktop'" +msgid "Brings it to the current virtual desktop" +msgstr "Traz para a área de trabalho virtual atual" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgid "Mouse wheel:" +msgstr "Scroll do mouse" + +#: ../contents/ui/ConfigBehavior.qml +msgctxt "Part of a sentence: 'Mouse wheel cycles through tasks'" +msgid "Cycles through tasks" +msgstr "Percorre entre as tarefas" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Skip minimized tasks" +msgstr "Ignorar tarefas minimizadas" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Show only tasks:" +msgstr "Exibir apenas tarefas:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "From current screen" +msgstr "No monitor atual" + +#: ../contents/ui/ConfigBehavior.qml +msgid "From current desktop" +msgstr "Na área de trabalho atual" + +#: ../contents/ui/ConfigBehavior.qml +msgid "From current activity" +msgstr "Na atividade atual" + +#: ../contents/ui/ConfigBehavior.qml +msgid "That are minimized" +msgstr "Que estão minimizadas" + +#: ../contents/ui/ConfigBehavior.qml +msgid "When panel is hidden:" +msgstr "Quando o painel está ocultado:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "Unhide when a window wants attention" +msgstr "Desocultar quando uma janela necessita de atenção" + +#: ../contents/ui/ConfigBehavior.qml +msgid "New tasks appear:" +msgstr "Novas tarefas aparecem:" + +#: ../contents/ui/ConfigBehavior.qml +msgid "To the right" +msgstr "Na direita" + +#: ../contents/ui/ConfigBehavior.qml +msgid "To the left" +msgstr "Na esquerda" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicators:" +msgstr "Indicadores:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Disabled" +msgstr "Desabilitado" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Enabled" +msgstr "Habilitado" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Display Progress on Indicator" +msgstr "Mostrar progresso no indicator" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Progress Color:" +msgstr "Cor de progresso:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Disable for Inactive Windows" +msgstr "Desabilitar para janelas inativas" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Group Overlay:" +msgstr "Agrupar sobreposição:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Takes effect on next time plasma groups tasks." +msgstr "Tem efeito na próxima vez que o plasma agrupar as tarefas." + +#: ../contents/ui/ConfigIndicators.qml +msgid "Animate Indicators:" +msgstr "Animar indicadores:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Location:" +msgstr "Posição do indicador:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Reverse shown side" +msgstr "Exibir na posiçao oposta" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Override location" +msgstr "Sobrepor posição" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Bottom" +msgstr "Base" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Left" +msgstr "Esquerda" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Right" +msgstr "Direita" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Top" +msgstr "Topo" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Edge Offset (px):" +msgstr "Distância do indicador em relação da borda (px):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Style:" +msgstr "Estilo do indicador:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Metro" +msgstr "Metro" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Ciliora" +msgstr "Ciliora" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Dashes" +msgstr "Dashes" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Min Limit:" +msgstr "Limite minímo de indicadores:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Max Limit:" +msgstr "Limite máximo de indicatores:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Minimize Options:" +msgstr "Ao minimizar uma tarefa:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Desaturate" +msgstr "Desaturar" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Shrink when minimized" +msgstr "Encolher" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Growth/Shrink factor:" +msgstr "Fator de crecimento/encolhimento:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator size (px):" +msgstr "Tamanho do indicador (px):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator length (px):" +msgstr "Comprimento do indicador (px):" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Radius (%):" +msgstr "Raio do Indicador (%)" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator margin (px):" +msgstr "Margin do indicador" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Indicator Color:" +msgstr "Cor do indicador:" + +#: ../contents/ui/ConfigIndicators.qml +msgid "Use plasma accent color" +msgstr "Usar cor de acentuação do Plasma" + +#: ../contents/ui/ContextMenu.qml +msgid "Places" +msgstr "Locais" + +#: ../contents/ui/ContextMenu.qml +msgid "Recent Files" +msgstr "Arquivos recentes" + +#: ../contents/ui/ContextMenu.qml +msgid "Actions" +msgstr "Ações" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Play previous track" +msgid "Previous Track" +msgstr "Faixa anterior" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Pause playback" +msgid "Pause" +msgstr "Pausar" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Start playback" +msgid "Play" +msgstr "Reproduzir" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Play next track" +msgid "Next Track" +msgstr "Próxima faixa" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Stop playback" +msgid "Stop" +msgstr "Parar" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Quit media player app" +msgid "Quit" +msgstr "Fechar" + +#: ../contents/ui/ContextMenu.qml +msgctxt "Open or bring to the front window of media player app" +msgid "Restore" +msgstr "Restaurar" + +#: ../contents/ui/ContextMenu.qml +msgid "Mute" +msgstr "Silenciar" + +#: ../contents/ui/ContextMenu.qml +msgid "Open New Window" +msgstr "Abrir nova janela" + +#: ../contents/ui/ContextMenu.qml +msgid "Move to &Desktop" +msgstr "Mover para &área de trabalho" + +#: ../contents/ui/ContextMenu.qml +msgid "Move &To Current Desktop" +msgstr "Mover ¶ a área de trabalho atual" + +#: ../contents/ui/ContextMenu.qml +msgid "&All Desktops" +msgstr "&Todas as áreas de trabalho" + +#: ../contents/ui/ContextMenu.qml +msgctxt "1 = number of desktop, 2 = desktop name" +msgid "&%1 %2" +msgstr "&%1 %2" + +#: ../contents/ui/ContextMenu.qml +msgid "&New Desktop" +msgstr "&Nova área de trabalho" + +#: ../contents/ui/ContextMenu.qml +msgid "Show in &Activities" +msgstr "Mostrar em &Activities" + +#: ../contents/ui/ContextMenu.qml +msgid "Add To Current Activity" +msgstr "Adicionar a atividade atual" + +#: ../contents/ui/ContextMenu.qml +msgid "All Activities" +msgstr "Todas as atividades" + +#: ../contents/ui/ContextMenu.qml +msgid "Move to %1" +msgstr "Mover para %1" + +#: ../contents/ui/ContextMenu.qml +msgid "&Pin to Task Manager" +msgstr "&Fixar no gerenciador de tarefas" + +#: ../contents/ui/ContextMenu.qml +msgid "On All Activities" +msgstr "Em todas atividades" + +#: ../contents/ui/ContextMenu.qml +msgid "On The Current Activity" +msgstr "Na atividade atual" + +#: ../contents/ui/ContextMenu.qml +msgid "Unpin from Task Manager" +msgstr "Desafixar do gerenciador de tarefas" + +#: ../contents/ui/ContextMenu.qml +msgid "More" +msgstr "Mais" + +#: ../contents/ui/ContextMenu.qml +msgid "&Move" +msgstr "&Mover" + +#: ../contents/ui/ContextMenu.qml +msgid "Re&size" +msgstr "Re&dimensionar" + +#: ../contents/ui/ContextMenu.qml +msgid "Ma&ximize" +msgstr "Ma&ximizar" + +#: ../contents/ui/ContextMenu.qml +msgid "Mi&nimize" +msgstr "Mi&nimizar" + +#: ../contents/ui/ContextMenu.qml +msgid "Keep &Above Others" +msgstr "Manter &acima das outras janelas" + +#: ../contents/ui/ContextMenu.qml +msgid "Keep &Below Others" +msgstr "Manter &abaixo das outras janelas" + +#: ../contents/ui/ContextMenu.qml +msgid "&Fullscreen" +msgstr "&Tela cheia" + +#: ../contents/ui/ContextMenu.qml +msgid "&Shade" +msgstr "&Sombreado" + +#: ../contents/ui/ContextMenu.qml +msgid "Allow this program to be grouped" +msgstr "Permitir que este programa seja agrupado" + +#: ../contents/ui/ContextMenu.qml +msgid "&Close" +msgstr "&Fechar" + +#: ../contents/ui/Task.qml +msgid "Activate %1" +msgstr "Ativo %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "button to unmute app" +msgid "Unmute %1" +msgstr "Silenciar %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "button to mute app" +msgid "Mute %1" +msgstr "Mutar %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Accessibility data on volume slider" +msgid "Adjust volume for %1" +msgstr "Ajustar volume para %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "volume percentage" +msgid "%1%" +msgstr "%1%" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "only used for sizing, should be widest possible string" +msgid "100%" +msgstr "100%" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Comma-separated list of desktops" +msgid "On %1" +msgstr "Em %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Comma-separated list of desktops" +msgid "Pinned to all desktops" +msgstr "Fixar em todas as áreas de trabalho" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Which virtual desktop a window is currently on" +msgid "Available on all activities" +msgstr "Disponível em todas as atividades" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Activities a window is currently on (apart from the current one)" +msgid "Also available on %1" +msgstr "Disponível também em %1" + +#: ../contents/ui/ToolTipInstance.qml +msgctxt "Which activities a window is currently on" +msgid "Available on %1" +msgstr "Disponível em %1" From cdd4ea7f8ca8800cd084414746aa2f8936928adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Douglas=20Guimar=C3=A3es?= Date: Thu, 21 Sep 2023 18:52:13 -0300 Subject: [PATCH 114/141] update Readme to show pt_BR support --- package/translate/ReadMe.md | 1 + 1 file changed, 1 insertion(+) diff --git a/package/translate/ReadMe.md b/package/translate/ReadMe.md index 37ae79a1..f4a4a149 100644 --- a/package/translate/ReadMe.md +++ b/package/translate/ReadMe.md @@ -37,4 +37,5 @@ Or if you know how to make a pull request |----------|---------|-------| | Template | 165 | | | nl | 150/165 | 90% | +| pt_BR | 165/165 | 100% | | zh_CN | 150/165 | 90% | From eab1496416c848e7a24f467ae003db5d8ba900ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Douglas=20Guimar=C3=A3es?= Date: Thu, 21 Sep 2023 18:52:42 -0300 Subject: [PATCH 115/141] add pt_BR locale --- .../plasma_applet_alexankitty.fancytasks.mo | Bin 0 -> 12792 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 package/contents/locale/pt_BR/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo diff --git a/package/contents/locale/pt_BR/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo b/package/contents/locale/pt_BR/LC_MESSAGES/plasma_applet_alexankitty.fancytasks.mo new file mode 100644 index 0000000000000000000000000000000000000000..e8574dbf2d7145139dcce87f64d9a4c232a16b2c GIT binary patch literal 12792 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 literal 0 HcmV?d00001 From 064c8b70f90c1a441914fdf05d9601034071910d Mon Sep 17 00:00:00 2001 From: Yevhen Popok Date: Sun, 22 Oct 2023 23:42:58 +0300 Subject: [PATCH 116/141] Make 1 stripe the default Upstream change from Plasma 5.27 (https://invent.kde.org/plasma/plasma-desktop/-/commit/4d737a3cd22fdba3bcfdc6b44cf2cb8402f510b8) which workarounds the issue when user centers "Task Manager" on the panel using Spacers (https://bugs.kde.org/show_bug.cgi?id=460911) --- package/contents/config/main.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index 8f212db0..3aa10300 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -64,7 +64,7 @@ - 2 + 1 1 From 3e07f911ca19edd6a611de3bffea8a60a73c70e4 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Sat, 6 Apr 2024 16:05:16 -0600 Subject: [PATCH 117/141] Add Supporters --- README.MD | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.MD b/README.MD index caf89337..7d530153 100644 --- a/README.MD +++ b/README.MD @@ -88,3 +88,6 @@ Minimized task shrinking I'm a solo developer working on this project in my free time so it may take me a bit of time to work on issues. You can help me out by either doing a PR with fixes and I'll validate that they work in the code, or put in an issue for things that need to be changed. Especially helpful will be settings names to make them more clear. I have a code bias unfortunately so it does make it exceedingly difficult to convey what everything does. Lastly any feedback is appreciated, and I'll try to implement it as soon as I can. + +## Supporters +catraxx From 3e72685e0467d7476130d6720661c54bcd892d0d Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Thu, 11 Jul 2024 16:19:46 -0600 Subject: [PATCH 118/141] Adding Sponsor Link --- FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 FUNDING.yml diff --git a/FUNDING.yml b/FUNDING.yml new file mode 100644 index 00000000..d5380694 --- /dev/null +++ b/FUNDING.yml @@ -0,0 +1 @@ +ko_fi: alexankitty From a59959466069908c2f942407e4ec61ec175c3b05 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Thu, 11 Jul 2024 16:25:01 -0600 Subject: [PATCH 119/141] Add info to readme concerning project state. Update supporters --- README.MD | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.MD b/README.MD index 7d530153..e8478fe6 100644 --- a/README.MD +++ b/README.MD @@ -1,5 +1,7 @@ # Notice -Development of this project has more or less resumed. Help is always wanted and appreciated, however. +Development of this project has more or less resumed. Help is always wanted and appreciated, however. +I'm struggling with burn out at the moment. I'm hoping to return to the project soon but I need to get that under control. +Currently I'm almost done with the overhauls of indicators which should finalize the Plasma 5 version of this plasmoid. Once that is completed, Plasma 5 will be split into its own fork and the main branch will be for Plasma 6. Any new features and code improvements the plasma 6 widget offers will be back ported in. I'm also in the process of modularizing the FancyTasks additions in order to make development simpler. # Contact You can reach me at ideas@alexankitty.com, by putting an issue on this github, by commenting on the [AUR package](https://aur.archlinux.org/packages/fancytasks), by commenting on the kde-look page, or on the [FancyTasks KDE Reddit community](https://www.reddit.com/r/fancytaskskde/). @@ -90,4 +92,8 @@ Especially helpful will be settings names to make them more clear. I have a code Lastly any feedback is appreciated, and I'll try to implement it as soon as I can. ## Supporters -catraxx +catraxx +Kloud + +If you want to support the project, you may do so below. +[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Q5Q4IFNAO) From b5f20eeb8ae798923ba2ff6f11045880cdc8c644 Mon Sep 17 00:00:00 2001 From: Alexandra <45508320+alexankitty@users.noreply.github.com> Date: Thu, 11 Jul 2024 16:25:37 -0600 Subject: [PATCH 120/141] Tweak wording --- README.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.MD b/README.MD index e8478fe6..f84ca2bb 100644 --- a/README.MD +++ b/README.MD @@ -95,5 +95,5 @@ Lastly any feedback is appreciated, and I'll try to implement it as soon as I ca catraxx Kloud -If you want to support the project, you may do so below. +If you want to support the project and have your name added to the readme, you may do so below. [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Q5Q4IFNAO) From 039f0bcf679a86bd13b699008a3535f5cb4358b9 Mon Sep 17 00:00:00 2001 From: Luis Bocanegra Date: Sat, 15 Mar 2025 13:20:24 -0600 Subject: [PATCH 121/141] WIP hover zoom --- package/contents/ui/Task.qml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/package/contents/ui/Task.qml b/package/contents/ui/Task.qml index 0ed890c3..ec47ffe9 100644 --- a/package/contents/ui/Task.qml +++ b/package/contents/ui/Task.qml @@ -861,9 +861,18 @@ PlasmaCore.ToolTipArea { Kirigami.Icon { id: icon - - anchors.fill: parent - + property int growSize: active ? 20 : 0 + width: parent.width + growSize + height: parent.height + growSize + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + Behavior on growSize { + NumberAnimation { + duration: 250 + easing.type: Easing.InOutQuad + } + } + roundToIconSize: growSize === 0 active: task.highlighted enabled: true From 143fcee95ad489f7e50b5846231bbab986b1dc07 Mon Sep 17 00:00:00 2001 From: SushiTrash Date: Wed, 26 Mar 2025 00:05:55 +0530 Subject: [PATCH 122/141] Add configurable icon zoom hover effect and more --- README.MD | 7 +- Screenshot_20250324_211131.png | Bin 0 -> 232555 bytes install.sh | 4 +- package/contents/config/config.qml | 17 +- package/contents/config/main.xml | 137 ++-- package/contents/ui/ConfigAppearance.qml | 76 ++- package/contents/ui/ConfigPinnedApps.qml | 724 ++++++++++++++++++++++ package/contents/ui/PipeWireThumbnail.qml | 16 +- package/contents/ui/Task.qml | 177 +++--- package/contents/ui/ToolTipDelegate.qml | 8 +- package/contents/ui/ToolTipInstance.qml | 81 ++- package/contents/ui/main.qml | 55 +- update.sh | 4 +- 13 files changed, 1048 insertions(+), 258 deletions(-) create mode 100644 Screenshot_20250324_211131.png create mode 100644 package/contents/ui/ConfigPinnedApps.qml diff --git a/README.MD b/README.MD index f84ca2bb..2877daa9 100644 --- a/README.MD +++ b/README.MD @@ -6,10 +6,13 @@ Currently I'm almost done with the overhauls of indicators which should finalize # Contact You can reach me at ideas@alexankitty.com, by putting an issue on this github, by commenting on the [AUR package](https://aur.archlinux.org/packages/fancytasks), by commenting on the kde-look page, or on the [FancyTasks KDE Reddit community](https://www.reddit.com/r/fancytaskskde/). -# FancyTasks +# FancyTasks+ ![Fancy Tasks Icon](https://github.com/alexankitty/FancyTasks/blob/main/package/FancyTasks.png?raw=true) - +This is a fork of [FancyTasks](https://github.com//alexankitty/FancyTasks) and [Luis Bocanegra's plasma6,hover-zoom branch](https://github.com/luisbocanegra/FancyTasks) with additional features: +- Configurable icon zoom on hover +- With better padding on hover previews +- With a option in configuration which allows you to choose apps to pin and rearrange them ## Installing If your distro does not include kirigami2, install it now. It's required for the settings, and used for the dominant icon color effect. Python3 is required for installing. diff --git a/Screenshot_20250324_211131.png b/Screenshot_20250324_211131.png new file mode 100644 index 0000000000000000000000000000000000000000..6df056f43fb005166bab56a1d4229346fc1be8de GIT binary patch literal 232555 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%0D-?$4(@fyeXD=sqHx%Zx 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