├── .gitignore ├── COPYING ├── LICENSE ├── README.md ├── package ├── contents │ ├── code │ │ └── tools.js │ ├── config │ │ ├── config.qml │ │ └── main.xml │ ├── locale │ │ ├── ko │ │ │ └── LC_MESSAGES │ │ │ │ └── plasma_applet_org.kde.plasma.dittomenu.mo │ │ ├── nl │ │ │ └── LC_MESSAGES │ │ │ │ └── plasma_applet_org.kde.plasma.dittomenu.mo │ │ ├── pl │ │ │ └── LC_MESSAGES │ │ │ │ └── plasma_applet_org.kde.plasma.dittomenu.mo │ │ ├── pt_BR │ │ │ └── LC_MESSAGES │ │ │ │ └── plasma_applet_org.kde.plasma.dittomenu.mo │ │ ├── ru │ │ │ └── LC_MESSAGES │ │ │ │ └── plasma_applet_org.kde.plasma.dittomenu.mo │ │ ├── template │ │ │ └── LC_MESSAGES │ │ │ │ └── plasma_applet_org.kde.plasma.dittomenu.mo │ │ └── tr │ │ │ └── LC_MESSAGES │ │ │ └── plasma_applet_org.kde.plasma.dittomenu.mo │ └── ui │ │ ├── ActionMenu.qml │ │ ├── CompactRepresentation.qml │ │ ├── ConfigGeneral.qml │ │ ├── ItemGridDelegate.qml │ │ ├── ItemGridView.qml │ │ ├── ItemMultiGridView.qml │ │ ├── MenuRepresentation.qml │ │ └── main.qml ├── metadata.desktop └── translate │ ├── ReadMe.md │ ├── build.sh │ ├── fr.po │ ├── ko.po │ ├── merge.sh │ ├── nl.po │ ├── pl.po │ ├── plasmoidlocaletest.sh │ ├── pt_BR.po │ ├── ru.po │ ├── template.pot │ └── tr.po └── preview.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | CMakeLists.txt* 2 | qml.qrc* 3 | cmake* 4 | build* 5 | check* 6 | gdb* 7 | 8 | 9 | # Prerequisites 10 | *.d 11 | 12 | # Compiled Object files 13 | *.slo 14 | *.lo 15 | *.o 16 | *.obj 17 | 18 | # Precompiled Headers 19 | *.gch 20 | *.pch 21 | 22 | # Compiled Dynamic libraries 23 | *.so 24 | *.dylib 25 | *.dll 26 | 27 | # Fortran module files 28 | *.mod 29 | *.smod 30 | 31 | # Compiled Static libraries 32 | *.lai 33 | *.la 34 | *.a 35 | *.lib 36 | 37 | # Executables 38 | *.exe 39 | *.out 40 | *.app 41 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | NOTE! The GPL below is copyrighted by the Free Software Foundation, but 2 | the instance of code that it refers to (the kde programs) are copyrighted 3 | by the authors who actually wrote it. 4 | 5 | --------------------------------------------------------------------------- 6 | 7 | GNU GENERAL PUBLIC LICENSE 8 | Version 2, June 1991 9 | 10 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 11 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 12 | Everyone is permitted to copy and distribute verbatim copies 13 | of this license document, but changing it is not allowed. 14 | 15 | Preamble 16 | 17 | The licenses for most software are designed to take away your 18 | freedom to share and change it. By contrast, the GNU General Public 19 | License is intended to guarantee your freedom to share and change free 20 | software--to make sure the software is free for all its users. This 21 | General Public License applies to most of the Free Software 22 | Foundation's software and to any other program whose authors commit to 23 | using it. (Some other Free Software Foundation software is covered by 24 | the GNU Library General Public License instead.) You can apply it to 25 | your programs, too. 26 | 27 | When we speak of free software, we are referring to freedom, not 28 | price. Our General Public Licenses are designed to make sure that you 29 | have the freedom to distribute copies of free software (and charge for 30 | this service if you wish), that you receive source code or can get it 31 | if you want it, that you can change the software or use pieces of it 32 | in new free programs; and that you know you can do these things. 33 | 34 | To protect your rights, we need to make restrictions that forbid 35 | anyone to deny you these rights or to ask you to surrender the rights. 36 | These restrictions translate to certain responsibilities for you if you 37 | distribute copies of the software, or if you modify it. 38 | 39 | For example, if you distribute copies of such a program, whether 40 | gratis or for a fee, you must give the recipients all the rights that 41 | you have. You must make sure that they, too, receive or can get the 42 | source code. And you must show them these terms so they know their 43 | rights. 44 | 45 | We protect your rights with two steps: (1) copyright the software, and 46 | (2) offer you this license which gives you legal permission to copy, 47 | distribute and/or modify the software. 48 | 49 | Also, for each author's protection and ours, we want to make certain 50 | that everyone understands that there is no warranty for this free 51 | software. If the software is modified by someone else and passed on, we 52 | want its recipients to know that what they have is not the original, so 53 | that any problems introduced by others will not reflect on the original 54 | authors' reputations. 55 | 56 | Finally, any free program is threatened constantly by software 57 | patents. We wish to avoid the danger that redistributors of a free 58 | program will individually obtain patent licenses, in effect making the 59 | program proprietary. To prevent this, we have made it clear that any 60 | patent must be licensed for everyone's free use or not licensed at all. 61 | 62 | The precise terms and conditions for copying, distribution and 63 | modification follow. 64 | 65 | GNU GENERAL PUBLIC LICENSE 66 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 67 | 68 | 0. This License applies to any program or other work which contains 69 | a notice placed by the copyright holder saying it may be distributed 70 | under the terms of this General Public License. The "Program", below, 71 | refers to any such program or work, and a "work based on the Program" 72 | means either the Program or any derivative work under copyright law: 73 | that is to say, a work containing the Program or a portion of it, 74 | either verbatim or with modifications and/or translated into another 75 | language. (Hereinafter, translation is included without limitation in 76 | the term "modification".) Each licensee is addressed as "you". 77 | 78 | Activities other than copying, distribution and modification are not 79 | covered by this License; they are outside its scope. The act of 80 | running the Program is not restricted, and the output from the Program 81 | is covered only if its contents constitute a work based on the 82 | Program (independent of having been made by running the Program). 83 | Whether that is true depends on what the Program does. 84 | 85 | 1. You may copy and distribute verbatim copies of the Program's 86 | source code as you receive it, in any medium, provided that you 87 | conspicuously and appropriately publish on each copy an appropriate 88 | copyright notice and disclaimer of warranty; keep intact all the 89 | notices that refer to this License and to the absence of any warranty; 90 | and give any other recipients of the Program a copy of this License 91 | along with the Program. 92 | 93 | You may charge a fee for the physical act of transferring a copy, and 94 | you may at your option offer warranty protection in exchange for a fee. 95 | 96 | 2. You may modify your copy or copies of the Program or any portion 97 | of it, thus forming a work based on the Program, and copy and 98 | distribute such modifications or work under the terms of Section 1 99 | above, provided that you also meet all of these conditions: 100 | 101 | a) You must cause the modified files to carry prominent notices 102 | stating that you changed the files and the date of any change. 103 | 104 | b) You must cause any work that you distribute or publish, that in 105 | whole or in part contains or is derived from the Program or any 106 | part thereof, to be licensed as a whole at no charge to all third 107 | parties under the terms of this License. 108 | 109 | c) If the modified program normally reads commands interactively 110 | when run, you must cause it, when started running for such 111 | interactive use in the most ordinary way, to print or display an 112 | announcement including an appropriate copyright notice and a 113 | notice that there is no warranty (or else, saying that you provide 114 | a warranty) and that users may redistribute the program under 115 | these conditions, and telling the user how to view a copy of this 116 | License. (Exception: if the Program itself is interactive but 117 | does not normally print such an announcement, your work based on 118 | the Program is not required to print an announcement.) 119 | 120 | These requirements apply to the modified work as a whole. If 121 | identifiable sections of that work are not derived from the Program, 122 | and can be reasonably considered independent and separate works in 123 | themselves, then this License, and its terms, do not apply to those 124 | sections when you distribute them as separate works. But when you 125 | distribute the same sections as part of a whole which is a work based 126 | on the Program, the distribution of the whole must be on the terms of 127 | this License, whose permissions for other licensees extend to the 128 | entire whole, and thus to each and every part regardless of who wrote it. 129 | 130 | Thus, it is not the intent of this section to claim rights or contest 131 | your rights to work written entirely by you; rather, the intent is to 132 | exercise the right to control the distribution of derivative or 133 | collective works based on the Program. 134 | 135 | In addition, mere aggregation of another work not based on the Program 136 | with the Program (or with a work based on the Program) on a volume of 137 | a storage or distribution medium does not bring the other work under 138 | the scope of this License. 139 | 140 | 3. You may copy and distribute the Program (or a work based on it, 141 | under Section 2) in object code or executable form under the terms of 142 | Sections 1 and 2 above provided that you also do one of the following: 143 | 144 | a) Accompany it with the complete corresponding machine-readable 145 | source code, which must be distributed under the terms of Sections 146 | 1 and 2 above on a medium customarily used for software interchange; or, 147 | 148 | b) Accompany it with a written offer, valid for at least three 149 | years, to give any third party, for a charge no more than your 150 | cost of physically performing source distribution, a complete 151 | machine-readable copy of the corresponding source code, to be 152 | distributed under the terms of Sections 1 and 2 above on a medium 153 | customarily used for software interchange; or, 154 | 155 | c) Accompany it with the information you received as to the offer 156 | to distribute corresponding source code. (This alternative is 157 | allowed only for noncommercial distribution and only if you 158 | received the program in object code or executable form with such 159 | an offer, in accord with Subsection b above.) 160 | 161 | The source code for a work means the preferred form of the work for 162 | making modifications to it. For an executable work, complete source 163 | code means all the source code for all modules it contains, plus any 164 | associated interface definition files, plus the scripts used to 165 | control compilation and installation of the executable. However, as a 166 | special exception, the source code distributed need not include 167 | anything that is normally distributed (in either source or binary 168 | form) with the major components (compiler, kernel, and so on) of the 169 | operating system on which the executable runs, unless that component 170 | itself accompanies the executable. 171 | 172 | If distribution of executable or object code is made by offering 173 | access to copy from a designated place, then offering equivalent 174 | access to copy the source code from the same place counts as 175 | distribution of the source code, even though third parties are not 176 | compelled to copy the source along with the object code. 177 | 178 | 4. You may not copy, modify, sublicense, or distribute the Program 179 | except as expressly provided under this License. Any attempt 180 | otherwise to copy, modify, sublicense or distribute the Program is 181 | void, and will automatically terminate your rights under this License. 182 | However, parties who have received copies, or rights, from you under 183 | this License will not have their licenses terminated so long as such 184 | parties remain in full compliance. 185 | 186 | 5. You are not required to accept this License, since you have not 187 | signed it. However, nothing else grants you permission to modify or 188 | distribute the Program or its derivative works. These actions are 189 | prohibited by law if you do not accept this License. Therefore, by 190 | modifying or distributing the Program (or any work based on the 191 | Program), you indicate your acceptance of this License to do so, and 192 | all its terms and conditions for copying, distributing or modifying 193 | the Program or works based on it. 194 | 195 | 6. Each time you redistribute the Program (or any work based on the 196 | Program), the recipient automatically receives a license from the 197 | original licensor to copy, distribute or modify the Program subject to 198 | these terms and conditions. You may not impose any further 199 | restrictions on the recipients' exercise of the rights granted herein. 200 | You are not responsible for enforcing compliance by third parties to 201 | this License. 202 | 203 | 7. If, as a consequence of a court judgment or allegation of patent 204 | infringement or for any other reason (not limited to patent issues), 205 | conditions are imposed on you (whether by court order, agreement or 206 | otherwise) that contradict the conditions of this License, they do not 207 | excuse you from the conditions of this License. If you cannot 208 | distribute so as to satisfy simultaneously your obligations under this 209 | License and any other pertinent obligations, then as a consequence you 210 | may not distribute the Program at all. For example, if a patent 211 | license would not permit royalty-free redistribution of the Program by 212 | all those who receive copies directly or indirectly through you, then 213 | the only way you could satisfy both it and this License would be to 214 | refrain entirely from distribution of the Program. 215 | 216 | If any portion of this section is held invalid or unenforceable under 217 | any particular circumstance, the balance of the section is intended to 218 | apply and the section as a whole is intended to apply in other 219 | circumstances. 220 | 221 | It is not the purpose of this section to induce you to infringe any 222 | patents or other property right claims or to contest validity of any 223 | such claims; this section has the sole purpose of protecting the 224 | integrity of the free software distribution system, which is 225 | implemented by public license practices. Many people have made 226 | generous contributions to the wide range of software distributed 227 | through that system in reliance on consistent application of that 228 | system; it is up to the author/donor to decide if he or she is willing 229 | to distribute software through any other system and a licensee cannot 230 | impose that choice. 231 | 232 | This section is intended to make thoroughly clear what is believed to 233 | be a consequence of the rest of this License. 234 | 235 | 8. If the distribution and/or use of the Program is restricted in 236 | certain countries either by patents or by copyrighted interfaces, the 237 | original copyright holder who places the Program under this License 238 | may add an explicit geographical distribution limitation excluding 239 | those countries, so that distribution is permitted only in or among 240 | countries not thus excluded. In such case, this License incorporates 241 | the limitation as if written in the body of this License. 242 | 243 | 9. The Free Software Foundation may publish revised and/or new versions 244 | of the General Public License from time to time. Such new versions will 245 | be similar in spirit to the present version, but may differ in detail to 246 | address new problems or concerns. 247 | 248 | Each version is given a distinguishing version number. If the Program 249 | specifies a version number of this License which applies to it and "any 250 | later version", you have the option of following the terms and conditions 251 | either of that version or of any later version published by the Free 252 | Software Foundation. If the Program does not specify a version number of 253 | this License, you may choose any version ever published by the Free Software 254 | Foundation. 255 | 256 | 10. If you wish to incorporate parts of the Program into other free 257 | programs whose distribution conditions are different, write to the author 258 | to ask for permission. For software which is copyrighted by the Free 259 | Software Foundation, write to the Free Software Foundation; we sometimes 260 | make exceptions for this. Our decision will be guided by the two goals 261 | of preserving the free status of all derivatives of our free software and 262 | of promoting the sharing and reuse of software generally. 263 | 264 | NO WARRANTY 265 | 266 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 267 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 268 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 269 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 270 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 271 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 272 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 273 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 274 | REPAIR OR CORRECTION. 275 | 276 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 277 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 278 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 279 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 280 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 281 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 282 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 283 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 284 | POSSIBILITY OF SUCH DAMAGES. 285 | 286 | END OF TERMS AND CONDITIONS 287 | 288 | How to Apply These Terms to Your New Programs 289 | 290 | If you develop a new program, and you want it to be of the greatest 291 | possible use to the public, the best way to achieve this is to make it 292 | free software which everyone can redistribute and change under these terms. 293 | 294 | To do so, attach the following notices to the program. It is safest 295 | to attach them to the start of each source file to most effectively 296 | convey the exclusion of warranty; and each file should have at least 297 | the "copyright" line and a pointer to where the full notice is found. 298 | 299 | 300 | Copyright (C) 19yy 301 | 302 | This program is free software; you can redistribute it and/or modify 303 | it under the terms of the GNU General Public License as published by 304 | the Free Software Foundation; either version 2 of the License, or 305 | (at your option) any later version. 306 | 307 | This program is distributed in the hope that it will be useful, 308 | but WITHOUT ANY WARRANTY; without even the implied warranty of 309 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 310 | GNU General Public License for more details. 311 | 312 | You should have received a copy of the GNU General Public License 313 | along with this program; if not, write to the Free Software 314 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 315 | 316 | 317 | Also add information on how to contact you by electronic and paper mail. 318 | 319 | If the program is interactive, make it output a short notice like this 320 | when it starts in an interactive mode: 321 | 322 | Gnomovision version 69, Copyright (C) 19yy name of author 323 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 324 | This is free software, and you are welcome to redistribute it 325 | under certain conditions; type `show c' for details. 326 | 327 | The hypothetical commands `show w' and `show c' should show the appropriate 328 | parts of the General Public License. Of course, the commands you use may 329 | be called something other than `show w' and `show c'; they could even be 330 | mouse-clicks or menu items--whatever suits your program. 331 | 332 | You should also get your employer (if you work as a programmer) or your 333 | school, if any, to sign a "copyright disclaimer" for the program, if 334 | necessary. Here is a sample; alter the names: 335 | 336 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 337 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 338 | 339 | , 1 April 1989 340 | Ty Coon, President of Vice 341 | 342 | This General Public License does not permit incorporating your program into 343 | proprietary programs. If your program is a subroutine library, you may 344 | consider it more useful to permit linking proprietary applications with the 345 | library. If this is what you want to do, use the GNU Library General 346 | Public License instead of this License. 347 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ditto menu 2 | 3 | Menu launcher for plasma KDE 4 | 5 | ### Features 6 | 7 | - Custom menu position 8 | - Hide applications 9 | - Favorite applications 10 | 11 | ## Installation 12 | 13 | Before using the menu, install the addons in your linux distribution. 14 | 15 | ```bash 16 | # Ubuntu Jammy 17 | sudo apt install plasma-widgets-addons 18 | 19 | # Arch / Manjaro 20 | sudo pacman -S kdeplasma-addons 21 | 22 | ``` 23 | Install the menu from: [https://store.kde.org/p/1312669/](https://store.kde.org/p/1312669/) or download from New Plasma Widgets. 24 | 25 | 26 | ## Screenshots 27 | 28 | ![Image of ditto](https://raw.githubusercontent.com/adhec/dittoMenuKDE/main/preview.jpg) 29 | 30 | ## License 31 | 32 | This project is [GPL-2.0+](https://choosealicense.com/licenses/gpl-2.0/) license 33 | 34 | 35 | ## Contributing 36 | 37 | Contributions are always welcome! 38 | 39 | ## Support 40 | 41 | You can also help the project. 42 | 43 |

44 | 45 | PayPal 46 | 47 | 48 | Liberapay 49 | 50 |

51 | 52 | 53 | ## Translating 54 | 55 | See the [package/translate](package/translate) folder for translation instructions. 56 | -------------------------------------------------------------------------------- /package/contents/code/tools.js: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2013 by Aurélien Gâteau * 3 | * Copyright (C) 2013-2015 by Eike Hein * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 2 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * GNU General Public License for more details. * 14 | * * 15 | * You should have received a copy of the GNU General Public License * 16 | * along with this program; if not, write to the * 17 | * Free Software Foundation, Inc., * 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * 19 | ***************************************************************************/ 20 | 21 | .pragma library 22 | 23 | function fillActionMenu(i18n, actionMenu, actionList, favoriteModel, favoriteId) { 24 | // Accessing actionList can be a costly operation, so we don't 25 | // access it until we need the menu. 26 | 27 | var actions = createFavoriteActions(i18n, favoriteModel, favoriteId); 28 | 29 | if (actions) { 30 | if (actionList && actionList.length > 0) { 31 | var separator = { "type": "separator" }; 32 | actionList.unshift(separator); 33 | // actionList = actions.concat(actionList); // this crashes Qt O.o 34 | actionList.unshift.apply(actionList, actions); 35 | } else { 36 | actionList = actions; 37 | } 38 | } 39 | 40 | actionMenu.actionList = actionList; 41 | } 42 | 43 | function createFavoriteActions(i18n, favoriteModel, favoriteId) { 44 | if (favoriteModel === null || !favoriteModel.enabled || favoriteId == null) { 45 | return null; 46 | } 47 | 48 | if ("initForClient" in favoriteModel) { 49 | var activities = favoriteModel.activities.runningActivities; 50 | 51 | if (activities.length <= 1) { 52 | var action = {}; 53 | 54 | if (favoriteModel.isFavorite(favoriteId)) { 55 | action.text = i18n("Remove from Favorites"); 56 | action.icon = "list-remove"; 57 | action.actionId = "_kicker_favorite_remove"; 58 | } else if (favoriteModel.maxFavorites == -1 || favoriteModel.count < favoriteModel.maxFavorites) { 59 | action.text = i18n("Add to Favorites"); 60 | action.icon = "bookmark-new"; 61 | action.actionId = "_kicker_favorite_add"; 62 | } else { 63 | return null; 64 | } 65 | 66 | action.actionArgument = { favoriteModel: favoriteModel, favoriteId: favoriteId }; 67 | 68 | return [action]; 69 | 70 | } else { 71 | var actions = []; 72 | 73 | var linkedActivities = favoriteModel.linkedActivitiesFor(favoriteId); 74 | 75 | // Adding the item to link/unlink to all activities 76 | 77 | var linkedToAllActivities = 78 | !(linkedActivities.indexOf(":global") === -1); 79 | 80 | actions.push({ 81 | text : i18n("On All Activities"), 82 | checkable : true, 83 | 84 | actionId : linkedToAllActivities ? 85 | "_kicker_favorite_remove_from_activity" : 86 | "_kicker_favorite_set_to_activity", 87 | checked : linkedToAllActivities, 88 | 89 | actionArgument : { 90 | favoriteModel: favoriteModel, 91 | favoriteId: favoriteId, 92 | favoriteActivity: "" 93 | } 94 | }); 95 | 96 | 97 | // Adding items for each activity separately 98 | 99 | var addActivityItem = function(activityId, activityName) { 100 | var linkedToThisActivity = 101 | !(linkedActivities.indexOf(activityId) === -1); 102 | 103 | actions.push({ 104 | text : activityName, 105 | checkable : true, 106 | checked : linkedToThisActivity && !linkedToAllActivities, 107 | 108 | actionId : 109 | // If we are on all activities, and the user clicks just one 110 | // specific activity, unlink from everything else 111 | linkedToAllActivities ? "_kicker_favorite_set_to_activity" : 112 | 113 | // If we are linked to the current activity, just unlink from 114 | // that single one 115 | linkedToThisActivity ? "_kicker_favorite_remove_from_activity" : 116 | 117 | // Otherwise, link to this activity, but do not unlink from 118 | // other ones 119 | "_kicker_favorite_add_to_activity", 120 | 121 | actionArgument : { 122 | favoriteModel : favoriteModel, 123 | favoriteId : favoriteId, 124 | favoriteActivity : activityId 125 | } 126 | }); 127 | }; 128 | 129 | // Adding the item to link/unlink to the current activity 130 | 131 | addActivityItem(favoriteModel.activities.currentActivity, i18n("On The Current Activity")); 132 | 133 | actions.push({ 134 | type: "separator", 135 | actionId: "_kicker_favorite_separator" 136 | }); 137 | 138 | // Adding the items for each activity 139 | 140 | activities.forEach(function(activityId) { 141 | addActivityItem(activityId, favoriteModel.activityNameForId(activityId)); 142 | }); 143 | 144 | return [{ 145 | text : i18n("Show In Favorites"), 146 | icon : "favorite", 147 | subActions : actions 148 | }]; 149 | } 150 | } else { 151 | var action = {}; 152 | 153 | if (favoriteModel.isFavorite(favoriteId)) { 154 | action.text = i18n("Remove from Favorites"); 155 | action.icon = "list-remove"; 156 | action.actionId = "_kicker_favorite_remove"; 157 | } else if (favoriteModel.maxFavorites == -1 || favoriteModel.count < favoriteModel.maxFavorites) { 158 | action.text = i18n("Add to Favorites"); 159 | action.icon = "bookmark-new"; 160 | action.actionId = "_kicker_favorite_add"; 161 | } else { 162 | return null; 163 | } 164 | 165 | action.actionArgument = { favoriteModel: favoriteModel, favoriteId: favoriteId }; 166 | 167 | return [action]; 168 | } 169 | } 170 | 171 | function triggerAction(plasmoid, model, index, actionId, actionArgument) { 172 | function startsWith(txt, needle) { 173 | return txt.substr(0, needle.length) === needle; 174 | } 175 | 176 | if (startsWith(actionId, "_kicker_favorite_")) { 177 | handleFavoriteAction(actionId, actionArgument); 178 | return; 179 | } 180 | 181 | var closeRequested = model.trigger(index, actionId, actionArgument); 182 | 183 | if (closeRequested) { 184 | plasmoid.expanded = false; 185 | 186 | return true; 187 | } 188 | 189 | return false; 190 | } 191 | 192 | function handleFavoriteAction(actionId, actionArgument) { 193 | var favoriteId = actionArgument.favoriteId; 194 | var favoriteModel = actionArgument.favoriteModel; 195 | 196 | console.log(actionId); 197 | 198 | if (favoriteModel === null || favoriteId == null) { 199 | return null; 200 | } 201 | 202 | if ("initForClient" in favoriteModel) { 203 | if (actionId == "_kicker_favorite_remove") { 204 | console.log("Removing from all activities"); 205 | favoriteModel.removeFavoriteFrom(favoriteId, ":any"); 206 | 207 | } else if (actionId == "_kicker_favorite_add") { 208 | console.log("Adding to global activity"); 209 | favoriteModel.addFavoriteTo(favoriteId, ":global"); 210 | 211 | } else if (actionId == "_kicker_favorite_remove_from_activity") { 212 | console.log("Removing from a specific activity"); 213 | favoriteModel.removeFavoriteFrom(favoriteId, actionArgument.favoriteActivity); 214 | 215 | } else if (actionId == "_kicker_favorite_add_to_activity") { 216 | console.log("Adding to another activity"); 217 | favoriteModel.addFavoriteTo(favoriteId, actionArgument.favoriteActivity); 218 | 219 | } else if (actionId == "_kicker_favorite_set_to_activity") { 220 | console.log("Removing the item from the favourites, and re-adding it just to be on a specific activity"); 221 | favoriteModel.setFavoriteOn(favoriteId, actionArgument.favoriteActivity); 222 | 223 | } 224 | } else { 225 | if (actionId == "_kicker_favorite_remove") { 226 | favoriteModel.removeFavorite(favoriteId); 227 | } else if (actionId == "_kicker_favorite_add") { 228 | favoriteModel.addFavorite(favoriteId); 229 | } 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /package/contents/config/config.qml: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2014 by Eike Hein * 3 | * * 4 | * This program is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU General Public License as published by * 6 | * the Free Software Foundation; either version 2 of the License, or * 7 | * (at your option) any later version. * 8 | * * 9 | * This program is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 12 | * GNU General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * 18 | ***************************************************************************/ 19 | 20 | import QtQuick 2.0 21 | 22 | import org.kde.plasma.configuration 2.0 23 | 24 | ConfigModel { 25 | ConfigCategory { 26 | name: i18n("General") 27 | icon: "kde" 28 | source: "ConfigGeneral.qml" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /package/contents/config/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Center 17 | 18 | 19 | 20 | start-here-kde 21 | 22 | 23 | false 24 | 25 | 26 | 27 | 28 | 29 | 30 | true 31 | 32 | 33 | 34 | 0 35 | 36 | 37 | false 38 | 39 | 40 | 41 | 6 42 | 43 | 44 | 45 | 4 46 | 47 | 48 | 49 | preferred://browser,kontact.desktop,systemsettings.desktop,org.kde.dolphin.desktop,ktp-contactlist.desktop,org.kde.kate.desktop 50 | 51 | 52 | logout,lock-screen,reboot,shutdown 53 | 54 | 55 | 56 | 57 | 58 | 59 | true 60 | 61 | 62 | true 63 | 64 | 65 | bookmarks,baloosearch 66 | 67 | 68 | true 69 | 70 | 71 | 72 | true 73 | 74 | 75 | 76 | muon-discover --application 77 | 78 | 79 | true 80 | 81 | 82 | false 83 | 84 | 85 | 86 | false 87 | 88 | 89 | 90 | true 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /package/contents/locale/ko/LC_MESSAGES/plasma_applet_org.kde.plasma.dittomenu.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adhec/dittoMenuKDE/ecb2f46f91102d9f7273abedcf97cf1efd5debf4/package/contents/locale/ko/LC_MESSAGES/plasma_applet_org.kde.plasma.dittomenu.mo -------------------------------------------------------------------------------- /package/contents/locale/nl/LC_MESSAGES/plasma_applet_org.kde.plasma.dittomenu.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adhec/dittoMenuKDE/ecb2f46f91102d9f7273abedcf97cf1efd5debf4/package/contents/locale/nl/LC_MESSAGES/plasma_applet_org.kde.plasma.dittomenu.mo -------------------------------------------------------------------------------- /package/contents/locale/pl/LC_MESSAGES/plasma_applet_org.kde.plasma.dittomenu.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adhec/dittoMenuKDE/ecb2f46f91102d9f7273abedcf97cf1efd5debf4/package/contents/locale/pl/LC_MESSAGES/plasma_applet_org.kde.plasma.dittomenu.mo -------------------------------------------------------------------------------- /package/contents/locale/pt_BR/LC_MESSAGES/plasma_applet_org.kde.plasma.dittomenu.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adhec/dittoMenuKDE/ecb2f46f91102d9f7273abedcf97cf1efd5debf4/package/contents/locale/pt_BR/LC_MESSAGES/plasma_applet_org.kde.plasma.dittomenu.mo -------------------------------------------------------------------------------- /package/contents/locale/ru/LC_MESSAGES/plasma_applet_org.kde.plasma.dittomenu.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adhec/dittoMenuKDE/ecb2f46f91102d9f7273abedcf97cf1efd5debf4/package/contents/locale/ru/LC_MESSAGES/plasma_applet_org.kde.plasma.dittomenu.mo -------------------------------------------------------------------------------- /package/contents/locale/template/LC_MESSAGES/plasma_applet_org.kde.plasma.dittomenu.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adhec/dittoMenuKDE/ecb2f46f91102d9f7273abedcf97cf1efd5debf4/package/contents/locale/template/LC_MESSAGES/plasma_applet_org.kde.plasma.dittomenu.mo -------------------------------------------------------------------------------- /package/contents/locale/tr/LC_MESSAGES/plasma_applet_org.kde.plasma.dittomenu.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adhec/dittoMenuKDE/ecb2f46f91102d9f7273abedcf97cf1efd5debf4/package/contents/locale/tr/LC_MESSAGES/plasma_applet_org.kde.plasma.dittomenu.mo -------------------------------------------------------------------------------- /package/contents/ui/ActionMenu.qml: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2013 by Aurélien Gâteau * 3 | * Copyright (C) 2014-2015 by Eike Hein * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 2 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * GNU General Public License for more details. * 14 | * * 15 | * You should have received a copy of the GNU General Public License * 16 | * along with this program; if not, write to the * 17 | * Free Software Foundation, Inc., * 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * 19 | ***************************************************************************/ 20 | 21 | import QtQuick 2.0 22 | 23 | import org.kde.plasma.components 2.0 as PlasmaComponents 24 | 25 | Item { 26 | id: root 27 | 28 | property QtObject menu 29 | property Item visualParent 30 | property variant actionList 31 | property bool opened: menu ? (menu.status != PlasmaComponents.DialogStatus.Closed) : false 32 | 33 | signal actionClicked(string actionId, variant actionArgument) 34 | signal closed 35 | 36 | onActionListChanged: refreshMenu(); 37 | 38 | onOpenedChanged: { 39 | if (!opened) { 40 | closed(); 41 | } 42 | } 43 | 44 | function open(x, y) { 45 | if (!actionList) { 46 | return; 47 | } 48 | 49 | if (x && y) { 50 | menu.open(x, y); 51 | } else { 52 | menu.open(); 53 | } 54 | } 55 | 56 | function refreshMenu() { 57 | if (menu) { 58 | menu.destroy(); 59 | } 60 | 61 | if (!actionList) { 62 | return; 63 | } 64 | 65 | menu = contextMenuComponent.createObject(root); 66 | 67 | fillMenu(menu, actionList); 68 | } 69 | 70 | function fillMenu(menu, items) { 71 | items.forEach(function(actionItem) { 72 | if (actionItem.subActions) { 73 | // This is a menu 74 | var submenuItem = contextSubmenuItemComponent.createObject( 75 | menu, { "actionItem" : actionItem }); 76 | 77 | fillMenu(submenuItem.submenu, actionItem.subActions); 78 | 79 | } else { 80 | var item = contextMenuItemComponent.createObject( 81 | menu, 82 | { 83 | "actionItem": actionItem, 84 | } 85 | ); 86 | } 87 | }); 88 | 89 | } 90 | 91 | Component { 92 | id: contextMenuComponent 93 | 94 | PlasmaComponents.ContextMenu { 95 | visualParent: root.visualParent 96 | } 97 | } 98 | 99 | Component { 100 | id: contextSubmenuItemComponent 101 | 102 | PlasmaComponents.MenuItem { 103 | id: submenuItem 104 | 105 | property variant actionItem 106 | 107 | text: actionItem.text ? actionItem.text : "" 108 | icon: actionItem.icon ? actionItem.icon : null 109 | 110 | property variant submenu : submenu_ 111 | 112 | PlasmaComponents.ContextMenu { 113 | id: submenu_ 114 | visualParent: submenuItem.action 115 | } 116 | } 117 | } 118 | 119 | Component { 120 | id: contextMenuItemComponent 121 | 122 | PlasmaComponents.MenuItem { 123 | property variant actionItem 124 | 125 | text : actionItem.text ? actionItem.text : "" 126 | enabled : actionItem.type != "title" && ("enabled" in actionItem ? actionItem.enabled : true) 127 | separator : actionItem.type == "separator" 128 | section : actionItem.type == "title" 129 | icon : actionItem.icon ? actionItem.icon : null 130 | checkable : actionItem.checkable ? actionItem.checkable : false 131 | checked : actionItem.checked ? actionItem.checked : false 132 | 133 | onClicked: { 134 | actionClicked(actionItem.actionId, actionItem.actionArgument); 135 | } 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /package/contents/ui/CompactRepresentation.qml: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2013-2014 by Eike Hein * 3 | * * 4 | * This program is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU General Public License as published by * 6 | * the Free Software Foundation; either version 2 of the License, or * 7 | * (at your option) any later version. * 8 | * * 9 | * This program is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 12 | * GNU General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * 18 | ***************************************************************************/ 19 | 20 | import QtQuick 2.0 21 | import QtQuick.Layouts 1.1 22 | 23 | import org.kde.plasma.plasmoid 2.0 24 | import org.kde.plasma.core 2.0 as PlasmaCore 25 | 26 | Item { 27 | id: root 28 | 29 | readonly property var screenGeometry: plasmoid.screenGeometry 30 | readonly property bool inPanel: (plasmoid.location == PlasmaCore.Types.TopEdge 31 | || plasmoid.location == PlasmaCore.Types.RightEdge 32 | || plasmoid.location == PlasmaCore.Types.BottomEdge 33 | || plasmoid.location == PlasmaCore.Types.LeftEdge) 34 | readonly property bool vertical: (plasmoid.formFactor == PlasmaCore.Types.Vertical) 35 | readonly property bool useCustomButtonImage: (plasmoid.configuration.useCustomButtonImage 36 | && plasmoid.configuration.customButtonImage.length != 0) 37 | property QtObject dashWindow: null 38 | 39 | Plasmoid.status: dashWindow && dashWindow.visible ? PlasmaCore.Types.RequiresAttentionStatus : PlasmaCore.Types.PassiveStatus 40 | 41 | onWidthChanged: updateSizeHints() 42 | onHeightChanged: updateSizeHints() 43 | 44 | function updateSizeHints() { 45 | if (useCustomButtonImage) { 46 | if (vertical) { 47 | var scaledHeight = Math.floor(parent.width * (buttonIcon.implicitHeight / buttonIcon.implicitWidth)); 48 | root.Layout.minimumHeight = scaledHeight; 49 | root.Layout.maximumHeight = scaledHeight; 50 | root.Layout.minimumWidth = PlasmaCore.Units.iconSizes.small; 51 | root.Layout.maximumWidth = inPanel ? PlasmaCore.Units.iconSizeHints.panel : -1; 52 | } else { 53 | var scaledWidth = Math.floor(parent.height * (buttonIcon.implicitWidth / buttonIcon.implicitHeight)); 54 | root.Layout.minimumWidth = scaledWidth; 55 | root.Layout.maximumWidth = scaledWidth; 56 | root.Layout.minimumHeight = PlasmaCore.Units.iconSizes.small; 57 | root.Layout.maximumHeight = inPanel ? PlasmaCore.Units.iconSizeHints.panel : -1; 58 | } 59 | } else { 60 | root.Layout.minimumWidth = PlasmaCore.Units.iconSizes.small; 61 | root.Layout.maximumWidth = inPanel ? PlasmaCore.Units.iconSizeHints.panel : -1; 62 | root.Layout.minimumHeight = PlasmaCore.Units.iconSizes.small 63 | root.Layout.maximumHeight = inPanel ? PlasmaCore.Units.iconSizeHints.panel : -1; 64 | } 65 | } 66 | 67 | Connections { 68 | target: PlasmaCore.Units.iconSizeHints 69 | function onPanelChanged(){ updateSizeHints()} 70 | } 71 | 72 | PlasmaCore.IconItem { 73 | id: buttonIcon 74 | 75 | anchors.fill: parent 76 | 77 | readonly property double aspectRatio: (vertical ? implicitHeight / implicitWidth 78 | : implicitWidth / implicitHeight) 79 | 80 | source: useCustomButtonImage ? plasmoid.configuration.customButtonImage : plasmoid.configuration.icon 81 | 82 | active: mouseArea.containsMouse 83 | 84 | smooth: true 85 | 86 | // A custom icon could also be rectangular. However, if a square, custom, icon is given, assume it 87 | // to be an icon and round it to the nearest icon size again to avoid scaling artefacts. 88 | roundToIconSize: !useCustomButtonImage || aspectRatio === 1 89 | 90 | onSourceChanged: updateSizeHints() 91 | } 92 | 93 | MouseArea 94 | { 95 | id: mouseArea 96 | 97 | anchors.fill: parent 98 | 99 | hoverEnabled: true 100 | 101 | onClicked: { 102 | dashWindow.visible = !dashWindow.visible; 103 | } 104 | } 105 | 106 | Component.onCompleted: { 107 | dashWindow = Qt.createQmlObject("MenuRepresentation {}", root); 108 | plasmoid.activated.connect(function() { 109 | dashWindow.visible = !dashWindow.visible; 110 | }); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /package/contents/ui/ConfigGeneral.qml: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2014 by Eike Hein * 3 | * * 4 | * This program is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU General Public License as published by * 6 | * the Free Software Foundation; either version 2 of the License, or * 7 | * (at your option) any later version. * 8 | * * 9 | * This program is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 12 | * GNU General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * 18 | ***************************************************************************/ 19 | 20 | import QtQuick 2.0 21 | import QtQuick.Controls 1.0 22 | import QtQuick.Dialogs 1.2 23 | import QtQuick.Layouts 1.0 24 | 25 | import org.kde.plasma.core 2.0 as PlasmaCore 26 | import org.kde.plasma.components 2.0 as PlasmaComponents 27 | 28 | import org.kde.kquickcontrolsaddons 2.0 as KQuickAddons 29 | import org.kde.draganddrop 2.0 as DragDrop 30 | 31 | import org.kde.kirigami 2.4 as Kirigami 32 | 33 | 34 | Kirigami.FormLayout { 35 | id: configGeneral 36 | 37 | 38 | property string cfg_icon: plasmoid.configuration.icon 39 | property bool cfg_useCustomButtonImage: plasmoid.configuration.useCustomButtonImage 40 | property string cfg_customButtonImage: plasmoid.configuration.customButtonImage 41 | 42 | //property alias cfg_appNameFormat: appNameFormat.currentIndex 43 | //property alias cfg_switchCategoriesOnHover: switchCategoriesOnHover.checked 44 | 45 | //property alias cfg_useExtraRunners: useExtraRunners.checked 46 | 47 | property alias cfg_numberColumns: numberColumns.value 48 | property alias cfg_numberRows: numberRows.value 49 | property alias cfg_showFavoritesFirst: showFavoritesFirst.checked 50 | 51 | 52 | property alias cfg_labels2lines: labels2lines.checked 53 | property alias cfg_displayPosition: displayPosition.currentIndex 54 | 55 | 56 | RowLayout { 57 | spacing: PlasmaCore.Units.smallSpacing 58 | Kirigami.FormData.label: i18n("Icon:") 59 | 60 | 61 | Button { 62 | id: iconButton 63 | Layout.minimumWidth: previewFrame.width + PlasmaCore.Units.smallSpacing * 2 64 | Layout.maximumWidth: Layout.minimumWidth 65 | Layout.minimumHeight: previewFrame.height + PlasmaCore.Units.smallSpacing * 2 66 | Layout.maximumHeight: Layout.minimumWidth 67 | 68 | DragDrop.DropArea { 69 | id: dropArea 70 | 71 | property bool containsAcceptableDrag: false 72 | 73 | anchors.fill: parent 74 | 75 | onDragEnter: { 76 | // Cannot use string operations (e.g. indexOf()) on "url" basic type. 77 | var urlString = event.mimeData.url.toString(); 78 | 79 | // This list is also hardcoded in KIconDialog. 80 | var extensions = [".png", ".xpm", ".svg", ".svgz"]; 81 | containsAcceptableDrag = urlString.indexOf("file:///") === 0 && extensions.some(function (extension) { 82 | return urlString.indexOf(extension) === urlString.length - extension.length; // "endsWith" 83 | }); 84 | 85 | if (!containsAcceptableDrag) { 86 | event.ignore(); 87 | } 88 | } 89 | onDragLeave: containsAcceptableDrag = false 90 | 91 | onDrop: { 92 | if (containsAcceptableDrag) { 93 | // Strip file:// prefix, we already verified in onDragEnter that we have only local URLs. 94 | iconDialog.setCustomButtonImage(event.mimeData.url.toString().substr("file://".length)); 95 | } 96 | containsAcceptableDrag = false; 97 | } 98 | } 99 | 100 | KQuickAddons.IconDialog { 101 | id: iconDialog 102 | 103 | function setCustomButtonImage(image) { 104 | cfg_customButtonImage = image || cfg_icon || "start-here-kde" 105 | cfg_useCustomButtonImage = true; 106 | } 107 | 108 | onIconNameChanged: setCustomButtonImage(iconName); 109 | } 110 | 111 | // just to provide some visual feedback, cannot have checked without checkable enabled 112 | checkable: true 113 | checked: dropArea.containsAcceptableDrag 114 | onClicked: { 115 | checked = Qt.binding(function() { // never actually allow it being checked 116 | return iconMenu.status === PlasmaComponents.DialogStatus.Open || dropArea.containsAcceptableDrag; 117 | }) 118 | 119 | iconMenu.open(0, height) 120 | } 121 | 122 | PlasmaCore.FrameSvgItem { 123 | id: previewFrame 124 | anchors.centerIn: parent 125 | imagePath: plasmoid.location === PlasmaCore.Types.Vertical || plasmoid.location === PlasmaCore.Types.Horizontal 126 | ? "widgets/panel-background" : "widgets/background" 127 | width: PlasmaCore.Units.iconSizes.large + fixedMargins.left + fixedMargins.right 128 | height: PlasmaCore.Units.iconSizes.large + fixedMargins.top + fixedMargins.bottom 129 | 130 | PlasmaCore.IconItem { 131 | anchors.centerIn: parent 132 | width: PlasmaCore.Units.iconSizes.large 133 | height: width 134 | source: cfg_useCustomButtonImage ? cfg_customButtonImage : cfg_icon 135 | } 136 | } 137 | } 138 | 139 | // QQC Menu can only be opened at cursor position, not a random one 140 | PlasmaComponents.ContextMenu { 141 | id: iconMenu 142 | visualParent: iconButton 143 | 144 | PlasmaComponents.MenuItem { 145 | text: i18nc("@item:inmenu Open icon chooser dialog", "Choose...") 146 | icon: "document-open-folder" 147 | onClicked: iconDialog.open() 148 | } 149 | PlasmaComponents.MenuItem { 150 | text: i18nc("@item:inmenu Reset icon to default", "Clear Icon") 151 | icon: "edit-clear" 152 | onClicked: { 153 | cfg_useCustomButtonImage = false; 154 | } 155 | } 156 | } 157 | } 158 | 159 | 160 | CheckBox { 161 | id: showFavoritesFirst 162 | Kirigami.FormData.label: i18n("Show favorites first") 163 | } 164 | 165 | ComboBox { 166 | Kirigami.FormData.label: i18n("Menu position") 167 | id: displayPosition 168 | model: [ 169 | i18n("Default"), 170 | i18n("Center"), 171 | i18n("Center bottom"), 172 | ] 173 | onActivated: cfg_displayPosition = currentIndex 174 | } 175 | 176 | 177 | CheckBox { 178 | id: labels2lines 179 | text: i18n("Show labels in two lines") 180 | } 181 | 182 | SpinBox{ 183 | id: numberColumns 184 | minimumValue: 4 185 | maximumValue: 10 186 | Kirigami.FormData.label: i18n("Number of columns") 187 | 188 | } 189 | 190 | SpinBox{ 191 | id: numberRows 192 | minimumValue: 1 193 | maximumValue: 10 194 | Kirigami.FormData.label: i18n("Number of rows") 195 | } 196 | 197 | RowLayout{ 198 | 199 | //Layout.fillWidth: true 200 | Button { 201 | text: i18n("Unhide all hidden applications") 202 | onClicked: { 203 | plasmoid.configuration.hiddenApplications = [""]; 204 | unhideAllAppsPopup.text = i18n("Unhidden!"); 205 | } 206 | } 207 | Label { 208 | id: unhideAllAppsPopup 209 | } 210 | } 211 | 212 | } 213 | -------------------------------------------------------------------------------- /package/contents/ui/ItemGridDelegate.qml: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2015 by Eike Hein * 3 | * * 4 | * This program is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU General Public License as published by * 6 | * the Free Software Foundation; either version 2 of the License, or * 7 | * (at your option) any later version. * 8 | * * 9 | * This program is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 12 | * GNU General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * 18 | ***************************************************************************/ 19 | 20 | import QtQuick 2.0 21 | 22 | import org.kde.plasma.core 2.0 as PlasmaCore 23 | import org.kde.plasma.components 2.0 as PlasmaComponents 24 | 25 | import "../code/tools.js" as Tools 26 | 27 | Item { 28 | id: item 29 | 30 | width: GridView.view.cellWidth 31 | height: GridView.view.cellHeight 32 | 33 | property bool showLabel: true 34 | 35 | property int itemIndex: model.index 36 | property string favoriteId: model.favoriteId !== undefined ? model.favoriteId : "" 37 | property url url: model.url !== undefined ? model.url : "" 38 | property variant icon: model.decoration !== undefined ? model.decoration : "" 39 | property var m: model 40 | property bool hasActionList: ((model.favoriteId !== null) 41 | || (("hasActionList" in model) && (model.hasActionList === true))) 42 | 43 | Accessible.role: Accessible.MenuItem 44 | Accessible.name: model.display 45 | 46 | function openActionMenu(x, y) { 47 | var actionList = hasActionList ? model.actionList : []; 48 | Tools.fillActionMenu(i18n, actionMenu, actionList, GridView.view.model.favoritesModel, model.favoriteId); 49 | actionMenu.visualParent = item; 50 | actionMenu.open(x, y); 51 | } 52 | 53 | function actionTriggered(actionId, actionArgument) { 54 | var close = (Tools.triggerAction(plasmoid, GridView.view.model, model.index, actionId, actionArgument) === true); 55 | if (close) root.toggle(); 56 | } 57 | 58 | Item{ 59 | height: iconSize + PlasmaCore.Units.gridUnit * 2 + PlasmaCore.Units.smallSpacing 60 | width: parent.width 61 | anchors.centerIn: parent 62 | 63 | PlasmaCore.IconItem { 64 | id: icon 65 | anchors{ 66 | top: parent.top 67 | horizontalCenter: parent.horizontalCenter 68 | } 69 | width: root.iconSize 70 | height: width 71 | colorGroup: PlasmaCore.Theme.ComplementaryColorGroup 72 | animated: false 73 | usesPlasmaTheme: item.GridView.view.usesPlasmaTheme 74 | source: model.decoration 75 | } 76 | 77 | PlasmaComponents.Label { 78 | id: label 79 | visible: showLabel 80 | anchors { 81 | top: icon.bottom 82 | topMargin: PlasmaCore.Units.smallSpacing 83 | horizontalCenter: parent.horizontalCenter 84 | } 85 | maximumLineCount: plasmoid.configuration.labels2lines ? 2 : 1 86 | horizontalAlignment: Text.AlignHCenter 87 | width: parent.width - PlasmaCore.Units.largeSpacing 88 | height: PlasmaCore.Units.gridUnit * 2 89 | elide: Text.ElideRight 90 | wrapMode: Text.Wrap 91 | color: theme.textColor 92 | text: ("name" in model ? model.name : model.display) 93 | } 94 | } 95 | PlasmaCore.ToolTipArea { 96 | id: toolTip 97 | property string text: model.display 98 | anchors.fill: parent 99 | active: root.visible && label.truncated 100 | mainItem: toolTipDelegate 101 | onContainsMouseChanged: item.GridView.view.itemContainsMouseChanged(containsMouse) 102 | } 103 | 104 | Keys.onPressed: { 105 | if (event.key === Qt.Key_Menu && hasActionList) { 106 | event.accepted = true; 107 | openActionMenu(item); 108 | } else if ((event.key === Qt.Key_Enter || event.key === Qt.Key_Return)) { 109 | event.accepted = true; 110 | if ("trigger" in GridView.view.model) { 111 | GridView.view.model.trigger(index, "", null); 112 | root.toggle(); 113 | } 114 | 115 | itemGrid.itemActivated(index, "", null); 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /package/contents/ui/ItemGridView.qml: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2015 by Eike Hein * 3 | * * 4 | * This program is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU General Public License as published by * 6 | * the Free Software Foundation; either version 2 of the License, or * 7 | * (at your option) any later version. * 8 | * * 9 | * This program is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 12 | * GNU General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * 18 | ***************************************************************************/ 19 | 20 | import QtQuick 2.4 21 | 22 | import org.kde.plasma.core 2.0 as PlasmaCore 23 | import org.kde.plasma.components 2.0 as PlasmaComponents 24 | import org.kde.plasma.extras 2.0 as PlasmaExtras 25 | import org.kde.kquickcontrolsaddons 2.0 26 | import org.kde.draganddrop 2.0 27 | import QtQuick.Controls 2.12 28 | 29 | FocusScope { 30 | id: itemGrid 31 | 32 | signal keyNavLeft 33 | signal keyNavRight 34 | signal keyNavUp 35 | signal keyNavDown 36 | 37 | signal itemActivated(int index, string actionId, string argument) 38 | 39 | property bool dragEnabled: false 40 | property bool dropEnabled: false 41 | property bool showLabels: true 42 | property alias usesPlasmaTheme: gridView.usesPlasmaTheme 43 | 44 | property alias currentIndex: gridView.currentIndex 45 | property alias currentItem: gridView.currentItem 46 | property alias contentItem: gridView.contentItem 47 | property alias count: gridView.count 48 | property alias model: gridView.model 49 | 50 | property alias cellWidth: gridView.cellWidth 51 | property alias cellHeight: gridView.cellHeight 52 | property alias iconSize: gridView.iconSize 53 | property alias scrollBar: scrollArea 54 | 55 | //<>property alias horizontalScrollBarPolicy: scrollArea.horizontalScrollBarPolicy 56 | //<>property alias verticalScrollBarPolicy: scrollArea.verticalScrollBarPolicy 57 | 58 | onDropEnabledChanged: { 59 | if (!dropEnabled && "dropPlaceHolderIndex" in model) { 60 | model.dropPlaceHolderIndex = -1; 61 | } 62 | } 63 | 64 | onFocusChanged: { 65 | if (!focus) { 66 | currentIndex = -1; 67 | } 68 | } 69 | 70 | function currentRow() { 71 | if (currentIndex == -1) { 72 | return -1; 73 | } 74 | 75 | return Math.floor(currentIndex / Math.floor(width / itemGrid.cellWidth)); 76 | } 77 | 78 | function currentCol() { 79 | if (currentIndex == -1) { 80 | return -1; 81 | } 82 | 83 | return currentIndex - (currentRow() * Math.floor(width / itemGrid.cellWidth)); 84 | } 85 | 86 | function lastRow() { 87 | var columns = Math.floor(width / itemGrid.cellWidth); 88 | return Math.ceil(count / columns) - 1; 89 | } 90 | 91 | function tryActivate(row, col) { 92 | if (count) { 93 | var columns = Math.floor(width / itemGrid.cellWidth); 94 | var rows = Math.ceil(count / columns); 95 | row = Math.min(row, rows - 1); 96 | col = Math.min(col, columns - 1); 97 | currentIndex = Math.min(row ? ((Math.max(1, row) * columns) + col) 98 | : col, 99 | count - 1); 100 | 101 | focus = true; 102 | } 103 | } 104 | 105 | function forceLayout() { 106 | gridView.forceLayout(); 107 | } 108 | 109 | ActionMenu { 110 | id: actionMenu 111 | 112 | onActionClicked: { 113 | visualParent.actionTriggered(actionId, actionArgument); 114 | } 115 | } 116 | 117 | DropArea { 118 | id: dropArea 119 | 120 | anchors.fill: parent 121 | 122 | onDragMove: { 123 | if (!itemGrid.dropEnabled || gridView.animating || !kicker.dragSource) { 124 | return; 125 | } 126 | 127 | var x = Math.max(0, event.x - (width % itemGrid.cellWidth)); 128 | var cPos = mapToItem(gridView.contentItem, x, event.y); 129 | var item = gridView.itemAt(cPos.x, cPos.y); 130 | 131 | if (item) { 132 | if (kicker.dragSource.parent === gridView.contentItem) { 133 | if (item !== kicker.dragSource) { 134 | item.GridView.view.model.moveRow(dragSource.itemIndex, item.itemIndex); 135 | } 136 | } else if (kicker.dragSource.GridView.view.model.favoritesModel === itemGrid.model 137 | && !itemGrid.model.isFavorite(kicker.dragSource.favoriteId)) { 138 | var hasPlaceholder = (itemGrid.model.dropPlaceholderIndex !== -1); 139 | 140 | itemGrid.model.dropPlaceholderIndex = item.itemIndex; 141 | 142 | if (!hasPlaceholder) { 143 | gridView.currentIndex = (item.itemIndex - 1); 144 | } 145 | } 146 | } else if (kicker.dragSource.parent !== gridView.contentItem 147 | && kicker.dragSource.GridView.view.model.favoritesModel === itemGrid.model 148 | && !itemGrid.model.isFavorite(kicker.dragSource.favoriteId)) { 149 | var hasPlaceholder = (itemGrid.model.dropPlaceholderIndex !== -1); 150 | 151 | itemGrid.model.dropPlaceholderIndex = hasPlaceholder ? itemGrid.model.count - 1 : itemGrid.model.count; 152 | 153 | if (!hasPlaceholder) { 154 | gridView.currentIndex = (itemGrid.model.count - 1); 155 | } 156 | } else { 157 | itemGrid.model.dropPlaceholderIndex = -1; 158 | gridView.currentIndex = -1; 159 | } 160 | } 161 | 162 | onDragLeave: { 163 | if ("dropPlaceholderIndex" in itemGrid.model) { 164 | itemGrid.model.dropPlaceholderIndex = -1; 165 | gridView.currentIndex = -1; 166 | } 167 | } 168 | 169 | onDrop: { 170 | if (kicker.dragSource && kicker.dragSource.parent !== gridView.contentItem && kicker.dragSource.GridView.view.model.favoritesModel === itemGrid.model) { 171 | itemGrid.model.addFavorite(kicker.dragSource.favoriteId, itemGrid.model.dropPlaceholderIndex); 172 | gridView.currentIndex = -1; 173 | } 174 | } 175 | 176 | Timer { 177 | id: resetAnimationDurationTimer 178 | 179 | interval: 120 180 | repeat: false 181 | 182 | onTriggered: { 183 | gridView.animationDuration = interval - 20; 184 | } 185 | } 186 | 187 | //PlasmaExtras.ScrollArea 188 | Flickable{ 189 | id: scrollArea 190 | 191 | clip: true 192 | anchors.fill: parent 193 | boundsBehavior: Flickable.StopAtBounds 194 | interactive: false 195 | focus: true 196 | 197 | GridView { 198 | id: gridView 199 | width: itemGrid.width 200 | height: itemGrid.height 201 | 202 | signal itemContainsMouseChanged(bool containsMouse) 203 | 204 | property bool usesPlasmaTheme: false 205 | 206 | property int iconSize: PlasmaCore.Units.iconSizes.huge 207 | 208 | property bool animating: false 209 | property int animationDuration: itemGrid.dropEnabled ? resetAnimationDurationTimer.interval : 0 210 | 211 | focus: true 212 | snapMode: GridView.SnapToRow 213 | 214 | ScrollBar.vertical: ScrollBar { 215 | visible: true 216 | active: true 217 | policy: ScrollBar.AlwaysOn; 218 | } 219 | 220 | currentIndex: -1 221 | 222 | move: Transition { 223 | enabled: itemGrid.dropEnabled 224 | 225 | SequentialAnimation { 226 | PropertyAction { target: gridView; property: "animating"; value: true } 227 | 228 | NumberAnimation { 229 | duration: gridView.animationDuration 230 | properties: "x, y" 231 | easing.type: Easing.OutQuad 232 | } 233 | 234 | PropertyAction { target: gridView; property: "animating"; value: false } 235 | } 236 | } 237 | 238 | moveDisplaced: Transition { 239 | enabled: itemGrid.dropEnabled 240 | 241 | SequentialAnimation { 242 | PropertyAction { target: gridView; property: "animating"; value: true } 243 | 244 | NumberAnimation { 245 | duration: gridView.animationDuration 246 | properties: "x, y" 247 | easing.type: Easing.OutQuad 248 | } 249 | 250 | PropertyAction { target: gridView; property: "animating"; value: false } 251 | } 252 | } 253 | 254 | keyNavigationWraps: false 255 | boundsBehavior: Flickable.StopAtBounds 256 | 257 | delegate: ItemGridDelegate { 258 | showLabel: itemGrid.showLabels 259 | } 260 | 261 | highlight: Item { 262 | property bool isDropPlaceHolder: "dropPlaceholderIndex" in itemGrid.model && itemGrid.currentIndex === itemGrid.model.dropPlaceholderIndex 263 | 264 | PlasmaComponents.Highlight { 265 | visible: gridView.currentItem && !isDropPlaceHolder 266 | 267 | anchors.fill: parent 268 | } 269 | 270 | PlasmaCore.FrameSvgItem { 271 | visible: gridView.currentItem && isDropPlaceHolder 272 | 273 | anchors.fill: parent 274 | 275 | imagePath: "widgets/viewitem" 276 | prefix: "selected" 277 | 278 | opacity: 0.5 279 | 280 | PlasmaCore.IconItem { 281 | anchors { 282 | right: parent.right 283 | rightMargin: parent.margins.right 284 | bottom: parent.bottom 285 | bottomMargin: parent.margins.bottom 286 | } 287 | 288 | width: PlasmaCore.Units.iconSizes.smallMedium 289 | height: width 290 | 291 | source: "list-add" 292 | active: false 293 | } 294 | } 295 | } 296 | 297 | highlightFollowsCurrentItem: true 298 | highlightMoveDuration: 0 299 | 300 | onCurrentIndexChanged: { 301 | if (currentIndex != -1) { 302 | hoverArea.hoverEnabled = false 303 | focus = true; 304 | } 305 | } 306 | 307 | onCountChanged: { 308 | animationDuration = 0; 309 | resetAnimationDurationTimer.start(); 310 | } 311 | 312 | onModelChanged: { 313 | currentIndex = -1; 314 | } 315 | 316 | Keys.onLeftPressed: { 317 | if (itemGrid.currentCol() !== 0) { 318 | event.accepted = true; 319 | moveCurrentIndexLeft(); 320 | } else { 321 | itemGrid.keyNavLeft(); 322 | } 323 | } 324 | 325 | Keys.onRightPressed: { 326 | var columns = Math.floor(width / cellWidth); 327 | 328 | if (itemGrid.currentCol() !== columns - 1 && currentIndex != count -1) { 329 | event.accepted = true; 330 | moveCurrentIndexRight(); 331 | } else { 332 | itemGrid.keyNavRight(); 333 | } 334 | } 335 | 336 | Keys.onUpPressed: { 337 | if (itemGrid.currentRow() !== 0) { 338 | event.accepted = true; 339 | moveCurrentIndexUp(); 340 | positionViewAtIndex(currentIndex, GridView.Contain); 341 | } else { 342 | itemGrid.keyNavUp(); 343 | } 344 | } 345 | 346 | Keys.onDownPressed: { 347 | if (itemGrid.currentRow() < itemGrid.lastRow()) { 348 | // Fix moveCurrentIndexDown()'s lack of proper spatial nav down 349 | // into partial columns. 350 | event.accepted = true; 351 | var columns = Math.floor(width / cellWidth); 352 | var newIndex = currentIndex + columns; 353 | currentIndex = Math.min(newIndex, count - 1); 354 | positionViewAtIndex(currentIndex, GridView.Contain); 355 | } else { 356 | itemGrid.keyNavDown(); 357 | } 358 | } 359 | 360 | onItemContainsMouseChanged: { 361 | if (!containsMouse) { 362 | if (!actionMenu.opened) { 363 | gridView.currentIndex = -1; 364 | } 365 | 366 | hoverArea.pressX = -1; 367 | hoverArea.pressY = -1; 368 | hoverArea.lastX = -1; 369 | hoverArea.lastY = -1; 370 | hoverArea.pressedItem = null; 371 | hoverArea.hoverEnabled = true; 372 | } 373 | } 374 | } 375 | } 376 | 377 | MouseArea { 378 | id: hoverArea 379 | 380 | //anchors.fill: parent 381 | width: itemGrid.width - PlasmaCore.Units.largeSpacing 382 | height: itemGrid.height 383 | 384 | 385 | property int pressX: -1 386 | property int pressY: -1 387 | property int lastX: -1 388 | property int lastY: -1 389 | property Item pressedItem: null 390 | 391 | acceptedButtons: Qt.LeftButton | Qt.RightButton 392 | 393 | hoverEnabled: true 394 | 395 | function updatePositionProperties(x, y) { 396 | // Prevent hover event synthesis in QQuickWindow interfering 397 | // with keyboard navigation by ignoring repeated events with 398 | // identical coordinates. As the work done here would be re- 399 | // dundant in any case, these are safe to ignore. 400 | if (lastX === x && lastY === y) { 401 | return; 402 | } 403 | 404 | lastX = x; 405 | lastY = y; 406 | 407 | var cPos = mapToItem(gridView.contentItem, x, y); 408 | var item = gridView.itemAt(cPos.x, cPos.y); 409 | 410 | if (!item) { 411 | gridView.currentIndex = -1; 412 | pressedItem = null; 413 | } else { 414 | gridView.currentIndex = item.itemIndex; 415 | itemGrid.focus = (itemGrid.currentIndex != -1) 416 | } 417 | 418 | return item; 419 | } 420 | 421 | onPressed: mouse => { 422 | mouse.accepted = true; 423 | 424 | updatePositionProperties(mouse.x, mouse.y); 425 | 426 | pressX = mouse.x; 427 | pressY = mouse.y; 428 | 429 | if (mouse.button == Qt.RightButton) { 430 | if (gridView.currentItem) { 431 | if (gridView.currentItem.hasActionList) { 432 | var mapped = mapToItem(gridView.currentItem, mouse.x, mouse.y); 433 | gridView.currentItem.openActionMenu(mapped.x, mapped.y); 434 | } 435 | } else { 436 | var mapped = mapToItem(rootItem, mouse.x, mouse.y); 437 | contextMenu.open(mapped.x, mapped.y); 438 | } 439 | } else { 440 | pressedItem = gridView.currentItem; 441 | } 442 | } 443 | 444 | onReleased: mouse => { 445 | mouse.accepted = true; 446 | updatePositionProperties(mouse.x, mouse.y); 447 | 448 | if (gridView.currentItem && gridView.currentItem == pressedItem) { 449 | if ("trigger" in gridView.model) { 450 | gridView.model.trigger(pressedItem.itemIndex, "", null); 451 | root.toggle(); 452 | } 453 | 454 | itemGrid.itemActivated(pressedItem.itemIndex, "", null); 455 | } else if (!dragHelper.dragging && !pressedItem && mouse.button == Qt.LeftButton) { 456 | root.toggle(); 457 | } 458 | 459 | pressX = -1; 460 | pressY = -1; 461 | pressedItem = null; 462 | } 463 | 464 | onPositionChanged: mouse => { 465 | var item = pressedItem? pressedItem : updatePositionProperties(mouse.x, mouse.y); 466 | 467 | if (gridView.currentIndex != -1) { 468 | if (itemGrid.dragEnabled && pressX != -1 && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) { 469 | if ("pluginName" in item.m) { 470 | dragHelper.startDrag(kicker, item.url, item.icon, 471 | "text/x-plasmoidservicename", item.m.pluginName); 472 | } else { 473 | dragHelper.startDrag(kicker, item.url, item.icon); 474 | } 475 | 476 | kicker.dragSource = item; 477 | 478 | pressX = -1; 479 | pressY = -1; 480 | } 481 | } 482 | } 483 | } 484 | } 485 | } 486 | -------------------------------------------------------------------------------- /package/contents/ui/ItemMultiGridView.qml: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2015 by Eike Hein * 3 | * * 4 | * This program is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU General Public License as published by * 6 | * the Free Software Foundation; either version 2 of the License, or * 7 | * (at your option) any later version. * 8 | * * 9 | * This program is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 12 | * GNU General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * 18 | ***************************************************************************/ 19 | 20 | import QtQuick 2.4 21 | 22 | import org.kde.plasma.core 2.0 as PlasmaCore 23 | import org.kde.plasma.extras 2.0 as PlasmaExtras 24 | 25 | import org.kde.plasma.private.kicker 0.1 as Kicker 26 | 27 | PlasmaExtras.ScrollArea { 28 | id: itemMultiGrid 29 | 30 | //anchors { 31 | // top: parent.top 32 | //} 33 | anchors.fill: parent 34 | 35 | //width: parent.width 36 | 37 | implicitHeight: itemColumn.implicitHeight 38 | 39 | signal keyNavLeft(int subGridIndex) 40 | signal keyNavRight(int subGridIndex) 41 | signal keyNavUp() 42 | signal keyNavDown() 43 | 44 | property bool grabFocus: false 45 | 46 | property alias model: repeater.model 47 | property alias count: repeater.count 48 | 49 | property int aCellHeight 50 | property int aCellWidth 51 | 52 | verticalScrollBarPolicy: Qt.ScrollBarAsNeeded 53 | horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff 54 | 55 | flickableItem.flickableDirection: Flickable.VerticalFlick 56 | 57 | onFocusChanged: { 58 | if (!focus) { 59 | for (var i = 0; i < repeater.count; i++) { 60 | subGridAt(i).focus = false; 61 | } 62 | } 63 | } 64 | 65 | function subGridAt(index) { 66 | return repeater.itemAt(index).itemGrid; 67 | } 68 | 69 | function tryActivate(row, col) { // FIXME TODO: Cleanup messy algo. 70 | if (flickableItem.contentY > 0) { 71 | row = 0; 72 | } 73 | 74 | var target = null; 75 | var rows = 0; 76 | 77 | for (var i = 0; i < repeater.count; i++) { 78 | var grid = subGridAt(i); 79 | 80 | if (rows <= row) { 81 | target = grid; 82 | rows += grid.lastRow() + 2; // Header counts as one. 83 | } else { 84 | break; 85 | } 86 | } 87 | 88 | if (target) { 89 | rows -= (target.lastRow() + 2); 90 | target.tryActivate(row - rows, col); 91 | } 92 | } 93 | 94 | Column { 95 | id: itemColumn 96 | 97 | width: itemMultiGrid.width //- PlasmaCore.Units.gridUnit 98 | 99 | Repeater { 100 | id: repeater 101 | 102 | delegate: Item { 103 | width: itemColumn.width 104 | //height: gridViewLabel.height + gridView.height + (index == repeater.count - 1 ? 0 : PlasmaCore.Units.smallSpacing) 105 | height: gridView.height 106 | //visible: gridView.count > 0 107 | 108 | property Item itemGrid: gridView 109 | 110 | 111 | 112 | MouseArea { 113 | width: parent.width 114 | height: parent.height 115 | onClicked: root.toggle() 116 | } 117 | 118 | ItemGridView { 119 | id: gridView 120 | 121 | anchors { 122 | top: parent.top 123 | } 124 | 125 | width: parent.width 126 | height: Math.ceil(count / plasmoid.configuration.numberColumns) * root.cellSize 127 | cellWidth: root.cellSize 128 | cellHeight: root.cellSize 129 | iconSize: root.iconSize 130 | //<> verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff 131 | 132 | model: repeater.model.modelForRow(index) 133 | 134 | onFocusChanged: { 135 | if (focus) { 136 | itemMultiGrid.focus = true; 137 | } 138 | } 139 | 140 | onCountChanged: { 141 | if (itemMultiGrid.grabFocus && index == 0 && count > 0) { 142 | currentIndex = 0; 143 | focus = true; 144 | } 145 | } 146 | 147 | onCurrentItemChanged: { 148 | if (!currentItem) { 149 | return; 150 | } 151 | 152 | if (index == 0 && currentRow() === 0) { 153 | itemMultiGrid.flickableItem.contentY = 0; 154 | return; 155 | } 156 | 157 | var y = currentItem.y; 158 | y = contentItem.mapToItem(itemMultiGrid.flickableItem.contentItem, 0, y).y; 159 | 160 | if (y < itemMultiGrid.flickableItem.contentY) { 161 | itemMultiGrid.flickableItem.contentY = y; 162 | } else { 163 | y += root.cellSize; 164 | y -= itemMultiGrid.flickableItem.contentY; 165 | y -= itemMultiGrid.viewport.height; 166 | 167 | if (y > 0) { 168 | itemMultiGrid.flickableItem.contentY += y; 169 | } 170 | } 171 | } 172 | 173 | onKeyNavLeft: { 174 | itemMultiGrid.keyNavLeft(index); 175 | } 176 | 177 | onKeyNavRight: { 178 | itemMultiGrid.keyNavRight(index); 179 | } 180 | 181 | onKeyNavUp: { 182 | if (index > 0) { 183 | var prevGrid = subGridAt(index - 1); 184 | prevGrid.tryActivate(prevGrid.lastRow(), currentCol()); 185 | } else { 186 | itemMultiGrid.keyNavUp(); 187 | } 188 | } 189 | 190 | onKeyNavDown: { 191 | if (index < repeater.count - 1) { 192 | subGridAt(index + 1).tryActivate(0, currentCol()); 193 | } else { 194 | itemMultiGrid.keyNavDown(); 195 | } 196 | } 197 | } 198 | 199 | // HACK: Steal wheel events from the nested grid view and forward them to 200 | // the ScrollView's internal WheelArea. 201 | Kicker.WheelInterceptor { 202 | anchors.fill: gridView 203 | z: 1 204 | 205 | destination: findWheelArea(itemMultiGrid.flickableItem) 206 | } 207 | } 208 | } 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /package/contents/ui/MenuRepresentation.qml: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2014 by Weng Xuetian 3 | * Copyright (C) 2013-2017 by Eike Hein * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 2 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * GNU General Public License for more details. * 14 | * * 15 | * You should have received a copy of the GNU General Public License * 16 | * along with this program; if not, write to the * 17 | * Free Software Foundation, Inc., * 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * 19 | ***************************************************************************/ 20 | 21 | import QtQuick 2.4 22 | import QtQuick.Layouts 1.1 23 | import org.kde.plasma.plasmoid 2.0 24 | import org.kde.plasma.core 2.0 as PlasmaCore 25 | import org.kde.plasma.components 2.0 as PlasmaComponents 26 | import org.kde.plasma.components 3.0 as PlasmaComponents3 27 | 28 | import org.kde.plasma.extras 2.0 as PlasmaExtras 29 | 30 | import org.kde.plasma.private.kicker 0.1 as Kicker 31 | import org.kde.kcoreaddons 1.0 as KCoreAddons // kuser 32 | import org.kde.plasma.private.shell 2.0 33 | 34 | import org.kde.kwindowsystem 1.0 35 | import QtGraphicalEffects 1.0 36 | import org.kde.kquickcontrolsaddons 2.0 37 | import org.kde.plasma.private.quicklaunch 1.0 38 | import QtQuick.Controls 2.12 39 | 40 | Item{ 41 | 42 | id: main 43 | property int sizeImage: PlasmaCore.Units.iconSizes.large * 2 44 | 45 | onVisibleChanged: { 46 | root.visible = !root.visible 47 | } 48 | 49 | PlasmaCore.Dialog { 50 | id: root 51 | 52 | objectName: "popupWindow" 53 | //flags: Qt.Window 54 | flags: Qt.WindowStaysOnTopHint 55 | location: PlasmaCore.Types.Floating 56 | hideOnWindowDeactivate: true 57 | 58 | property int iconSize: PlasmaCore.Units.iconSizes.large 59 | property int cellSize: iconSize 60 | + PlasmaCore.Units.gridUnit * 2 61 | + (2 * Math.max(highlightItemSvg.margins.top + highlightItemSvg.margins.bottom, 62 | highlightItemSvg.margins.left + highlightItemSvg.margins.right)) 63 | property bool searching: (searchField.text != "") 64 | 65 | property bool showFavorites 66 | 67 | onVisibleChanged: { 68 | 69 | if (visible) { 70 | root.showFavorites = plasmoid.configuration.showFavoritesFirst 71 | var pos = popupPosition(width, height); 72 | x = pos.x; 73 | y = pos.y; 74 | requestActivate(); 75 | reset(); 76 | animation1.start() 77 | 78 | }else{ 79 | rootItem.opacity = 0 80 | } 81 | } 82 | 83 | onHeightChanged: { 84 | var pos = popupPosition(width, height); 85 | x = pos.x; 86 | y = pos.y; 87 | } 88 | 89 | onWidthChanged: { 90 | var pos = popupPosition(width, height); 91 | x = pos.x; 92 | y = pos.y; 93 | } 94 | 95 | function toggle(){ 96 | main.visible = !main.visible 97 | } 98 | 99 | function reset() { 100 | searchField.text = ""; 101 | 102 | if(showFavorites) 103 | globalFavoritesGrid.tryActivate(0,0) 104 | else 105 | mainColumn.visibleGrid.tryActivate(0,0) 106 | 107 | 108 | } 109 | 110 | function popupPosition(width, height) { 111 | var screenAvail = plasmoid.availableScreenRect; 112 | var screenGeom = plasmoid.screenGeometry; 113 | 114 | var screen = Qt.rect(screenAvail.x + screenGeom.x, 115 | screenAvail.y + screenGeom.y, 116 | screenAvail.width, 117 | screenAvail.height); 118 | 119 | 120 | var offset = PlasmaCore.Units.smallSpacing 121 | 122 | // Fall back to bottom-left of screen area when the applet is on the desktop or floating. 123 | var x = offset; 124 | var y = screen.height - height - offset; 125 | var appletTopLeft; 126 | var horizMidPoint; 127 | var vertMidPoint; 128 | 129 | 130 | if (plasmoid.configuration.displayPosition === 1) { 131 | horizMidPoint = screen.x + (screen.width / 2); 132 | vertMidPoint = screen.y + (screen.height / 2); 133 | x = horizMidPoint - width / 2; 134 | y = vertMidPoint - height / 2; 135 | } else if (plasmoid.configuration.displayPosition === 2) { 136 | horizMidPoint = screen.x + (screen.width / 2); 137 | vertMidPoint = screen.y + (screen.height / 2); 138 | x = horizMidPoint - width / 2; 139 | y = screen.y + screen.height - height - offset - panelSvg.margins.top; 140 | } else if (plasmoid.location === PlasmaCore.Types.BottomEdge) { 141 | horizMidPoint = screen.x + (screen.width / 2); 142 | appletTopLeft = parent.mapToGlobal(0, 0); 143 | x = (appletTopLeft.x < horizMidPoint) ? screen.x + offset : (screen.x + screen.width) - width - offset; 144 | y = screen.y + screen.height - height - offset - panelSvg.margins.top; 145 | } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { 146 | horizMidPoint = screen.x + (screen.width / 2); 147 | var appletBottomLeft = parent.mapToGlobal(0, parent.height); 148 | x = (appletBottomLeft.x < horizMidPoint) ? screen.x + offset : (screen.x + screen.width) - width - offset; 149 | y = parent.height + panelSvg.margins.bottom + offset; 150 | y = screen.y + y + (plasmoid.configuration.viewUser ? main.sizeImage*0.5 : 0); 151 | } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { 152 | vertMidPoint = screen.y + (screen.height / 2); 153 | appletTopLeft = parent.mapToGlobal(0, 0); 154 | x = parent.width + panelSvg.margins.right + offset; 155 | y = (appletTopLeft.y < vertMidPoint) ? screen.y + offset : (screen.y + screen.height) - height - offset; 156 | y = screen.y + y + (plasmoid.configuration.viewUser ? main.sizeImage*0.5 : 0); 157 | } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { 158 | vertMidPoint = screen.y + (screen.height / 2); 159 | appletTopLeft = parent.mapToGlobal(0, 0); 160 | x = appletTopLeft.x - panelSvg.margins.left - offset - width; 161 | y = (appletTopLeft.y < vertMidPoint) ? screen.y + offset : (screen.y + screen.height) - height - offset; 162 | y = screen.y + y + (plasmoid.configuration.viewUser ? main.sizeImage*0.5 : 0); 163 | } 164 | return Qt.point(x, y); 165 | } 166 | 167 | FocusScope { 168 | 169 | id: rootItem 170 | Layout.minimumWidth: (root.cellSize * plasmoid.configuration.numberColumns)+ PlasmaCore.Units.largeSpacing 171 | Layout.maximumWidth: (root.cellSize * plasmoid.configuration.numberColumns)+ PlasmaCore.Units.largeSpacing 172 | Layout.minimumHeight: (root.cellSize * plasmoid.configuration.numberRows) + searchField.implicitHeight + (plasmoid.configuration.viewUser ? main.sizeImage*0.5 : PlasmaCore.Units.largeSpacing * 1.5 ) + PlasmaCore.Units.largeSpacing * 6 173 | Layout.maximumHeight: (root.cellSize * plasmoid.configuration.numberRows) + searchField.implicitHeight + (plasmoid.configuration.viewUser ? main.sizeImage*0.5 : PlasmaCore.Units.largeSpacing * 1.5 ) + PlasmaCore.Units.largeSpacing * 6 174 | 175 | 176 | focus: true 177 | opacity: 0 178 | 179 | KCoreAddons.KUser { id: kuser } 180 | Logic { id: logic } 181 | 182 | 183 | OpacityAnimator { id: animation1; target: rootItem; from: 0; to: 1; } 184 | 185 | PlasmaCore.DataSource { 186 | id: pmEngine 187 | engine: "powermanagement" 188 | connectedSources: ["PowerDevil", "Sleep States"] 189 | function performOperation(what) { 190 | var service = serviceForSource("PowerDevil") 191 | var operation = service.operationDescription(what) 192 | service.startOperationCall(operation) 193 | } 194 | } 195 | 196 | PlasmaCore.DataSource { 197 | id: executable 198 | engine: "executable" 199 | connectedSources: [] 200 | onNewData: { 201 | var exitCode = data["exit code"] 202 | var exitStatus = data["exit status"] 203 | var stdout = data["stdout"] 204 | var stderr = data["stderr"] 205 | exited(sourceName, exitCode, exitStatus, stdout, stderr) 206 | disconnectSource(sourceName) 207 | } 208 | function exec(cmd) { 209 | if (cmd) { 210 | connectSource(cmd) 211 | } 212 | } 213 | signal exited(string cmd, int exitCode, int exitStatus, string stdout, string stderr) 214 | } 215 | 216 | PlasmaComponents.Highlight { 217 | id: delegateHighlight 218 | visible: false 219 | z: -1 // otherwise it shows ontop of the icon/label and tints them slightly 220 | } 221 | 222 | PlasmaExtras.Heading { 223 | id: dummyHeading 224 | visible: false 225 | width: 0 226 | level: 5 227 | } 228 | 229 | TextMetrics { 230 | id: headingMetrics 231 | font: dummyHeading.font 232 | } 233 | 234 | ActionMenu { 235 | id: actionMenu 236 | onActionClicked: visualParent.actionTriggered(actionId, actionArgument) 237 | } 238 | 239 | PlasmaCore.FrameSvgItem { 240 | id : headingSvg 241 | width: parent.width + backgroundSvg.margins.right + backgroundSvg.margins.left 242 | height: root.cellSize * plasmoid.configuration.numberRows + PlasmaCore.Units.largeSpacing * 2 + backgroundSvg.margins.bottom - 1 //<>+ paginationBar.height 243 | y: globalFavoritesGrid.y - PlasmaCore.Units.largeSpacing 244 | x: - backgroundSvg.margins.left 245 | imagePath: "widgets/plasmoidheading" 246 | prefix: "footer" 247 | opacity: 0.7 248 | } 249 | 250 | RowLayout{ 251 | id: rowTop 252 | anchors { 253 | left: parent.left 254 | right: parent.right 255 | top: parent.top 256 | margins: PlasmaCore.Units.smallSpacing 257 | topMargin: PlasmaCore.Units.largeSpacing / 2 258 | } 259 | 260 | PlasmaComponents3.ToolButton { 261 | icon.name: "configure" 262 | onClicked: logic.openUrl("file:///usr/share/applications/systemsettings.desktop") 263 | ToolTip.delay: 200 264 | ToolTip.timeout: 1000 265 | ToolTip.visible: hovered 266 | ToolTip.text: i18n("System Preferences") 267 | } 268 | 269 | Item{ 270 | Layout.fillWidth: true 271 | } 272 | 273 | PlasmaComponents3.ToolButton { 274 | icon.name: "user-home" 275 | onClicked: logic.openUrl("file:///usr/share/applications/org.kde.dolphin.desktop") 276 | ToolTip.delay: 200 277 | ToolTip.timeout: 1000 278 | ToolTip.visible: hovered 279 | ToolTip.text: i18n("User Home") 280 | } 281 | 282 | PlasmaComponents3.ToolButton { 283 | icon.name: "system-lock-screen" 284 | onClicked: pmEngine.performOperation("lockScreen") 285 | enabled: pmEngine.data["Sleep States"]["LockScreen"] 286 | ToolTip.delay: 200 287 | ToolTip.timeout: 1000 288 | ToolTip.visible: hovered 289 | ToolTip.text: i18n("Lock Screen") 290 | } 291 | 292 | PlasmaComponents3.ToolButton { 293 | icon.name: "system-shutdown" 294 | onClicked: pmEngine.performOperation("requestShutDown") 295 | ToolTip.delay: 200 296 | ToolTip.timeout: 1000 297 | ToolTip.visible: hovered 298 | ToolTip.text: i18n("Leave ...") 299 | } 300 | } 301 | 302 | PlasmaExtras.Heading { 303 | anchors { 304 | top: rowTop.bottom 305 | topMargin: PlasmaCore.Units.largeSpacing 306 | horizontalCenter: parent.horizontalCenter 307 | } 308 | level: 1 309 | color: theme.textColor 310 | text: i18n("Hi, ")+ kuser.fullName 311 | font.bold: true 312 | visible: plasmoid.configuration.viewUser 313 | } 314 | 315 | RowLayout { 316 | id: rowSearchField 317 | anchors{ 318 | top: plasmoid.configuration.viewUser ? parent.top : rowTop.bottom 319 | topMargin: plasmoid.configuration.viewUser ? PlasmaCore.Units.largeSpacing*3 + sizeImage/2 : PlasmaCore.Units.largeSpacing/2 320 | left: parent.left 321 | right: parent.right 322 | margins: PlasmaCore.Units.smallSpacing 323 | } 324 | 325 | Item{ 326 | Layout.fillWidth: true 327 | } 328 | PlasmaComponents3.TextField { 329 | id: searchField 330 | Layout.fillWidth: true 331 | placeholderText: i18n("Type here to search ...") 332 | leftPadding: PlasmaCore.Units.largeSpacing + PlasmaCore.Units.iconSizes.small 333 | text: "" 334 | //clearButtonShown: true // TODO: kubuntu 20.04 335 | onTextChanged: { 336 | runnerModel.query = text; 337 | } 338 | 339 | Keys.onPressed: { 340 | if (event.key === Qt.Key_Escape) { 341 | event.accepted = true; 342 | if(root.searching){ 343 | searchField.clear() 344 | } else { 345 | root.toggle() 346 | } 347 | } 348 | 349 | if (event.key === Qt.Key_Down || event.key === Qt.Key_Tab || event.key === Qt.Key_Backtab) { 350 | event.accepted = true; 351 | if(root.showFavorites) 352 | globalFavoritesGrid.tryActivate(0,0) 353 | else 354 | mainColumn.visibleGrid.tryActivate(0,0) 355 | } 356 | } 357 | 358 | function backspace() { 359 | if (!root.visible) { 360 | return; 361 | } 362 | focus = true; 363 | text = text.slice(0, -1); 364 | } 365 | 366 | function appendText(newText) { 367 | if (!root.visible) { 368 | return; 369 | } 370 | focus = true; 371 | text = text + newText; 372 | } 373 | PlasmaCore.IconItem { 374 | source: 'search' 375 | anchors { 376 | left: searchField.left 377 | verticalCenter: searchField.verticalCenter 378 | leftMargin: PlasmaCore.Units.smallSpacing * 2 379 | 380 | } 381 | height: PlasmaCore.Units.iconSizes.small 382 | width: height 383 | } 384 | 385 | } 386 | 387 | Item{ 388 | Layout.fillWidth: true 389 | } 390 | 391 | PlasmaComponents3.ToolButton { 392 | id: btnFavorites 393 | icon.name: 'favorites' 394 | flat: !root.showFavorites 395 | onClicked: { 396 | searchField.text = "" 397 | root.showFavorites = true 398 | } 399 | ToolTip.delay: 200 400 | ToolTip.timeout: 1000 401 | ToolTip.visible: hovered 402 | ToolTip.text: i18n("Favorites") 403 | 404 | } 405 | PlasmaComponents3.ToolButton { 406 | icon.name: "view-list-icons" 407 | flat: root.showFavorites 408 | onClicked: { 409 | searchField.text = "" 410 | root.showFavorites = false 411 | //<>allAppsGrid.scrollBar.flickableItem.contentY = 0; 412 | } 413 | ToolTip.delay: 200 414 | ToolTip.timeout: 1000 415 | ToolTip.visible: hovered 416 | ToolTip.text: i18n("All apps") 417 | } 418 | } 419 | 420 | // 421 | // 422 | // 423 | // 424 | // 425 | 426 | ItemGridView { 427 | id: globalFavoritesGrid 428 | visible: (plasmoid.configuration.showFavoritesFirst || root.showFavorites ) && !root.searching && root.showFavorites 429 | anchors { 430 | top: rowSearchField.bottom 431 | topMargin: PlasmaCore.Units.largeSpacing * 2 432 | left: parent.left 433 | right: parent.right 434 | } 435 | 436 | width: root.cellSize * plasmoid.configuration.numberColumns + PlasmaCore.Units.largeSpacing 437 | height: root.cellSize * plasmoid.configuration.numberRows 438 | focus: true 439 | cellWidth: root.cellSize 440 | cellHeight: root.cellSize 441 | iconSize: root.iconSize 442 | dragEnabled: true 443 | dropEnabled: true 444 | usesPlasmaTheme: true 445 | 446 | onKeyNavUp: searchField.focus = true 447 | Keys.onPressed: { 448 | if(event.modifiers & Qt.ControlModifier ||event.modifiers & Qt.ShiftModifier){ 449 | searchField.focus = true; 450 | return 451 | } 452 | if (event.key === Qt.Key_Tab) { 453 | event.accepted = true; 454 | searchField.focus = true 455 | } 456 | } 457 | } 458 | 459 | // 460 | // 461 | // 462 | // 463 | // 464 | 465 | Item{ 466 | id: mainGrids 467 | visible: (!plasmoid.configuration.showFavoritesFirst && !root.showFavorites ) || root.searching || !root.showFavorites //TODO 468 | 469 | anchors { 470 | top: rowSearchField.bottom 471 | topMargin: PlasmaCore.Units.largeSpacing * 2 472 | left: parent.left 473 | right: parent.right 474 | 475 | } 476 | width: root.cellSize * plasmoid.configuration.numberColumns + PlasmaCore.Units.largeSpacing 477 | height: root.cellSize * plasmoid.configuration.numberRows 478 | 479 | Item { 480 | id: mainColumn 481 | width: root.cellSize * plasmoid.configuration.numberColumns + PlasmaCore.Units.largeSpacing 482 | height: root.cellSize * plasmoid.configuration.numberRows 483 | 484 | property Item visibleGrid: allAppsGrid 485 | 486 | function tryActivate(row, col) { 487 | if (visibleGrid) { 488 | visibleGrid.tryActivate(row, col); 489 | } 490 | } 491 | 492 | ItemGridView { 493 | id: allAppsGrid 494 | 495 | width: root.cellSize * plasmoid.configuration.numberColumns + PlasmaCore.Units.largeSpacing 496 | height: root.cellSize * plasmoid.configuration.numberRows 497 | 498 | cellWidth: root.cellSize 499 | cellHeight: root.cellSize 500 | iconSize: root.iconSize 501 | enabled: (opacity == 1) ? 1 : 0 502 | dropEnabled: false 503 | dragEnabled: false 504 | opacity: root.searching ? 0 : 1 505 | 506 | onOpacityChanged: { 507 | if (opacity == 1) { 508 | //allAppsGrid.scrollBar.flickableItem.contentY = 0; 509 | mainColumn.visibleGrid = allAppsGrid; 510 | } 511 | } 512 | onKeyNavUp: searchField.focus = true 513 | } 514 | 515 | ItemMultiGridView { 516 | id: runnerGrid 517 | width: root.cellSize * plasmoid.configuration.numberColumns + PlasmaCore.Units.largeSpacing 518 | height: root.cellSize * plasmoid.configuration.numberRows 519 | z: (opacity == 1.0) ? 1 : 0 520 | aCellWidth: parent.width - PlasmaCore.Units.largeSpacing 521 | aCellHeight: root.cellSize 522 | enabled: (opacity == 1.0) ? 1 : 0 523 | model: runnerModel 524 | grabFocus: true 525 | opacity: root.searching ? 1.0 : 0.0 526 | onOpacityChanged: { 527 | if (opacity == 1.0) { 528 | mainColumn.visibleGrid = runnerGrid; 529 | } 530 | } 531 | onKeyNavUp: searchField.focus = true 532 | } 533 | 534 | Keys.onPressed: { 535 | if(event.modifiers & Qt.ControlModifier ||event.modifiers & Qt.ShiftModifier){ 536 | searchField.focus = true; 537 | return 538 | } 539 | if (event.key === Qt.Key_Tab) { 540 | event.accepted = true; 541 | searchField.focus = true 542 | } else if (event.key === Qt.Key_Backspace) { 543 | event.accepted = true; 544 | if(root.searching) 545 | searchField.backspace(); 546 | else 547 | searchField.focus = true 548 | } else if (event.key === Qt.Key_Escape) { 549 | event.accepted = true; 550 | if(root.searching){ 551 | searchField.clear() 552 | } else { 553 | root.toggle() 554 | } 555 | } else if (event.text !== "") { 556 | event.accepted = true; 557 | searchField.appendText(event.text); 558 | } 559 | } 560 | } 561 | } 562 | 563 | 564 | 565 | 566 | Keys.onPressed: { 567 | if(event.modifiers & Qt.ControlModifier ||event.modifiers & Qt.ShiftModifier){ 568 | searchField.focus = true; 569 | return 570 | } 571 | if (event.key === Qt.Key_Escape) { 572 | event.accepted = true; 573 | if (root.searching) { 574 | reset(); 575 | } else { 576 | root.visible = false; 577 | } 578 | return; 579 | } 580 | 581 | if (searchField.focus) { 582 | return; 583 | } 584 | 585 | if (event.key === Qt.Key_Backspace) { 586 | event.accepted = true; 587 | searchField.backspace(); 588 | } else if (event.text !== "") { 589 | event.accepted = true; 590 | searchField.appendText(event.text); 591 | } 592 | } 593 | 594 | } 595 | 596 | function setModels(){ 597 | globalFavoritesGrid.model = globalFavorites 598 | allAppsGrid.model = rootModel.modelForRow(0); 599 | } 600 | 601 | Component.onCompleted: { 602 | rootModel.refreshed.connect(setModels) 603 | reset(); 604 | rootModel.refresh(); 605 | } 606 | } 607 | 608 | 609 | 610 | PlasmaCore.Dialog { 611 | id: dialog 612 | 613 | width: main.sizeImage 614 | height: width 615 | 616 | visible: root.visible 617 | 618 | y: root.y - sizeImage/2 619 | x: root.x + root.width/2 - sizeImage/2 620 | 621 | objectName: "popupWindowIcon" 622 | //flags: Qt.WindowStaysOnTopHint 623 | type: "Notification" 624 | location: PlasmaCore.Types.Floating 625 | 626 | hideOnWindowDeactivate: false 627 | backgroundHints: PlasmaCore.Dialog.NoBackground 628 | 629 | mainItem: Rectangle{ 630 | width: main.sizeImage 631 | height: width 632 | color: 'transparent' 633 | 634 | Image { 635 | id: iconUser 636 | //anchors.centerIn: parent 637 | source: kuser.faceIconUrl.toString() || "user-identity" 638 | cache: false 639 | visible: source !== "" && plasmoid.configuration.viewUser 640 | sourceSize.width: main.sizeImage 641 | sourceSize.height: main.sizeImage 642 | 643 | fillMode: Image.PreserveAspectFit 644 | // Crop the avatar to fit in a circle, like the lock and login screens 645 | // but don't on software rendering where this won't render 646 | layer.enabled:true // iconUser.GraphicsInfo.api !== GraphicsInfo.Software 647 | layer.effect: OpacityMask { 648 | // this Rectangle is a circle due to radius size 649 | maskSource: Rectangle { 650 | width: main.sizeImage 651 | height: width 652 | radius: height / 2 653 | visible: false 654 | } 655 | } 656 | state: "hide" 657 | states: [ 658 | State { 659 | name: "show" 660 | when: dialog.visible 661 | PropertyChanges { target: iconUser; y: 0; opacity: 1; } 662 | }, 663 | State { 664 | name: "hide" 665 | when: !dialog.visible 666 | PropertyChanges { target: iconUser; y: sizeImage/2 ; opacity: 0; } 667 | } 668 | ] 669 | transitions: Transition { 670 | PropertyAnimation { properties: "opacity,y"; easing.type: Easing.InOutQuad; } 671 | } 672 | MouseArea { 673 | anchors.fill: parent 674 | acceptedButtons: Qt.LeftButton 675 | onClicked: KCMShell.openSystemSettings("kcm_users") 676 | visible: KCMShell.authorize("user_manager.desktop").length > 0 677 | } 678 | } 679 | } 680 | } 681 | } 682 | -------------------------------------------------------------------------------- /package/contents/ui/main.qml: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2014-2015 by Eike Hein * 3 | * * 4 | * This program is free software; you can redistribute it and/or modify * 5 | * it under the terms of the GNU General Public License as published by * 6 | * the Free Software Foundation; either version 2 of the License, or * 7 | * (at your option) any later version. * 8 | * * 9 | * This program is distributed in the hope that it will be useful, * 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 12 | * GNU General Public License for more details. * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * 18 | ***************************************************************************/ 19 | 20 | import QtQuick 2.0 21 | import QtQuick.Layouts 1.1 22 | import org.kde.plasma.plasmoid 2.0 23 | 24 | import org.kde.plasma.core 2.0 as PlasmaCore 25 | import org.kde.plasma.components 2.0 as PlasmaComponents 26 | 27 | import org.kde.plasma.private.kicker 0.1 as Kicker 28 | 29 | Item { 30 | id: kicker 31 | 32 | anchors.fill: parent 33 | 34 | signal reset 35 | 36 | property bool isDash: false 37 | 38 | Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation 39 | 40 | Plasmoid.compactRepresentation: null 41 | Plasmoid.fullRepresentation: compactRepresentation 42 | 43 | property Item dragSource: null 44 | 45 | property QtObject globalFavorites: rootModel.favoritesModel 46 | property QtObject systemFavorites: rootModel.systemFavoritesModel 47 | 48 | function action_menuedit() { 49 | processRunner.runMenuEditor(); 50 | } 51 | 52 | Component { 53 | id: compactRepresentation 54 | CompactRepresentation {} 55 | } 56 | 57 | Component { 58 | id: menuRepresentation 59 | MenuRepresentation {} 60 | } 61 | 62 | readonly property Kicker.RootModel rootModel: Kicker.RootModel { 63 | id: rootModel 64 | 65 | autoPopulate: false 66 | 67 | appNameFormat: plasmoid.configuration.appNameFormat 68 | flat: true 69 | sorted: true 70 | showSeparators: false 71 | appletInterface: plasmoid 72 | showAllApps: true 73 | showRecentApps: false 74 | showRecentDocs: false 75 | showRecentContacts: false 76 | showPowerSession: false 77 | 78 | Component.onCompleted: { 79 | 80 | favoritesModel.initForClient("org.kde.plasma.kickoff.favorites.instance-" + plasmoid.id) 81 | 82 | if (!plasmoid.configuration.favoritesPortedToKAstats) { 83 | if (favoritesModel.count < 1) { 84 | favoritesModel.portOldFavorites(plasmoid.configuration.favorites); 85 | } 86 | plasmoid.configuration.favoritesPortedToKAstats = true; 87 | } 88 | } 89 | } 90 | 91 | Connections { 92 | target: globalFavorites 93 | 94 | function onFavoritesChanged () { 95 | plasmoid.configuration.favoriteApps = target.favorites; 96 | } 97 | } 98 | 99 | Connections { 100 | target: systemFavorites 101 | 102 | function onFavoritesChanged() { 103 | plasmoid.configuration.favoriteSystemActions = target.favorites; 104 | } 105 | } 106 | 107 | Connections { 108 | target: plasmoid.configuration 109 | 110 | function onFavoriteAppsChanged () { 111 | globalFavorites.favorites = plasmoid.configuration.favoriteApps; 112 | } 113 | 114 | function onFavoriteSystemActionsChanged () { 115 | systemFavorites.favorites = plasmoid.configuration.favoriteSystemActions; 116 | } 117 | 118 | function onHiddenApplicationsChanged(){ 119 | rootModel.refresh(); // Force refresh on hidden 120 | } 121 | } 122 | 123 | Kicker.RunnerModel { 124 | id: runnerModel 125 | 126 | appletInterface: plasmoid 127 | favoritesModel: globalFavorites 128 | deleteWhenEmpty: false 129 | mergeResults: true 130 | } 131 | 132 | Kicker.DragHelper { 133 | id: dragHelper 134 | } 135 | 136 | Kicker.ProcessRunner { 137 | id: processRunner; 138 | } 139 | 140 | PlasmaCore.FrameSvgItem { 141 | id : highlightItemSvg 142 | 143 | visible: false 144 | 145 | imagePath: "widgets/viewitem" 146 | prefix: "hover" 147 | } 148 | 149 | PlasmaCore.FrameSvgItem { 150 | id : panelSvg 151 | 152 | visible: false 153 | 154 | imagePath: "widgets/panel-background" 155 | } 156 | 157 | PlasmaCore.FrameSvgItem { 158 | id : scrollbarSvg 159 | 160 | visible: false 161 | 162 | imagePath: "widgets/scrollbar" 163 | } 164 | 165 | PlasmaCore.FrameSvgItem { 166 | id : backgroundSvg 167 | 168 | visible: false 169 | 170 | imagePath: "dialogs/background" 171 | } 172 | 173 | 174 | PlasmaComponents.Label { 175 | id: toolTipDelegate 176 | 177 | width: contentWidth 178 | height: contentHeight 179 | 180 | property Item toolTip 181 | 182 | text: (toolTip != null) ? toolTip.text : "" 183 | } 184 | 185 | function resetDragSource() { 186 | dragSource = null; 187 | } 188 | 189 | Component.onCompleted: { 190 | plasmoid.setAction("menuedit", i18n("Edit Applications...")); 191 | 192 | //rootModel.refreshed.connect(reset); 193 | //dragHelper.dropped.connect(resetDragSource); 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /package/metadata.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Ditto Menu 3 | Comment=A configurable launcher menu 4 | 5 | Type=Service 6 | Icon=start-here-kde 7 | X-KDE-ServiceTypes=Plasma/Applet 8 | 9 | X-Plasma-API=declarativeappletscript 10 | X-Plasma-MainScript=ui/main.qml 11 | X-Plasma-Provides=org.kde.plasma.launchermenu 12 | 13 | X-KDE-PluginInfo-Author=adhe 14 | X-KDE-PluginInfo-Email=adhemarks[at]gmail.com 15 | X-KDE-PluginInfo-Name=org.kde.plasma.dittomenu 16 | X-KDE-PluginInfo-Version=0.30 17 | X-KDE-PluginInfo-Category=Application Launchers 18 | X-KDE-PluginInfo-Depends= 19 | X-KDE-PluginInfo-License=GPL v2+ 20 | X-KDE-PluginInfo-EnabledByDefault=true 21 | X-KDE-PluginInfo-Website=https://store.kde.org/p/1312669/ 22 | 23 | Name[ko]=Ditto 메뉴 24 | Name[nl]=Ditto-menu 25 | Name[pt_BR]=Ditto Menu 26 | Name[ru]=Ditto Menu 27 | Name[tr]=Ditto Menu 28 | Comment[ko]=프로그램 실행기 29 | Comment[nl]=Een instelbare programmastarter 30 | Comment[pl]=Konfigurowalne menu uruchamiania programów 31 | Comment[pt_BR]=Configuração do Menu Iniciar 32 | Comment[ru]=Настраиваемое меню приложений 33 | Comment[tr]=Yapılandırılabilir bir başlatıcı menüsü 34 | -------------------------------------------------------------------------------- /package/translate/ReadMe.md: -------------------------------------------------------------------------------- 1 | > Version 7 of Zren's i18n scripts. [link](https://github.com/Zren/plasma-applet-tiledmenu) 2 | 3 | With KDE Frameworks v5.37 and above, translations are bundled with the `*.plasmoid` file downloaded from the store. 4 | 5 | ## Install Translations 6 | 7 | Go to `~/.local/share/plasma/plasmoids/org.kde.plasma.dittomenu/translate/` and run `sh ./build --restartplasma`. 8 | 9 | ## New Translations 10 | 11 | 1. Fill out [`template.pot`](template.pot) with your translations then open a [new issue](https://github.com/Zren/plasma-applet-tiledmenu/issues/new), name the file `spanish.txt`, attach the txt file to the issue (drag and drop). 12 | 13 | Or if you know how to make a pull request 14 | 15 | 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 ""`. 16 | 17 | ## Scripts 18 | 19 | * `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. 20 | * `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. 21 | * `sh ./plasmoidlocaletest` will run `./build` then `plasmoidviewer` (part of `plasma-sdk`). 22 | 23 | ## Links 24 | 25 | * https://zren.github.io/kde/docs/widget/#translations-i18n 26 | * https://techbase.kde.org/Development/Tutorials/Localization/i18n_Build_Systems 27 | * https://api.kde.org/frameworks/ki18n/html/prg_guide.html 28 | 29 | ## Examples 30 | 31 | * https://l10n.kde.org/stats/gui/trunk-kf5/team/fr/plasma-desktop/ 32 | * https://github.com/psifidotos/nowdock-plasmoid/tree/master/po 33 | * https://github.com/kotelnik/plasma-applet-redshift-control/tree/master/translations 34 | 35 | ## Status 36 | | Locale | Lines | % Done| 37 | |----------|---------|-------| 38 | | Template | 30 | | 39 | | ko | 27/30 | 90% | 40 | | nl | 20/30 | 66% | 41 | | pl | 22/30 | 73% | 42 | | pt_BR | 30/30 | 100% | 43 | | ru | 30/30 | 100% | 44 | | tr | 23/30 | 76% | 45 | -------------------------------------------------------------------------------- /package/translate/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Version: 6 3 | 4 | # This script will convert the *.po files to *.mo files, rebuilding the package/contents/locale folder. 5 | # Feature discussion: https://phabricator.kde.org/D5209 6 | # Eg: contents/locale/fr_CA/LC_MESSAGES/plasma_applet_org.kde.plasma.eventcalendar.mo 7 | 8 | DIR=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd` 9 | plasmoidName=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Name"` 10 | website=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Website"` 11 | bugAddress="$website" 12 | packageRoot=".." # Root of translatable sources 13 | projectName="plasma_applet_${plasmoidName}" # project name 14 | 15 | #--- 16 | if [ -z "$plasmoidName" ]; then 17 | echo "[build] Error: Couldn't read plasmoidName." 18 | exit 19 | fi 20 | 21 | if [ -z "$(which msgfmt)" ]; then 22 | echo "[build] Error: msgfmt command not found. Need to install gettext" 23 | echo "[build] Running 'sudo apt install gettext'" 24 | sudo apt install gettext 25 | echo "[build] gettext installation should be finished. Going back to installing translations." 26 | fi 27 | 28 | #--- 29 | echo "[build] Compiling messages" 30 | 31 | catalogs=`find . -name '*.po' | sort` 32 | for cat in $catalogs; do 33 | echo "$cat" 34 | catLocale=`basename ${cat%.*}` 35 | msgfmt -o "${catLocale}.mo" "$cat" 36 | 37 | installPath="$DIR/../contents/locale/${catLocale}/LC_MESSAGES/${projectName}.mo" 38 | 39 | echo "[build] Install to ${installPath}" 40 | mkdir -p "$(dirname "$installPath")" 41 | mv "${catLocale}.mo" "${installPath}" 42 | done 43 | 44 | echo "[build] Done building messages" 45 | 46 | if [ "$1" = "--restartplasma" ]; then 47 | echo "[build] Restarting plasmashell" 48 | killall plasmashell 49 | kstart5 plasmashell 50 | echo "[build] Done restarting plasmashell" 51 | else 52 | echo "[build] (re)install the plasmoid and restart plasmashell to test." 53 | fi 54 | -------------------------------------------------------------------------------- /package/translate/fr.po: -------------------------------------------------------------------------------- 1 | # Translation of dittomenu in fr 2 | # Copyright (C) 2023 3 | # This file is distributed under the same license as the dittomenu package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: dittomenu\n" 10 | "Report-Msgid-Bugs-To: https://store.kde.org/p/1312669/\n" 11 | "POT-Creation-Date: 2023-05-01 16:59-0300\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: omano\n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: fr\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: ../metadata.desktop 21 | msgid "Ditto Menu" 22 | msgstr "Ditto Menu" 23 | 24 | #: ../metadata.desktop 25 | msgid "A configurable launcher menu" 26 | msgstr "Un menu de lancement configurable" 27 | 28 | #: ../contents/code/tools.js 29 | msgid "Remove from Favorites" 30 | msgstr "Enlever des Favoris" 31 | 32 | #: ../contents/code/tools.js 33 | msgid "Add to Favorites" 34 | msgstr "Ajouter aux Favoris" 35 | 36 | #: ../contents/code/tools.js 37 | msgid "On All Activities" 38 | msgstr "Sur toutes les Activités" 39 | 40 | #: ../contents/code/tools.js 41 | msgid "On The Current Activity" 42 | msgstr "Sur l'Activité actuelle" 43 | 44 | #: ../contents/code/tools.js 45 | msgid "Show In Favorites" 46 | msgstr "Voir dans les Favoris" 47 | 48 | #: ../contents/config/config.qml 49 | msgid "General" 50 | msgstr "Général" 51 | 52 | #: ../contents/ui/ConfigGeneral.qml 53 | msgid "Icon:" 54 | msgstr "Icône:" 55 | 56 | #: ../contents/ui/ConfigGeneral.qml 57 | msgctxt "@item:inmenu Open icon chooser dialog" 58 | msgid "Choose..." 59 | msgstr "Choisir..." 60 | 61 | #: ../contents/ui/ConfigGeneral.qml 62 | msgctxt "@item:inmenu Reset icon to default" 63 | msgid "Clear Icon" 64 | msgstr "Supprimer l'icône" 65 | 66 | #: ../contents/ui/ConfigGeneral.qml 67 | msgid "Show favorites first" 68 | msgstr "Voir les Favoris en premier" 69 | 70 | #: ../contents/ui/ConfigGeneral.qml 71 | msgid "Menu position" 72 | msgstr "Position du menu" 73 | 74 | #: ../contents/ui/ConfigGeneral.qml 75 | msgid "Default" 76 | msgstr "Défaut" 77 | 78 | #: ../contents/ui/ConfigGeneral.qml 79 | msgid "Center" 80 | msgstr "Centre" 81 | 82 | #: ../contents/ui/ConfigGeneral.qml 83 | msgid "Center bottom" 84 | msgstr "Milieu en bas" 85 | 86 | #: ../contents/ui/ConfigGeneral.qml 87 | msgid "Show labels in two lines" 88 | msgstr "Voir les étiquettes sur deux lignes" 89 | 90 | #: ../contents/ui/ConfigGeneral.qml 91 | msgid "Number of columns" 92 | msgstr "Nombre de colonnes" 93 | 94 | #: ../contents/ui/ConfigGeneral.qml 95 | msgid "Number of rows" 96 | msgstr "Nombre de lignes" 97 | 98 | #: ../contents/ui/ConfigGeneral.qml 99 | msgid "Unhide all hidden applications" 100 | msgstr "Ne plus cacher les applications" 101 | 102 | #: ../contents/ui/ConfigGeneral.qml 103 | msgid "Unhidden!" 104 | msgstr "Plus cachées!" 105 | 106 | #: ../contents/ui/MenuRepresentation.qml 107 | msgid "System Preferences" 108 | msgstr "Préférences Système" 109 | 110 | #: ../contents/ui/MenuRepresentation.qml 111 | msgid "User Home" 112 | msgstr "Dossier Personnel" 113 | 114 | #: ../contents/ui/MenuRepresentation.qml 115 | msgid "Lock Screen" 116 | msgstr "Verrouiller l'écran" 117 | 118 | #: ../contents/ui/MenuRepresentation.qml 119 | msgid "Leave ..." 120 | msgstr "Quitter ..." 121 | 122 | #: ../contents/ui/MenuRepresentation.qml 123 | msgid "Hi, " 124 | msgstr "Salut, " 125 | 126 | #: ../contents/ui/MenuRepresentation.qml 127 | msgid "Type here to search ..." 128 | msgstr "Rechercher ..." 129 | 130 | #: ../contents/ui/MenuRepresentation.qml 131 | msgid "Favorites" 132 | msgstr "Favoris" 133 | 134 | #: ../contents/ui/MenuRepresentation.qml 135 | msgid "All apps" 136 | msgstr "Toutes les applications" 137 | -------------------------------------------------------------------------------- /package/translate/ko.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: \n" 4 | "Report-Msgid-Bugs-To: https://store.kde.org/p/1312669/\n" 5 | "POT-Creation-Date: 2023-05-01 16:59-0300\n" 6 | "PO-Revision-Date: 2021-09-29 09:43+0900\n" 7 | "Last-Translator: \n" 8 | "Language-Team: \n" 9 | "Language: ko\n" 10 | "MIME-Version: 1.0\n" 11 | "Content-Type: text/plain; charset=UTF-8\n" 12 | "Content-Transfer-Encoding: 8bit\n" 13 | "X-Generator: Poedit 3.0\n" 14 | "X-Poedit-Basepath: .\n" 15 | "Plural-Forms: nplurals=1; plural=0;\n" 16 | 17 | #: ../metadata.desktop 18 | msgid "Ditto Menu" 19 | msgstr "Ditto 메뉴" 20 | 21 | #: ../metadata.desktop 22 | msgid "A configurable launcher menu" 23 | msgstr "프로그램 실행기" 24 | 25 | #: ../contents/code/tools.js 26 | msgid "Remove from Favorites" 27 | msgstr "즐겨찾기에서 제거" 28 | 29 | #: ../contents/code/tools.js 30 | msgid "Add to Favorites" 31 | msgstr "즐겨찾기에 추가" 32 | 33 | #: ../contents/code/tools.js 34 | msgid "On All Activities" 35 | msgstr "모든 활동" 36 | 37 | #: ../contents/code/tools.js 38 | msgid "On The Current Activity" 39 | msgstr "현재 활동만" 40 | 41 | #: ../contents/code/tools.js 42 | msgid "Show In Favorites" 43 | msgstr "즐겨찾기에 표시" 44 | 45 | #: ../contents/config/config.qml 46 | msgid "General" 47 | msgstr "일반" 48 | 49 | #: ../contents/ui/ConfigGeneral.qml 50 | msgid "Icon:" 51 | msgstr "아이콘:" 52 | 53 | #: ../contents/ui/ConfigGeneral.qml 54 | msgctxt "@item:inmenu Open icon chooser dialog" 55 | msgid "Choose..." 56 | msgstr "선택..." 57 | 58 | #: ../contents/ui/ConfigGeneral.qml 59 | msgctxt "@item:inmenu Reset icon to default" 60 | msgid "Clear Icon" 61 | msgstr "아이콘 초기화" 62 | 63 | #: ../contents/ui/ConfigGeneral.qml 64 | msgid "Show favorites first" 65 | msgstr "즐겨찾기 먼저 표시" 66 | 67 | #: ../contents/ui/ConfigGeneral.qml 68 | msgid "Menu position" 69 | msgstr "" 70 | 71 | #: ../contents/ui/ConfigGeneral.qml 72 | msgid "Default" 73 | msgstr "기본" 74 | 75 | #: ../contents/ui/ConfigGeneral.qml 76 | msgid "Center" 77 | msgstr "가운데" 78 | 79 | #: ../contents/ui/ConfigGeneral.qml 80 | msgid "Center bottom" 81 | msgstr "가운데 밑" 82 | 83 | #: ../contents/ui/ConfigGeneral.qml 84 | msgid "Show labels in two lines" 85 | msgstr "라벨 두 줄로 표시" 86 | 87 | #: ../contents/ui/ConfigGeneral.qml 88 | msgid "Number of columns" 89 | msgstr "" 90 | 91 | #: ../contents/ui/ConfigGeneral.qml 92 | msgid "Number of rows" 93 | msgstr "" 94 | 95 | #: ../contents/ui/ConfigGeneral.qml 96 | msgid "Unhide all hidden applications" 97 | msgstr "모든 숨겨진 프로그램 복구" 98 | 99 | #: ../contents/ui/ConfigGeneral.qml 100 | msgid "Unhidden!" 101 | msgstr "복구됨!" 102 | 103 | #: ../contents/ui/main.qml 104 | msgid "Edit Applications..." 105 | msgstr "프로그램 편집..." 106 | 107 | #: ../contents/ui/MenuRepresentation.qml 108 | msgid "System Preferences" 109 | msgstr "시스템 설정" 110 | 111 | #: ../contents/ui/MenuRepresentation.qml 112 | msgid "User Home" 113 | msgstr "사용자 홈" 114 | 115 | #: ../contents/ui/MenuRepresentation.qml 116 | msgid "Lock Screen" 117 | msgstr "잠금" 118 | 119 | #: ../contents/ui/MenuRepresentation.qml 120 | msgid "Leave ..." 121 | msgstr "떠나기..." 122 | 123 | #: ../contents/ui/MenuRepresentation.qml 124 | msgid "Hi, " 125 | msgstr "안녕하세요, " 126 | 127 | #: ../contents/ui/MenuRepresentation.qml 128 | msgid "Type here to search ..." 129 | msgstr "검색..." 130 | 131 | #: ../contents/ui/MenuRepresentation.qml 132 | msgid "Favorites" 133 | msgstr "즐겨찾기" 134 | 135 | #: ../contents/ui/MenuRepresentation.qml 136 | msgid "All apps" 137 | msgstr "모든 프로그램" 138 | -------------------------------------------------------------------------------- /package/translate/merge.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Version: 20 3 | 4 | # https://techbase.kde.org/Development/Tutorials/Localization/i18n_Build_Systems 5 | # https://techbase.kde.org/Development/Tutorials/Localization/i18n_Build_Systems/Outside_KDE_repositories 6 | # https://invent.kde.org/sysadmin/l10n-scripty/-/blob/master/extract-messages.sh 7 | 8 | DIR=`cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd` 9 | plasmoidName=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Name"` 10 | widgetName="${plasmoidName##*.}" # Strip namespace 11 | website=`kreadconfig5 --file="$DIR/../metadata.desktop" --group="Desktop Entry" --key="X-KDE-PluginInfo-Website"` 12 | bugAddress="$website" 13 | packageRoot=".." # Root of translatable sources 14 | projectName="plasma_applet_${plasmoidName}" # project name 15 | 16 | #--- 17 | if [ -z "$plasmoidName" ]; then 18 | echo "[merge] Error: Couldn't read plasmoidName." 19 | exit 20 | fi 21 | 22 | if [ -z "$(which xgettext)" ]; then 23 | echo "[merge] Error: xgettext command not found. Need to install gettext" 24 | echo "[merge] Running 'sudo apt install gettext'" 25 | sudo apt install gettext 26 | echo "[merge] gettext installation should be finished. Going back to merging translations." 27 | fi 28 | 29 | #--- 30 | echo "[merge] Extracting messages" 31 | potArgs="--from-code=UTF-8 --width=200 --add-location=file" 32 | 33 | find "${packageRoot}" -name '*.desktop' | sort > "${DIR}/infiles.list" 34 | xgettext \ 35 | ${potArgs} \ 36 | --files-from="${DIR}/infiles.list" \ 37 | --language=Desktop \ 38 | -D "${packageRoot}" \ 39 | -D "${DIR}" \ 40 | -o "template.pot.new" \ 41 | || \ 42 | { echo "[merge] error while calling xgettext. aborting."; exit 1; } 43 | 44 | sed -i 's/"Content-Type: text\/plain; charset=CHARSET\\n"/"Content-Type: text\/plain; charset=UTF-8\\n"/' "template.pot.new" 45 | 46 | # See Ki18n's extract-messages.sh for a full example: 47 | # https://invent.kde.org/sysadmin/l10n-scripty/-/blob/master/extract-messages.sh#L25 48 | # The -kN_ and -kaliasLocale keywords are mentioned in the Outside_KDE_repositories wiki. 49 | # We don't need -kN_ since we don't use intltool-extract but might as well keep it. 50 | # I have no idea what -kaliasLocale is used for. Googling aliasLocale found only listed kde1 code. 51 | # We don't need to parse -ki18nd since that'll extract messages from other domains. 52 | find "${packageRoot}" -name '*.cpp' -o -name '*.h' -o -name '*.c' -o -name '*.qml' -o -name '*.js' | sort > "${DIR}/infiles.list" 53 | xgettext \ 54 | ${potArgs} \ 55 | --files-from="${DIR}/infiles.list" \ 56 | -C -kde \ 57 | -ci18n \ 58 | -ki18n:1 -ki18nc:1c,2 -ki18np:1,2 -ki18ncp:1c,2,3 \ 59 | -kki18n:1 -kki18nc:1c,2 -kki18np:1,2 -kki18ncp:1c,2,3 \ 60 | -kxi18n:1 -kxi18nc:1c,2 -kxi18np:1,2 -kxi18ncp:1c,2,3 \ 61 | -kkxi18n:1 -kkxi18nc:1c,2 -kkxi18np:1,2 -kkxi18ncp:1c,2,3 \ 62 | -kI18N_NOOP:1 -kI18NC_NOOP:1c,2 \ 63 | -kI18N_NOOP2:1c,2 -kI18N_NOOP2_NOSTRIP:1c,2 \ 64 | -ktr2i18n:1 -ktr2xi18n:1 \ 65 | -kN_:1 \ 66 | -kaliasLocale \ 67 | --package-name="${widgetName}" \ 68 | --msgid-bugs-address="${bugAddress}" \ 69 | -D "${packageRoot}" \ 70 | -D "${DIR}" \ 71 | --join-existing \ 72 | -o "template.pot.new" \ 73 | || \ 74 | { echo "[merge] error while calling xgettext. aborting."; exit 1; } 75 | 76 | sed -i 's/# SOME DESCRIPTIVE TITLE./'"# Translation of ${widgetName} in LANGUAGE"'/' "template.pot.new" 77 | sed -i 's/# Copyright (C) YEAR THE PACKAGE'"'"'S COPYRIGHT HOLDER/'"# Copyright (C) $(date +%Y)"'/' "template.pot.new" 78 | 79 | if [ -f "template.pot" ]; then 80 | newPotDate=`grep "POT-Creation-Date:" template.pot.new | sed 's/.\{3\}$//'` 81 | oldPotDate=`grep "POT-Creation-Date:" template.pot | sed 's/.\{3\}$//'` 82 | sed -i 's/'"${newPotDate}"'/'"${oldPotDate}"'/' "template.pot.new" 83 | changes=`diff "template.pot" "template.pot.new"` 84 | if [ ! -z "$changes" ]; then 85 | # There's been changes 86 | sed -i 's/'"${oldPotDate}"'/'"${newPotDate}"'/' "template.pot.new" 87 | mv "template.pot.new" "template.pot" 88 | 89 | addedKeys=`echo "$changes" | grep "> msgid" | cut -c 9- | sort` 90 | removedKeys=`echo "$changes" | grep "< msgid" | cut -c 9- | sort` 91 | echo "" 92 | echo "Added Keys:" 93 | echo "$addedKeys" 94 | echo "" 95 | echo "Removed Keys:" 96 | echo "$removedKeys" 97 | echo "" 98 | 99 | else 100 | # No changes 101 | rm "template.pot.new" 102 | fi 103 | else 104 | # template.pot didn't already exist 105 | mv "template.pot.new" "template.pot" 106 | fi 107 | 108 | potMessageCount=`expr $(grep -Pzo 'msgstr ""\n(\n|$)' "template.pot" | grep -c 'msgstr ""')` 109 | echo "| Locale | Lines | % Done|" > "./Status.md" 110 | echo "|----------|---------|-------|" >> "./Status.md" 111 | entryFormat="| %-8s | %7s | %5s |" 112 | templateLine=`perl -e "printf(\"$entryFormat\", \"Template\", \"${potMessageCount}\", \"\")"` 113 | echo "$templateLine" >> "./Status.md" 114 | 115 | rm "${DIR}/infiles.list" 116 | echo "[merge] Done extracting messages" 117 | 118 | #--- 119 | echo "[merge] Merging messages" 120 | catalogs=`find . -name '*.po' | sort` 121 | for cat in $catalogs; do 122 | echo "[merge] $cat" 123 | catLocale=`basename ${cat%.*}` 124 | 125 | widthArg="" 126 | catUsesGenerator=`grep "X-Generator:" "$cat"` 127 | if [ -z "$catUsesGenerator" ]; then 128 | widthArg="--width=400" 129 | fi 130 | 131 | cp "$cat" "$cat.new" 132 | sed -i 's/"Content-Type: text\/plain; charset=CHARSET\\n"/"Content-Type: text\/plain; charset=UTF-8\\n"/' "$cat.new" 133 | 134 | msgmerge \ 135 | ${widthArg} \ 136 | --add-location=file \ 137 | --no-fuzzy-matching \ 138 | -o "$cat.new" \ 139 | "$cat.new" "${DIR}/template.pot" 140 | 141 | sed -i 's/# SOME DESCRIPTIVE TITLE./'"# Translation of ${widgetName} in ${catLocale}"'/' "$cat.new" 142 | sed -i 's/# Translation of '"${widgetName}"' in LANGUAGE/'"# Translation of ${widgetName} in ${catLocale}"'/' "$cat.new" 143 | sed -i 's/# Copyright (C) YEAR THE PACKAGE'"'"'S COPYRIGHT HOLDER/'"# Copyright (C) $(date +%Y)"'/' "$cat.new" 144 | 145 | poEmptyMessageCount=`expr $(grep -Pzo 'msgstr ""\n(\n|$)' "$cat.new" | grep -c 'msgstr ""')` 146 | poMessagesDoneCount=`expr $potMessageCount - $poEmptyMessageCount` 147 | poCompletion=`perl -e "printf(\"%d\", $poMessagesDoneCount * 100 / $potMessageCount)"` 148 | poLine=`perl -e "printf(\"$entryFormat\", \"$catLocale\", \"${poMessagesDoneCount}/${potMessageCount}\", \"${poCompletion}%\")"` 149 | echo "$poLine" >> "./Status.md" 150 | 151 | # mv "$cat" "$cat.old" 152 | mv "$cat.new" "$cat" 153 | done 154 | echo "[merge] Done merging messages" 155 | 156 | #--- 157 | echo "[merge] Updating .desktop file" 158 | 159 | # Generate LINGUAS for msgfmt 160 | if [ -f "$DIR/LINGUAS" ]; then 161 | rm "$DIR/LINGUAS" 162 | fi 163 | touch "$DIR/LINGUAS" 164 | for cat in $catalogs; do 165 | catLocale=`basename ${cat%.*}` 166 | echo "${catLocale}" >> "$DIR/LINGUAS" 167 | done 168 | 169 | cp -f "$DIR/../metadata.desktop" "$DIR/template.desktop" 170 | sed -i '/^Name\[/ d; /^GenericName\[/ d; /^Comment\[/ d; /^Keywords\[/ d' "$DIR/template.desktop" 171 | 172 | msgfmt \ 173 | --desktop \ 174 | --template="$DIR/template.desktop" \ 175 | -d "$DIR/" \ 176 | -o "$DIR/new.desktop" 177 | 178 | # Delete empty msgid messages that used the po header 179 | if [ ! -z "$(grep '^Name=$' "$DIR/new.desktop")" ]; then 180 | echo "[merge] Name in metadata.desktop is empty!" 181 | sed -i '/^Name\[/ d' "$DIR/new.desktop" 182 | fi 183 | if [ ! -z "$(grep '^GenericName=$' "$DIR/new.desktop")" ]; then 184 | echo "[merge] GenericName in metadata.desktop is empty!" 185 | sed -i '/^GenericName\[/ d' "$DIR/new.desktop" 186 | fi 187 | if [ ! -z "$(grep '^Comment=$' "$DIR/new.desktop")" ]; then 188 | echo "[merge] Comment in metadata.desktop is empty!" 189 | sed -i '/^Comment\[/ d' "$DIR/new.desktop" 190 | fi 191 | if [ ! -z "$(grep '^Keywords=$' "$DIR/new.desktop")" ]; then 192 | echo "[merge] Keywords in metadata.desktop is empty!" 193 | sed -i '/^Keywords\[/ d' "$DIR/new.desktop" 194 | fi 195 | 196 | # Place translations at the bottom of the desktop file. 197 | translatedLines=`cat "$DIR/new.desktop" | grep "]="` 198 | if [ ! -z "${translatedLines}" ]; then 199 | sed -i '/^Name\[/ d; /^GenericName\[/ d; /^Comment\[/ d; /^Keywords\[/ d' "$DIR/new.desktop" 200 | if [ "$(tail -c 2 "$DIR/new.desktop" | wc -l)" != "2" ]; then 201 | # Does not end with 2 empty lines, so add an empty line. 202 | echo "" >> "$DIR/new.desktop" 203 | fi 204 | echo "${translatedLines}" >> "$DIR/new.desktop" 205 | fi 206 | 207 | # Cleanup 208 | mv "$DIR/new.desktop" "$DIR/../metadata.desktop" 209 | rm "$DIR/template.desktop" 210 | rm "$DIR/LINGUAS" 211 | 212 | #--- 213 | # Populate ReadMe.md 214 | echo "[merge] Updating translate/ReadMe.md" 215 | sed -i -E 's`share\/plasma\/plasmoids\/(.+)\/translate`share/plasma/plasmoids/'"${plasmoidName}"'/translate`' ./ReadMe.md 216 | if [[ "$website" == *"github.com"* ]]; then 217 | sed -i -E 's`\[new issue\]\(https:\/\/github\.com\/(.+)\/(.+)\/issues\/new\)`[new issue]('"${website}"'/issues/new)`' ./ReadMe.md 218 | fi 219 | sed -i '/^|/ d' ./ReadMe.md # Remove status table from ReadMe 220 | cat ./Status.md >> ./ReadMe.md 221 | rm ./Status.md 222 | 223 | echo "[merge] Done" 224 | -------------------------------------------------------------------------------- /package/translate/nl.po: -------------------------------------------------------------------------------- 1 | # Translation of dittomenu in nl 2 | # Copyright (C) 2021 3 | # This file is distributed under the same license as the dittomenu package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: dittomenu\n" 9 | "Report-Msgid-Bugs-To: https://store.kde.org/p/1312669/\n" 10 | "POT-Creation-Date: 2023-05-01 16:59-0300\n" 11 | "PO-Revision-Date: 2022-01-01 20:09+0100\n" 12 | "Last-Translator: Heimen Stoffels \n" 13 | "Language-Team: \n" 14 | "Language: nl\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "X-Generator: Poedit 3.0\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 20 | 21 | #: ../metadata.desktop 22 | msgid "Ditto Menu" 23 | msgstr "Ditto-menu" 24 | 25 | #: ../metadata.desktop 26 | msgid "A configurable launcher menu" 27 | msgstr "Een instelbare programmastarter" 28 | 29 | #: ../contents/code/tools.js 30 | msgid "Remove from Favorites" 31 | msgstr "Verwijderen uit favorieten" 32 | 33 | #: ../contents/code/tools.js 34 | msgid "Add to Favorites" 35 | msgstr "Toevoegen aan favorieten" 36 | 37 | #: ../contents/code/tools.js 38 | msgid "On All Activities" 39 | msgstr "Op alle activiteiten" 40 | 41 | #: ../contents/code/tools.js 42 | msgid "On The Current Activity" 43 | msgstr "Op de huidige activiteit" 44 | 45 | #: ../contents/code/tools.js 46 | msgid "Show In Favorites" 47 | msgstr "Toevoegen aan favorieten" 48 | 49 | #: ../contents/config/config.qml 50 | msgid "General" 51 | msgstr "Algemeen" 52 | 53 | #: ../contents/ui/ConfigGeneral.qml 54 | msgid "Icon:" 55 | msgstr "Pictogram:" 56 | 57 | #: ../contents/ui/ConfigGeneral.qml 58 | msgctxt "@item:inmenu Open icon chooser dialog" 59 | msgid "Choose..." 60 | msgstr "Kiezen…" 61 | 62 | #: ../contents/ui/ConfigGeneral.qml 63 | msgctxt "@item:inmenu Reset icon to default" 64 | msgid "Clear Icon" 65 | msgstr "Pictogram verwijderen" 66 | 67 | #: ../contents/ui/ConfigGeneral.qml 68 | msgid "Show favorites first" 69 | msgstr "Favorieten bovenaan tonen" 70 | 71 | #: ../contents/ui/ConfigGeneral.qml 72 | msgid "Menu position" 73 | msgstr "" 74 | 75 | #: ../contents/ui/ConfigGeneral.qml 76 | msgid "Default" 77 | msgstr "Standaard" 78 | 79 | #: ../contents/ui/ConfigGeneral.qml 80 | msgid "Center" 81 | msgstr "Gecentreerd" 82 | 83 | #: ../contents/ui/ConfigGeneral.qml 84 | msgid "Center bottom" 85 | msgstr "Gecentreerd (onderaan)" 86 | 87 | #: ../contents/ui/ConfigGeneral.qml 88 | msgid "Show labels in two lines" 89 | msgstr "Labeltekst verdelen over twee regels" 90 | 91 | #: ../contents/ui/ConfigGeneral.qml 92 | msgid "Number of columns" 93 | msgstr "" 94 | 95 | #: ../contents/ui/ConfigGeneral.qml 96 | msgid "Number of rows" 97 | msgstr "" 98 | 99 | #: ../contents/ui/ConfigGeneral.qml 100 | msgid "Unhide all hidden applications" 101 | msgstr "Alle verborgen programma's zichtbaar maken" 102 | 103 | #: ../contents/ui/ConfigGeneral.qml 104 | msgid "Unhidden!" 105 | msgstr "Alles programma's zijn weer zichtbaar!" 106 | 107 | #: ../contents/ui/main.qml 108 | msgid "Edit Applications..." 109 | msgstr "Programma's bewerken…" 110 | 111 | #: ../contents/ui/MenuRepresentation.qml 112 | msgid "System Preferences" 113 | msgstr "Systeeminstellingen" 114 | 115 | #: ../contents/ui/MenuRepresentation.qml 116 | msgid "User Home" 117 | msgstr "" 118 | 119 | #: ../contents/ui/MenuRepresentation.qml 120 | msgid "Lock Screen" 121 | msgstr "" 122 | 123 | #: ../contents/ui/MenuRepresentation.qml 124 | msgid "Leave ..." 125 | msgstr "" 126 | 127 | #: ../contents/ui/MenuRepresentation.qml 128 | msgid "Hi, " 129 | msgstr "" 130 | 131 | #: ../contents/ui/MenuRepresentation.qml 132 | msgid "Type here to search ..." 133 | msgstr "" 134 | 135 | #: ../contents/ui/MenuRepresentation.qml 136 | msgid "Favorites" 137 | msgstr "" 138 | 139 | #: ../contents/ui/MenuRepresentation.qml 140 | msgid "All apps" 141 | msgstr "" 142 | 143 | #~ msgctxt "@action" 144 | #~ msgid "Lock Screen" 145 | #~ msgstr "Scherm vergrendelen" 146 | 147 | #~ msgid "Behavior" 148 | #~ msgstr "Gedrag" 149 | 150 | #~ msgid "Show applications as:" 151 | #~ msgstr "Programmaweergave:" 152 | 153 | #~ msgid "Name only" 154 | #~ msgstr "Alleen naam" 155 | 156 | #~ msgid "Description only" 157 | #~ msgstr "Alleen beschrijving" 158 | 159 | #~ msgid "Name (Description)" 160 | #~ msgstr "Naam (beschrijving)" 161 | 162 | #~ msgid "Description (Name)" 163 | #~ msgstr "Beschrijving (naam)" 164 | 165 | #~ msgid "Menu position:" 166 | #~ msgstr "Menupositie:" 167 | 168 | #~ msgid "Search" 169 | #~ msgstr "Zoeken" 170 | 171 | #~ msgid "Expand search to bookmarks, files and emails" 172 | #~ msgstr "Ook bladwijzers, bestanden en e-mails doorzoeken" 173 | 174 | #~ msgid "Show user icon" 175 | #~ msgstr "Gebruikersafbeelding tonen" 176 | 177 | #~ msgid "Grid" 178 | #~ msgstr "Rooster" 179 | 180 | #~ msgid "Number of columns in grid" 181 | #~ msgstr "Aantal kolommen op rooster" 182 | 183 | #~ msgid "Number of rows in grid" 184 | #~ msgstr "Aantal rijen op rooster" 185 | 186 | #~ msgid "Search ..." 187 | #~ msgstr "Zoeken…" 188 | -------------------------------------------------------------------------------- /package/translate/pl.po: -------------------------------------------------------------------------------- 1 | # Translation of dittomenu in pl 2 | # Copyright (C) 2022 3 | # This file is distributed under the same license as the dittomenu package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: dittomenu\n" 10 | "Report-Msgid-Bugs-To: https://store.kde.org/p/1312669/\n" 11 | "POT-Creation-Date: 2023-05-01 16:59-0300\n" 12 | "PO-Revision-Date: 2022-04-05 10:40+0100\n" 13 | "Last-Translator: Krzysztof Korab \n" 14 | "Language-Team: \n" 15 | "Language: pl\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: ../metadata.desktop 21 | msgid "Ditto Menu" 22 | msgstr "" 23 | 24 | #: ../metadata.desktop 25 | msgid "A configurable launcher menu" 26 | msgstr "Konfigurowalne menu uruchamiania programów" 27 | 28 | #: ../contents/code/tools.js 29 | msgid "Remove from Favorites" 30 | msgstr "Usuń z ulubionych" 31 | 32 | #: ../contents/code/tools.js 33 | msgid "Add to Favorites" 34 | msgstr "Dodaj do ulubionych" 35 | 36 | #: ../contents/code/tools.js 37 | msgid "On All Activities" 38 | msgstr "Na wszystkich aktywnościach" 39 | 40 | #: ../contents/code/tools.js 41 | msgid "On The Current Activity" 42 | msgstr "Na bieżącej aktywności" 43 | 44 | #: ../contents/code/tools.js 45 | msgid "Show In Favorites" 46 | msgstr "Pokaż w ulubionych" 47 | 48 | #: ../contents/config/config.qml 49 | msgid "General" 50 | msgstr "Ogólne" 51 | 52 | #: ../contents/ui/ConfigGeneral.qml 53 | msgid "Icon:" 54 | msgstr "Ikona:" 55 | 56 | #: ../contents/ui/ConfigGeneral.qml 57 | msgctxt "@item:inmenu Open icon chooser dialog" 58 | msgid "Choose..." 59 | msgstr "Wybierz..." 60 | 61 | #: ../contents/ui/ConfigGeneral.qml 62 | msgctxt "@item:inmenu Reset icon to default" 63 | msgid "Clear Icon" 64 | msgstr "Wyczyść ikonę" 65 | 66 | #: ../contents/ui/ConfigGeneral.qml 67 | msgid "Show favorites first" 68 | msgstr "Najpierw pokaż ulubione" 69 | 70 | #: ../contents/ui/ConfigGeneral.qml 71 | msgid "Menu position" 72 | msgstr "" 73 | 74 | #: ../contents/ui/ConfigGeneral.qml 75 | msgid "Default" 76 | msgstr "Domyślne" 77 | 78 | #: ../contents/ui/ConfigGeneral.qml 79 | msgid "Center" 80 | msgstr "Wyśrodkowane" 81 | 82 | #: ../contents/ui/ConfigGeneral.qml 83 | msgid "Center bottom" 84 | msgstr "Wyśrodkowane, na dole" 85 | 86 | #: ../contents/ui/ConfigGeneral.qml 87 | msgid "Show labels in two lines" 88 | msgstr "Pokaż podpisy w dwóch liniach" 89 | 90 | #: ../contents/ui/ConfigGeneral.qml 91 | msgid "Number of columns" 92 | msgstr "" 93 | 94 | #: ../contents/ui/ConfigGeneral.qml 95 | msgid "Number of rows" 96 | msgstr "" 97 | 98 | #: ../contents/ui/ConfigGeneral.qml 99 | msgid "Unhide all hidden applications" 100 | msgstr "Uwidocznij wszystkie ukryte aplikacje" 101 | 102 | #: ../contents/ui/ConfigGeneral.qml 103 | msgid "Unhidden!" 104 | msgstr "Wszystkie programy są widoczne!" 105 | 106 | #: ../contents/ui/main.qml 107 | msgid "Edit Applications..." 108 | msgstr "Edytuj programy..." 109 | 110 | #: ../contents/ui/MenuRepresentation.qml 111 | msgid "System Preferences" 112 | msgstr "Ustawienia systemowe" 113 | 114 | #: ../contents/ui/MenuRepresentation.qml 115 | msgid "User Home" 116 | msgstr "Katalog domowy" 117 | 118 | #: ../contents/ui/MenuRepresentation.qml 119 | msgid "Lock Screen" 120 | msgstr "" 121 | 122 | #: ../contents/ui/MenuRepresentation.qml 123 | msgid "Leave ..." 124 | msgstr "" 125 | 126 | #: ../contents/ui/MenuRepresentation.qml 127 | msgid "Hi, " 128 | msgstr "Cześć, " 129 | 130 | #: ../contents/ui/MenuRepresentation.qml 131 | msgid "Type here to search ..." 132 | msgstr "Wpisz tutaj, aby wyszukać..." 133 | 134 | #: ../contents/ui/MenuRepresentation.qml 135 | msgid "Favorites" 136 | msgstr "" 137 | 138 | #: ../contents/ui/MenuRepresentation.qml 139 | msgid "All apps" 140 | msgstr "" 141 | 142 | #~ msgctxt "@action" 143 | #~ msgid "Lock Screen" 144 | #~ msgstr "Zablokuj ekran" 145 | 146 | #~ msgid "Behavior" 147 | #~ msgstr "Zachowanie" 148 | 149 | #~ msgid "Show applications as:" 150 | #~ msgstr "Pokazuj programy jako:" 151 | 152 | #~ msgid "Name only" 153 | #~ msgstr "Tylko nazwa" 154 | 155 | #~ msgid "Description only" 156 | #~ msgstr "Tylko opis" 157 | 158 | #~ msgid "Name (Description)" 159 | #~ msgstr "Nazwa (Opis)" 160 | 161 | #~ msgid "Description (Name)" 162 | #~ msgstr "Opis (Nazwa)" 163 | 164 | #~ msgid "Menu position:" 165 | #~ msgstr "Położenie menu:" 166 | 167 | #~ msgid "Search" 168 | #~ msgstr "Szukaj" 169 | 170 | #~ msgid "Expand search to bookmarks, files and emails" 171 | #~ msgstr "Rozszerz wyszukiwanie na zakładki, pliki i pocztę" 172 | 173 | #~ msgid "Show user icon" 174 | #~ msgstr "Pokaż ikonę użytkownika" 175 | 176 | #~ msgid "Grid" 177 | #~ msgstr "Siatka" 178 | 179 | #~ msgid "Number of columns in grid" 180 | #~ msgstr "Liczba kolumn w siatce" 181 | 182 | #~ msgid "Number of rows in grid" 183 | #~ msgstr "Liczba wierszy w siatce" 184 | -------------------------------------------------------------------------------- /package/translate/plasmoidlocaletest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Version 9 3 | # Requires plasmoidviewer v5.13.0 4 | 5 | function checkIfLangInstalled { 6 | if [ -x "$(command -v dpkg)" ]; then 7 | dpkg -l ${1} >/dev/null 2>&1 || ( \ 8 | echo -e "${1} not installed.\nInstalling now before continuing.\n" \ 9 | ; sudo apt install ${1} \ 10 | ) || ( \ 11 | echo -e "\nError trying to install ${1}\nPlease run 'sudo apt install ${1}'\n" \ 12 | ; exit 1 \ 13 | ) 14 | elif [ -x "$(command -v pacman)" ]; then 15 | # TODO: run `locale -a` and check if the locale is enabled. 16 | if false; then 17 | # https://wiki.archlinux.org/index.php/Locale 18 | # Uncomment the locale in /etc/locale.gen 19 | # Then run `locale-gen` 20 | echo -e "\nPlease install this locale in System Settings first.\n" 21 | exit 1 22 | else 23 | echo "" 24 | fi 25 | else 26 | echo -e "\nPackage manager not recognized. If the widget is not translated, please install the package '${1}'\n" 27 | fi 28 | } 29 | 30 | langInput="${1}" 31 | lang="" 32 | languagePack="" 33 | 34 | if [[ "$langInput" =~ ":" ]]; then # String contains a colon so assume it's a locale code. 35 | lang="${langInput}" 36 | IFS=: read -r l1 l2 <<< "${lang}" 37 | languagePack="language-pack-${l2}" 38 | fi 39 | 40 | # https://stackoverflow.com/questions/3191664/list-of-all-locales-and-their-short-codes/28357857#28357857 41 | declare -a langArr=( 42 | "af_ZA:af:Afrikaans (South Africa)" 43 | "ak_GH:ak:Akan (Ghana)" 44 | "am_ET:am:Amharic (Ethiopia)" 45 | "ar_EG:ar:Arabic (Egypt)" 46 | "as_IN:as:Assamese (India)" 47 | "az_AZ:az:Azerbaijani (Azerbaijan)" 48 | "be_BY:be:Belarusian (Belarus)" 49 | "bem_ZM:bem:Bemba (Zambia)" 50 | "bg_BG:bg:Bulgarian (Bulgaria)" 51 | "bo_IN:bo:Tibetan (India)" 52 | "bs_BA:bs:Bosnian (Bosnia and Herzegovina)" 53 | "ca_ES:ca:Catalan (Spain)" 54 | "chr_US:ch:Cherokee (United States)" 55 | "cs_CZ:cs:Czech (Czech Republic)" 56 | "cy_GB:cy:Welsh (United Kingdom)" 57 | "da_DK:da:Danish (Denmark)" 58 | "de_DE:de:German (Germany)" 59 | "el_GR:el:Greek (Greece)" 60 | "es_MX:es:Spanish (Mexico)" 61 | "et_EE:et:Estonian (Estonia)" 62 | "eu_ES:eu:Basque (Spain)" 63 | "fa_IR:fa:Persian (Iran)" 64 | "ff_SN:ff:Fulah (Senegal)" 65 | "fi_FI:fi:Finnish (Finland)" 66 | "fo_FO:fo:Faroese (Faroe Islands)" 67 | "fr_CA:fr:French (Canada)" 68 | "ga_IE:ga:Irish (Ireland)" 69 | "gl_ES:gl:Galician (Spain)" 70 | "gu_IN:gu:Gujarati (India)" 71 | "gv_GB:gv:Manx (United Kingdom)" 72 | "ha_NG:ha:Hausa (Nigeria)" 73 | "he_IL:he:Hebrew (Israel)" 74 | "hi_IN:hi:Hindi (India)" 75 | "hr_HR:hr:Croatian (Croatia)" 76 | "hu_HU:hu:Hungarian (Hungary)" 77 | "hy_AM:hy:Armenian (Armenia)" 78 | "id_ID:id:Indonesian (Indonesia)" 79 | "ig_NG:ig:Igbo (Nigeria)" 80 | "is_IS:is:Icelandic (Iceland)" 81 | "it_IT:it:Italian (Italy)" 82 | "ja_JP:ja:Japanese (Japan)" 83 | "ka_GE:ka:Georgian (Georgia)" 84 | "kk_KZ:kk:Kazakh (Kazakhstan)" 85 | "kl_GL:kl:Kalaallisut (Greenland)" 86 | "km_KH:km:Khmer (Cambodia)" 87 | "kn_IN:kn:Kannada (India)" 88 | "ko_KR:ko:Korean (South Korea)" 89 | "ko_KR:ko:Korean (South Korea)" 90 | "lg_UG:lg:Ganda (Uganda)" 91 | "lt_LT:lt:Lithuanian (Lithuania)" 92 | "lv_LV:lv:Latvian (Latvia)" 93 | "mg_MG:mg:Malagasy (Madagascar)" 94 | "mk_MK:mk:Macedonian (Macedonia)" 95 | "ml_IN:ml:Malayalam (India)" 96 | "mr_IN:mr:Marathi (India)" 97 | "ms_MY:ms:Malay (Malaysia)" 98 | "mt_MT:mt:Maltese (Malta)" 99 | "my_MM:my:Burmese (Myanmar [Burma])" 100 | "nb_NO:nb:Norwegian Bokmål (Norway)" 101 | "ne_NP:ne:Nepali (Nepal)" 102 | "nl_NL:nl:Dutch (Netherlands)" 103 | "nn_NO:nn:Norwegian Nynorsk (Norway)" 104 | "om_ET:om:Oromo (Ethiopia)" 105 | "or_IN:or:Oriya (India)" 106 | "pa_PK:pa:Punjabi (Pakistan)" 107 | "pl_PL:pl:Polish (Poland)" 108 | "ps_AF:ps:Pashto (Afghanistan)" 109 | "pt_BR:pt:Portuguese (Brazil)" 110 | "ro_RO:ro:Romanian (Romania)" 111 | "ru_RU:ru:Russian (Russia)" 112 | "rw_RW:rw:Kinyarwanda (Rwanda)" 113 | "si_LK:si:Sinhala (Sri Lanka)" 114 | "sk_SK:sk:Slovak (Slovakia)" 115 | "sl_SI:sl:Slovenian (Slovenia)" 116 | "so_SO:so:Somali (Somalia)" 117 | "sq_AL:sq:Albanian (Albania)" 118 | "sr_RS:sr:Serbian (Serbia)" 119 | "sv_SE:sv:Swedish (Sweden)" 120 | "sw_KE:sw:Swahili (Kenya)" 121 | "ta_IN:ta:Tamil (India)" 122 | "te_IN:te:Telugu (India)" 123 | "th_TH:th:Thai (Thailand)" 124 | "ti_ER:ti:Tigrinya (Eritrea)" 125 | "to_TO:to:Tonga (Tonga)" 126 | "tr_TR:tr:Turkish (Turkey)" 127 | "uk_UA:uk:Ukrainian (Ukraine)" 128 | "ur_IN:ur:Urdu (India)" 129 | "uz_UZ:uz:Uzbek (Uzbekistan)" 130 | "vi_VN:vi:Vietnamese (Vietnam)" 131 | "yo_NG:yo:Yoruba (Nigeria)" 132 | "yo_NG:yo:Yoruba (Nigeria)" 133 | "yue_HK:yu:Cantonese (Hong Kong)" 134 | "zh_CN:zh:Chinese (China)" 135 | "zu_ZA:zu:Zulu (South Africa)" 136 | ) 137 | 138 | for i in "${langArr[@]}"; do 139 | IFS=: read -r l1 l2 l3 <<< "$i" 140 | if [ "$langInput" == "$l2" ]; then 141 | lang="${l1}:${l2}" 142 | languagePack="language-pack-${l2}" 143 | fi 144 | done 145 | 146 | if [ -z "$lang" ]; then 147 | echo "plasmoidlocaletest doesn't recognize the language '$lang'" 148 | echo "Eg:" 149 | scriptcmd='sh ./plasmoidlocaletest' 150 | for i in "${langArr[@]}"; do 151 | IFS=: read -r l1 l2 l3 <<< "$i" 152 | echo " ${scriptcmd} ${l2} | ${l3}" 153 | done 154 | echo "" 155 | echo "Or use a the full locale code:" 156 | echo " ${scriptcmd} ar_EG:ar" 157 | exit 1 158 | fi 159 | 160 | IFS=: read -r l1 l2 <<< "${lang}" 161 | l1="${l1}.UTF-8" 162 | 163 | # Check if language is installed 164 | if [ ! -z "$languagePack" ]; then 165 | if [ "$lang" == "zh_CN:zh" ]; then languagePack="language-pack-zh-hans" 166 | fi 167 | 168 | checkIfLangInstalled "$languagePack" || exit 1 169 | fi 170 | 171 | 172 | echo "LANGUAGE=\"${lang}\"" 173 | echo "LANG=\"${l1}\"" 174 | 175 | scriptDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 176 | packageDir="${scriptDir}/.." 177 | 178 | # Build local translations for plasmoidviewer 179 | sh "${scriptDir}/build" 180 | 181 | LANGUAGE="${lang}" LANG="${l1}" LC_TIME="${l1}" QML_DISABLE_DISK_CACHE=true plasmoidviewer -a "$packageDir" -l topedge -f horizontal -x 0 -y 0 182 | -------------------------------------------------------------------------------- /package/translate/pt_BR.po: -------------------------------------------------------------------------------- 1 | # Translation of dittomenu in pt_BR 2 | # Copyright (C) 2022 3 | # This file is distributed under the same license as the dittomenu package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: dittomenu\n" 10 | "Report-Msgid-Bugs-To: https://store.kde.org/p/1312669/\n" 11 | "POT-Creation-Date: 2023-05-01 16:59-0300\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: pt_BR\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: ../metadata.desktop 21 | msgid "Ditto Menu" 22 | msgstr "Ditto Menu" 23 | 24 | #: ../metadata.desktop 25 | msgid "A configurable launcher menu" 26 | msgstr "Configuração do Menu Iniciar" 27 | 28 | #: ../contents/code/tools.js 29 | msgid "Remove from Favorites" 30 | msgstr "Remover dos favoritos" 31 | 32 | #: ../contents/code/tools.js 33 | msgid "Add to Favorites" 34 | msgstr "Adicionar aos Favoritos" 35 | 36 | #: ../contents/code/tools.js 37 | msgid "On All Activities" 38 | msgstr "Em todas as atividades" 39 | 40 | #: ../contents/code/tools.js 41 | msgid "On The Current Activity" 42 | msgstr "Na atividade atual" 43 | 44 | #: ../contents/code/tools.js 45 | msgid "Show In Favorites" 46 | msgstr "Exibir nos favoritos" 47 | 48 | #: ../contents/config/config.qml 49 | msgid "General" 50 | msgstr "Geral" 51 | 52 | #: ../contents/ui/ConfigGeneral.qml 53 | msgid "Icon:" 54 | msgstr "Ícone" 55 | 56 | #: ../contents/ui/ConfigGeneral.qml 57 | msgctxt "@item:inmenu Open icon chooser dialog" 58 | msgid "Choose..." 59 | msgstr "Procurar" 60 | 61 | #: ../contents/ui/ConfigGeneral.qml 62 | msgctxt "@item:inmenu Reset icon to default" 63 | msgid "Clear Icon" 64 | msgstr "Resetar Ícone" 65 | 66 | #: ../contents/ui/ConfigGeneral.qml 67 | msgid "Show favorites first" 68 | msgstr "Exbir os Favoritros primeiro" 69 | 70 | #: ../contents/ui/ConfigGeneral.qml 71 | msgid "Menu position" 72 | msgstr "Posição do menu" 73 | 74 | #: ../contents/ui/ConfigGeneral.qml 75 | msgid "Default" 76 | msgstr "Padrão" 77 | 78 | #: ../contents/ui/ConfigGeneral.qml 79 | msgid "Center" 80 | msgstr "Centro" 81 | 82 | #: ../contents/ui/ConfigGeneral.qml 83 | msgid "Center bottom" 84 | msgstr "Centro inferior" 85 | 86 | #: ../contents/ui/ConfigGeneral.qml 87 | msgid "Show labels in two lines" 88 | msgstr "Exibir os nomes em duas linhas" 89 | 90 | #: ../contents/ui/ConfigGeneral.qml 91 | msgid "Number of columns" 92 | msgstr "Numero de colunas" 93 | 94 | #: ../contents/ui/ConfigGeneral.qml 95 | msgid "Number of rows" 96 | msgstr "Numero de filas" 97 | 98 | #: ../contents/ui/ConfigGeneral.qml 99 | msgid "Unhide all hidden applications" 100 | msgstr "Mostrar aplicativos ocultos" 101 | 102 | #: ../contents/ui/ConfigGeneral.qml 103 | msgid "Unhidden!" 104 | msgstr "Reexibido" 105 | 106 | #: ../contents/ui/main.qml 107 | msgid "Edit Applications..." 108 | msgstr "Editar Programa" 109 | 110 | #: ../contents/ui/MenuRepresentation.qml 111 | msgid "System Preferences" 112 | msgstr "Configurações do Sistema" 113 | 114 | #: ../contents/ui/MenuRepresentation.qml 115 | msgid "User Home" 116 | msgstr "Diretório do Usuário" 117 | 118 | #: ../contents/ui/MenuRepresentation.qml 119 | msgid "Lock Screen" 120 | msgstr "Tela de bloqueio" 121 | 122 | #: ../contents/ui/MenuRepresentation.qml 123 | msgid "Leave ..." 124 | msgstr "Sair ..." 125 | 126 | #: ../contents/ui/MenuRepresentation.qml 127 | msgid "Hi, " 128 | msgstr "Olá, " 129 | 130 | #: ../contents/ui/MenuRepresentation.qml 131 | msgid "Type here to search ..." 132 | msgstr "Digite aqui para pesquisar" 133 | 134 | #: ../contents/ui/MenuRepresentation.qml 135 | msgid "Favorites" 136 | msgstr "Favoritos" 137 | 138 | #: ../contents/ui/MenuRepresentation.qml 139 | msgid "All apps" 140 | msgstr "Todos os programas" 141 | -------------------------------------------------------------------------------- /package/translate/ru.po: -------------------------------------------------------------------------------- 1 | # Translation of dittomenu in pl 2 | # Copyright (C) 2022 3 | # This file is distributed under the same license as the dittomenu package. 4 | # FIRST AUTHOR , YEAR.. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: dittomenu\n" 10 | "Report-Msgid-Bugs-To: https://store.kde.org/p/1312669/\n" 11 | "POT-Creation-Date: 2023-05-01 16:59-0300\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: Edward Karate \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: ru\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: ../metadata.desktop 21 | msgid "Ditto Menu" 22 | msgstr "Ditto Menu" 23 | 24 | #: ../metadata.desktop 25 | msgid "A configurable launcher menu" 26 | msgstr "Настраиваемое меню приложений" 27 | 28 | #: ../contents/code/tools.js 29 | msgid "Remove from Favorites" 30 | msgstr "Убрать из избранного" 31 | 32 | #: ../contents/code/tools.js 33 | msgid "Add to Favorites" 34 | msgstr "Добавить в избранное" 35 | 36 | #: ../contents/code/tools.js 37 | msgid "On All Activities" 38 | msgstr "По всем видам деятельности" 39 | 40 | #: ../contents/code/tools.js 41 | msgid "On The Current Activity" 42 | msgstr "О текущей деятельности" 43 | 44 | #: ../contents/code/tools.js 45 | msgid "Show In Favorites" 46 | msgstr "Показать в Избранном" 47 | 48 | #: ../contents/config/config.qml 49 | msgid "General" 50 | msgstr "Общие" 51 | 52 | #: ../contents/ui/ConfigGeneral.qml 53 | msgid "Icon:" 54 | msgstr "Значок" 55 | 56 | #: ../contents/ui/ConfigGeneral.qml 57 | msgctxt "@item:inmenu Open icon chooser dialog" 58 | msgid "Choose..." 59 | msgstr "Выбрать..." 60 | 61 | #: ../contents/ui/ConfigGeneral.qml 62 | msgctxt "@item:inmenu Reset icon to default" 63 | msgid "Clear Icon" 64 | msgstr "Очистить значок" 65 | 66 | #: ../contents/ui/ConfigGeneral.qml 67 | msgid "Show favorites first" 68 | msgstr "Сначала показать избранное" 69 | 70 | #: ../contents/ui/ConfigGeneral.qml 71 | msgid "Menu position" 72 | msgstr "Положение меню" 73 | 74 | #: ../contents/ui/ConfigGeneral.qml 75 | msgid "Default" 76 | msgstr "По умолчанию" 77 | 78 | #: ../contents/ui/ConfigGeneral.qml 79 | msgid "Center" 80 | msgstr "Центр" 81 | 82 | #: ../contents/ui/ConfigGeneral.qml 83 | msgid "Center bottom" 84 | msgstr "Снизу по центру" 85 | 86 | #: ../contents/ui/ConfigGeneral.qml 87 | msgid "Show labels in two lines" 88 | msgstr "Отображать метки в две строки" 89 | 90 | #: ../contents/ui/ConfigGeneral.qml 91 | msgid "Number of columns" 92 | msgstr "Количество колонок" 93 | 94 | #: ../contents/ui/ConfigGeneral.qml 95 | msgid "Number of rows" 96 | msgstr "Количество строк" 97 | 98 | #: ../contents/ui/ConfigGeneral.qml 99 | msgid "Unhide all hidden applications" 100 | msgstr "Показать все скрытые приложения" 101 | 102 | #: ../contents/ui/ConfigGeneral.qml 103 | msgid "Unhidden!" 104 | msgstr "Показаны!" 105 | 106 | #: ../contents/ui/main.qml 107 | msgid "Edit Applications..." 108 | msgstr "Редактировать меню..." 109 | 110 | #: ../contents/ui/MenuRepresentation.qml 111 | msgid "System Preferences" 112 | msgstr "Параметры системы" 113 | 114 | #: ../contents/ui/MenuRepresentation.qml 115 | msgid "User Home" 116 | msgstr "Домашняя папка" 117 | 118 | #: ../contents/ui/MenuRepresentation.qml 119 | msgid "Lock Screen" 120 | msgstr "Заблокировать" 121 | 122 | #: ../contents/ui/MenuRepresentation.qml 123 | msgid "Leave ..." 124 | msgstr "Выход ..." 125 | 126 | #: ../contents/ui/MenuRepresentation.qml 127 | msgid "Hi, " 128 | msgstr "Привет, " 129 | 130 | #: ../contents/ui/MenuRepresentation.qml 131 | msgid "Type here to search ..." 132 | msgstr "Введите текст для поиска..." 133 | 134 | #: ../contents/ui/MenuRepresentation.qml 135 | msgid "Favorites" 136 | msgstr "Избранное" 137 | 138 | #: ../contents/ui/MenuRepresentation.qml 139 | msgid "All apps" 140 | msgstr "Все приложения" 141 | 142 | #~ msgctxt "@action" 143 | #~ msgid "Lock Screen" 144 | #~ msgstr "Заблокировать" 145 | 146 | #~ msgid "Behavior" 147 | #~ msgstr "Поведение" 148 | 149 | #~ msgid "Show applications as:" 150 | #~ msgstr "Показывать приложения в виде:" 151 | 152 | #~ msgid "Name only" 153 | #~ msgstr "Только имя" 154 | 155 | #~ msgid "Description only" 156 | #~ msgstr "Только описание" 157 | 158 | #~ msgid "Name (Description)" 159 | #~ msgstr "Имя (Описание)" 160 | 161 | #~ msgid "Description (Name)" 162 | #~ msgstr "Описание (Имя)" 163 | 164 | #~ msgid "Menu position:" 165 | #~ msgstr "Позиция меню" 166 | 167 | #~ msgid "Search" 168 | #~ msgstr "Поиск" 169 | 170 | #~ msgid "Expand search to bookmarks, files and emails" 171 | #~ msgstr "Расширить поиск по закладкам, файлам и почте" 172 | 173 | #~ msgid "Show user icon" 174 | #~ msgstr "Показать иконку пользователя" 175 | 176 | #~ msgid "Grid" 177 | #~ msgstr "Сетка" 178 | 179 | #~ msgid "Number of columns in grid" 180 | #~ msgstr "Количество колонок в сетке" 181 | 182 | #~ msgid "Number of rows in grid" 183 | #~ msgstr "Количество строк в сетке" 184 | -------------------------------------------------------------------------------- /package/translate/template.pot: -------------------------------------------------------------------------------- 1 | # Translation of dittomenu in LANGUAGE 2 | # Copyright (C) 2023 3 | # This file is distributed under the same license as the dittomenu package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: dittomenu\n" 10 | "Report-Msgid-Bugs-To: https://store.kde.org/p/1312669/\n" 11 | "POT-Creation-Date: 2023-05-01 16:59-0300\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: ../metadata.desktop 21 | msgid "Ditto Menu" 22 | msgstr "" 23 | 24 | #: ../metadata.desktop 25 | msgid "A configurable launcher menu" 26 | msgstr "" 27 | 28 | #: ../contents/code/tools.js 29 | msgid "Remove from Favorites" 30 | msgstr "" 31 | 32 | #: ../contents/code/tools.js 33 | msgid "Add to Favorites" 34 | msgstr "" 35 | 36 | #: ../contents/code/tools.js 37 | msgid "On All Activities" 38 | msgstr "" 39 | 40 | #: ../contents/code/tools.js 41 | msgid "On The Current Activity" 42 | msgstr "" 43 | 44 | #: ../contents/code/tools.js 45 | msgid "Show In Favorites" 46 | msgstr "" 47 | 48 | #: ../contents/config/config.qml 49 | msgid "General" 50 | msgstr "" 51 | 52 | #: ../contents/ui/ConfigGeneral.qml 53 | msgid "Icon:" 54 | msgstr "" 55 | 56 | #: ../contents/ui/ConfigGeneral.qml 57 | msgctxt "@item:inmenu Open icon chooser dialog" 58 | msgid "Choose..." 59 | msgstr "" 60 | 61 | #: ../contents/ui/ConfigGeneral.qml 62 | msgctxt "@item:inmenu Reset icon to default" 63 | msgid "Clear Icon" 64 | msgstr "" 65 | 66 | #: ../contents/ui/ConfigGeneral.qml 67 | msgid "Show favorites first" 68 | msgstr "" 69 | 70 | #: ../contents/ui/ConfigGeneral.qml 71 | msgid "Menu position" 72 | msgstr "" 73 | 74 | #: ../contents/ui/ConfigGeneral.qml 75 | msgid "Default" 76 | msgstr "" 77 | 78 | #: ../contents/ui/ConfigGeneral.qml 79 | msgid "Center" 80 | msgstr "" 81 | 82 | #: ../contents/ui/ConfigGeneral.qml 83 | msgid "Center bottom" 84 | msgstr "" 85 | 86 | #: ../contents/ui/ConfigGeneral.qml 87 | msgid "Show labels in two lines" 88 | msgstr "" 89 | 90 | #: ../contents/ui/ConfigGeneral.qml 91 | msgid "Number of columns" 92 | msgstr "" 93 | 94 | #: ../contents/ui/ConfigGeneral.qml 95 | msgid "Number of rows" 96 | msgstr "" 97 | 98 | #: ../contents/ui/ConfigGeneral.qml 99 | msgid "Unhide all hidden applications" 100 | msgstr "" 101 | 102 | #: ../contents/ui/ConfigGeneral.qml 103 | msgid "Unhidden!" 104 | msgstr "" 105 | 106 | #: ../contents/ui/main.qml 107 | msgid "Edit Applications..." 108 | msgstr "" 109 | 110 | #: ../contents/ui/MenuRepresentation.qml 111 | msgid "System Preferences" 112 | msgstr "" 113 | 114 | #: ../contents/ui/MenuRepresentation.qml 115 | msgid "User Home" 116 | msgstr "" 117 | 118 | #: ../contents/ui/MenuRepresentation.qml 119 | msgid "Lock Screen" 120 | msgstr "" 121 | 122 | #: ../contents/ui/MenuRepresentation.qml 123 | msgid "Leave ..." 124 | msgstr "" 125 | 126 | #: ../contents/ui/MenuRepresentation.qml 127 | msgid "Hi, " 128 | msgstr "" 129 | 130 | #: ../contents/ui/MenuRepresentation.qml 131 | msgid "Type here to search ..." 132 | msgstr "" 133 | 134 | #: ../contents/ui/MenuRepresentation.qml 135 | msgid "Favorites" 136 | msgstr "" 137 | 138 | #: ../contents/ui/MenuRepresentation.qml 139 | msgid "All apps" 140 | msgstr "" 141 | -------------------------------------------------------------------------------- /package/translate/tr.po: -------------------------------------------------------------------------------- 1 | # Translation of dittomenu in tr 2 | # Copyright (C) 2022 3 | # This file is distributed under the same license as the dittomenu package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: dittomenu\n" 10 | "Report-Msgid-Bugs-To: https://store.kde.org/p/1312669/\n" 11 | "POT-Creation-Date: 2023-05-01 16:59-0300\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0;\n" 20 | "X-Language: tr_TR\n" 21 | "X-Source-Language: C\n" 22 | 23 | #: ../metadata.desktop 24 | msgid "Ditto Menu" 25 | msgstr "Ditto Menu" 26 | 27 | #: ../metadata.desktop 28 | msgid "A configurable launcher menu" 29 | msgstr "Yapılandırılabilir bir başlatıcı menüsü" 30 | 31 | #: ../contents/code/tools.js 32 | msgid "Remove from Favorites" 33 | msgstr "Favorilerden Çıkar" 34 | 35 | #: ../contents/code/tools.js 36 | msgid "Add to Favorites" 37 | msgstr "Favorilerden Ekle" 38 | 39 | #: ../contents/code/tools.js 40 | msgid "On All Activities" 41 | msgstr "Tüm Etkinliklerde" 42 | 43 | #: ../contents/code/tools.js 44 | msgid "On The Current Activity" 45 | msgstr "Mevcut Etkinlik Üzerine" 46 | 47 | #: ../contents/code/tools.js 48 | msgid "Show In Favorites" 49 | msgstr "Favorilerde Göster" 50 | 51 | #: ../contents/config/config.qml 52 | msgid "General" 53 | msgstr "Genel" 54 | 55 | #: ../contents/ui/ConfigGeneral.qml 56 | msgid "Icon:" 57 | msgstr "Sİmge:" 58 | 59 | #: ../contents/ui/ConfigGeneral.qml 60 | msgctxt "@item:inmenu Open icon chooser dialog" 61 | msgid "Choose..." 62 | msgstr "Seçmek..." 63 | 64 | #: ../contents/ui/ConfigGeneral.qml 65 | msgctxt "@item:inmenu Reset icon to default" 66 | msgid "Clear Icon" 67 | msgstr "Simgeyi Temizle" 68 | 69 | #: ../contents/ui/ConfigGeneral.qml 70 | msgid "Show favorites first" 71 | msgstr "Önce favorileri göster" 72 | 73 | #: ../contents/ui/ConfigGeneral.qml 74 | msgid "Menu position" 75 | msgstr "" 76 | 77 | #: ../contents/ui/ConfigGeneral.qml 78 | msgid "Default" 79 | msgstr "Varsayılan" 80 | 81 | #: ../contents/ui/ConfigGeneral.qml 82 | msgid "Center" 83 | msgstr "Orta" 84 | 85 | #: ../contents/ui/ConfigGeneral.qml 86 | msgid "Center bottom" 87 | msgstr "Orta alt" 88 | 89 | #: ../contents/ui/ConfigGeneral.qml 90 | msgid "Show labels in two lines" 91 | msgstr "Etiketleri iki satırda göster" 92 | 93 | #: ../contents/ui/ConfigGeneral.qml 94 | msgid "Number of columns" 95 | msgstr "" 96 | 97 | #: ../contents/ui/ConfigGeneral.qml 98 | msgid "Number of rows" 99 | msgstr "" 100 | 101 | #: ../contents/ui/ConfigGeneral.qml 102 | msgid "Unhide all hidden applications" 103 | msgstr "Tüm gizli uygulamaları göster" 104 | 105 | #: ../contents/ui/ConfigGeneral.qml 106 | msgid "Unhidden!" 107 | msgstr "Gizli!" 108 | 109 | #: ../contents/ui/main.qml 110 | msgid "Edit Applications..." 111 | msgstr "Uygulamaları Düzenle..." 112 | 113 | #: ../contents/ui/MenuRepresentation.qml 114 | msgid "System Preferences" 115 | msgstr "Sistem Tercihleri" 116 | 117 | #: ../contents/ui/MenuRepresentation.qml 118 | msgid "User Home" 119 | msgstr "Kullanıcı Ana Sayfası" 120 | 121 | #: ../contents/ui/MenuRepresentation.qml 122 | msgid "Lock Screen" 123 | msgstr "" 124 | 125 | #: ../contents/ui/MenuRepresentation.qml 126 | msgid "Leave ..." 127 | msgstr "" 128 | 129 | #: ../contents/ui/MenuRepresentation.qml 130 | msgid "Hi, " 131 | msgstr "Merhaba, " 132 | 133 | #: ../contents/ui/MenuRepresentation.qml 134 | msgid "Type here to search ..." 135 | msgstr "Aramak için buraya yazınız ..." 136 | 137 | #: ../contents/ui/MenuRepresentation.qml 138 | msgid "Favorites" 139 | msgstr "" 140 | 141 | #: ../contents/ui/MenuRepresentation.qml 142 | msgid "All apps" 143 | msgstr "" 144 | 145 | #~ msgctxt "@action" 146 | #~ msgid "Lock Screen" 147 | #~ msgstr "Kilit Ekranı" 148 | 149 | #~ msgid "Behavior" 150 | #~ msgstr "Davranış" 151 | 152 | #~ msgid "Show applications as:" 153 | #~ msgstr "Uygulamaları şu şekilde göster:" 154 | 155 | #~ msgid "Name only" 156 | #~ msgstr "Sadece isim" 157 | 158 | #~ msgid "Description only" 159 | #~ msgstr "Yalnızca açıklama" 160 | 161 | #~ msgid "Name (Description)" 162 | #~ msgstr "İsim (Açıklama)" 163 | 164 | #~ msgid "Description (Name)" 165 | #~ msgstr "Açıklama (İsim)" 166 | 167 | #~ msgid "Menu position:" 168 | #~ msgstr "Menü konumu:" 169 | 170 | #~ msgid "Search" 171 | #~ msgstr "Ara" 172 | 173 | #~ msgid "Expand search to bookmarks, files and emails" 174 | #~ msgstr "Aramayı yer imlerine, dosyalara ve e-postalara genişletin" 175 | 176 | #~ msgid "Show user icon" 177 | #~ msgstr "Kullanıcı simgesini göster" 178 | 179 | #~ msgid "Grid" 180 | #~ msgstr "Izgara" 181 | 182 | #~ msgid "Number of columns in grid" 183 | #~ msgstr "Izgaradaki sütun sayısı" 184 | 185 | #~ msgid "Number of rows in grid" 186 | #~ msgstr "Izgaradaki satır sayısı" 187 | -------------------------------------------------------------------------------- /preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adhec/dittoMenuKDE/ecb2f46f91102d9f7273abedcf97cf1efd5debf4/preview.jpg --------------------------------------------------------------------------------