Very early KDE 6 release.

This commit is contained in:
wackyideas 2024-08-09 03:20:25 +02:00
parent 7cc4ccabbc
commit 686046d4f7
6272 changed files with 140920 additions and 529657 deletions

Binary file not shown.

View file

@ -0,0 +1,346 @@
NOTE! The GPL below is copyrighted by the Free Software Foundation, but
the instance of code that it refers to (the kde programs) are copyrighted
by the authors who actually wrote it.
---------------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View file

@ -0,0 +1,231 @@
/***************************************************************************
* Copyright (C) 2013 by Aurélien Gâteau <agateau@kde.org> *
* Copyright (C) 2013-2015 by Eike Hein <hein@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
.pragma library
function fillActionMenu(i18n, actionMenu, actionList, favoriteModel, favoriteId) {
// Accessing actionList can be a costly operation, so we don't
// access it until we need the menu.
var actions = createFavoriteActions(i18n, favoriteModel, favoriteId);
if (actions) {
if (actionList && actionList.length > 0) {
var separator = { "type": "separator" };
actionList.unshift(separator);
// actionList = actions.concat(actionList); // this crashes Qt O.o
actionList.unshift.apply(actionList, actions);
} else {
actionList = actions;
}
}
actionMenu.actionList = actionList;
}
function createFavoriteActions(i18n, favoriteModel, favoriteId) {
if (favoriteModel === null || !favoriteModel.enabled || favoriteId == null) {
return null;
}
if ("initForClient" in favoriteModel) {
var activities = favoriteModel.activities.runningActivities;
if (activities.length <= 1) {
var action = {};
if (favoriteModel.isFavorite(favoriteId)) {
action.text = i18n("Remove from Favorites");
action.icon = "list-remove";
action.actionId = "_kicker_favorite_remove";
} else if (favoriteModel.maxFavorites == -1 || favoriteModel.count < favoriteModel.maxFavorites) {
action.text = i18n("Add to Favorites");
action.icon = "bookmark-new";
action.actionId = "_kicker_favorite_add";
} else {
return null;
}
action.actionArgument = { favoriteModel: favoriteModel, favoriteId: favoriteId };
return [action];
} else {
var actions = [];
var linkedActivities = favoriteModel.linkedActivitiesFor(favoriteId);
// Adding the item to link/unlink to all activities
var linkedToAllActivities =
!(linkedActivities.indexOf(":global") === -1);
actions.push({
text : i18n("On All Activities"),
checkable : true,
actionId : linkedToAllActivities ?
"_kicker_favorite_remove_from_activity" :
"_kicker_favorite_set_to_activity",
checked : linkedToAllActivities,
actionArgument : {
favoriteModel: favoriteModel,
favoriteId: favoriteId,
favoriteActivity: ""
}
});
// Adding items for each activity separately
var addActivityItem = function(activityId, activityName) {
var linkedToThisActivity =
!(linkedActivities.indexOf(activityId) === -1);
actions.push({
text : activityName,
checkable : true,
checked : linkedToThisActivity && !linkedToAllActivities,
actionId :
// If we are on all activities, and the user clicks just one
// specific activity, unlink from everything else
linkedToAllActivities ? "_kicker_favorite_set_to_activity" :
// If we are linked to the current activity, just unlink from
// that single one
linkedToThisActivity ? "_kicker_favorite_remove_from_activity" :
// Otherwise, link to this activity, but do not unlink from
// other ones
"_kicker_favorite_add_to_activity",
actionArgument : {
favoriteModel : favoriteModel,
favoriteId : favoriteId,
favoriteActivity : activityId
}
});
};
// Adding the item to link/unlink to the current activity
addActivityItem(favoriteModel.activities.currentActivity, i18n("On The Current Activity"));
actions.push({
type: "separator",
actionId: "_kicker_favorite_separator"
});
// Adding the items for each activity
activities.forEach(function(activityId) {
addActivityItem(activityId, favoriteModel.activityNameForId(activityId));
});
return [{
text : i18n("Show In Favorites"),
icon : "favorite",
subActions : actions
}];
}
} else {
var action = {};
if (favoriteModel.isFavorite(favoriteId)) {
action.text = i18n("Remove from Favorites");
action.icon = "list-remove";
action.actionId = "_kicker_favorite_remove";
} else if (favoriteModel.maxFavorites == -1 || favoriteModel.count < favoriteModel.maxFavorites) {
action.text = i18n("Add to Favorites");
action.icon = "bookmark-new";
action.actionId = "_kicker_favorite_add";
} else {
return null;
}
action.actionArgument = { favoriteModel: favoriteModel, favoriteId: favoriteId };
return [action];
}
}
function triggerAction(plasmoid, model, index, actionId, actionArgument) {
function startsWith(txt, needle) {
return txt.substr(0, needle.length) === needle;
}
if (startsWith(actionId, "_kicker_favorite_")) {
handleFavoriteAction(actionId, actionArgument);
return;
}
var closeRequested = model.trigger(index, actionId, actionArgument);
if (closeRequested) {
plasmoid.expanded = false;
return true;
}
return false;
}
function handleFavoriteAction(actionId, actionArgument) {
var favoriteId = actionArgument.favoriteId;
var favoriteModel = actionArgument.favoriteModel;
console.log(actionId);
if (favoriteModel === null || favoriteId == null) {
return null;
}
if ("initForClient" in favoriteModel) {
if (actionId == "_kicker_favorite_remove") {
console.log("Removing from all activities");
favoriteModel.removeFavoriteFrom(favoriteId, ":any");
} else if (actionId == "_kicker_favorite_add") {
console.log("Adding to global activity");
favoriteModel.addFavoriteTo(favoriteId, ":global");
} else if (actionId == "_kicker_favorite_remove_from_activity") {
console.log("Removing from a specific activity");
favoriteModel.removeFavoriteFrom(favoriteId, actionArgument.favoriteActivity);
} else if (actionId == "_kicker_favorite_add_to_activity") {
console.log("Adding to another activity");
favoriteModel.addFavoriteTo(favoriteId, actionArgument.favoriteActivity);
} else if (actionId == "_kicker_favorite_set_to_activity") {
console.log("Removing the item from the favourites, and re-adding it just to be on a specific activity");
favoriteModel.setFavoriteOn(favoriteId, actionArgument.favoriteActivity);
}
} else {
if (actionId == "_kicker_favorite_remove") {
favoriteModel.removeFavorite(favoriteId);
} else if (actionId == "_kicker_favorite_add") {
favoriteModel.addFavorite(favoriteId);
}
}
}

View file

@ -0,0 +1,35 @@
/***************************************************************************
* Copyright (C) 2014 by Eike Hein <hein@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 2.0
import org.kde.plasma.configuration 2.0
ConfigModel {
ConfigCategory {
name: i18n("General")
icon: "preferences-desktop-plasma-theme"
source: "ConfigGeneral.qml"
}
ConfigCategory {
name: i18n("Side panel")
icon: "menu_new"
source: "ConfigSidepanel.qml"
}
}

View file

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name=""/>
<group name="General">
<entry name="icon" type="String">
<default>start-here-kde</default>
</entry>
<entry name="useCustomButtonImage" type="Bool">
<default>true</default>
</entry>
<entry name="stickOutOrb" type="Bool">
<default>false</default>
</entry>
<entry name="customButtonImage" type="Url">
<default></default>
</entry>
<entry name="customButtonImageHover" type="Url">
<default></default>
</entry>
<entry name="customButtonImageActive" type="Url">
<default></default>
</entry>
<entry name="showFilterList" type="Bool">
<default>true</default>
</entry>
<entry name="appNameFormat" type="Int">
<default>0</default>
</entry>
<entry name="limitDepth" type="Bool">
<default>false</default>
</entry>
<entry name="numberColumns" type="Int">
<default>1</default>
</entry>
<entry name="numberRows" type="Int">
<default>12</default>
</entry>
<entry name="favoriteApps" type="StringList">
<default></default>
</entry>
<entry name="favoriteSystemActions" type="StringList">
<default>logout,lock-screen,reboot,shutdown</default>
</entry>
<entry name="hiddenApplications" type="StringList">
<default></default>
</entry>
<entry name="useExtraRunners" type="Bool">
<default>true</default>
</entry>
<entry name="extraRunners" type="StringList">
<label>The plugin id's of additional KRunner plugins to use. Only used if useExtraRunners is true.</label>
<default>shell,bookmarks,baloosearch,locations</default>
</entry>
<entry name="alignResultsToBottom" type="Bool">
<default>true</default>
</entry>
<entry name="switchCategoriesOnHover" type="Bool">
<label>Whether to switch between menu categories by hovering them.</label>
<default>true</default>
</entry>
<entry name="removeApplicationCommand" type="String">
<default>muon-discover --application</default>
</entry>
<entry name="favoritesPortedToKAstats" type="Bool">
<label>Are the favorites ported to use KActivitiesStats to allow per-activity favorites</label>
<default>false</default>
</entry>
<entry name="showRecentsView" type="Bool">
<default>true</default>
</entry>
<entry name="showHomeSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showDocumentsSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showPicturesSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showMusicSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showVideosSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showDownloadsSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showRootSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showGamesSidepanel" type="Bool">
<default>false</default>
</entry>
<entry name="showRecentItemsSidepanel" type="Bool">
<default>false</default>
</entry>
<entry name="showNetworkSidepanel" type="Bool">
<default>false</default>
</entry>
<entry name="showSettingsSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showDevicesSidepanel" type="Bool">
<default>false</default>
</entry>
<entry name="showDefaultsSidepanel" type="Bool">
<default>false</default>
</entry>
<entry name="showHelpSidepanel" type="Bool">
<default>false</default>
</entry>
</group>
</kcfg>

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 115 KiB

View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
viewBox="0 0 32 32"
id="svg7"
sodipodi:docname="system-lock-screen.svg"
inkscape:version="1.1 (c4e8f9ed74, 2021-05-24)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview9"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
showgrid="false"
inkscape:zoom="20.125"
inkscape:cx="15.975155"
inkscape:cy="15.975155"
inkscape:window-width="1600"
inkscape:window-height="832"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg7" />
<defs
id="defs3">
<style
type="text/css"
id="current-color-scheme">
.ColorScheme-Text {
color:#eff0f1;
}
</style>
</defs>
<path
class="ColorScheme-Text"
d="m 16,8 c -2.216,0 -4,1.784 -4,4 v 4 h -2 v 8 H 22 V 16 H 20 V 12 C 20,9.784 18.216,8 16,8 Z m 0,1 c 1.662,0 3,1.561 3,3.5 V 16 H 13 V 12.5 C 13,10.561 14.338,9 16,9 Z"
fill="currentColor"
id="path5"
sodipodi:nodetypes="ssccccccssssccss" />
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -0,0 +1,107 @@
/*
SPDX-FileCopyrightText: 2013 Aurélien Gâteau <agateau@kde.org>
SPDX-FileCopyrightText: 2014-2015 Eike Hein <hein@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.15
import org.kde.plasma.extras 2.0 as PlasmaExtras
Item {
id: root
property variant actionList
property QtObject menu
property bool opened: menu ? (menu.status !== PlasmaExtras.Menu.Closed) : false
property Item visualParent
signal actionClicked(string actionId, variant actionArgument)
signal closed
function fillMenu(menu, items) {
items.forEach(function (actionItem) {
if (actionItem.subActions) {
// This is a menu
var submenuItem = contextSubmenuItemComponent.createObject(menu, {
"actionItem": actionItem
});
fillMenu(submenuItem.submenu, actionItem.subActions);
} else {
var item = contextMenuItemComponent.createObject(menu, {
"actionItem": actionItem
});
}
});
}
function open(x, y) {
if (!actionList) {
return;
}
if (x && y) {
menu.open(x, y);
} else {
menu.open();
}
}
function refreshMenu() {
if (menu) {
menu.destroy();
}
if (!actionList) {
return;
}
menu = contextMenuComponent.createObject(root);
fillMenu(menu, actionList);
}
onActionListChanged: refreshMenu()
onOpenedChanged: {
if (!opened) {
closed();
}
}
Component {
id: contextMenuComponent
PlasmaExtras.Menu {
visualParent: root.visualParent
}
}
Component {
id: contextSubmenuItemComponent
PlasmaExtras.MenuItem {
id: submenuItem
property variant actionItem
property PlasmaExtras.Menu submenu: PlasmaExtras.Menu {
visualParent: submenuItem.action
}
icon: actionItem.icon ? actionItem.icon : null
text: actionItem.text ? actionItem.text : ""
}
}
Component {
id: contextMenuItemComponent
PlasmaExtras.MenuItem {
property variant actionItem
checkable: actionItem.checkable ? actionItem.checkable : false
checked: actionItem.checked ? actionItem.checked : false
enabled: actionItem.type !== "title" && ("enabled" in actionItem ? actionItem.enabled : true)
icon: actionItem.icon ? actionItem.icon : null
section: actionItem.type === "title"
separator: actionItem.type === "separator"
text: actionItem.text ? actionItem.text : ""
onClicked: {
root.actionClicked(actionItem.actionId, actionItem.actionArgument);
}
}
}
}

View file

@ -0,0 +1,350 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Gregor Taetzner <gregor@freenet.de>
Copyright 2014 Sebastian Kügler <sebas@kde.org>
Copyright (C) 2015-2018 Eike Hein <hein@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import org.kde.plasma.plasmoid
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.components as PlasmaComponents
import org.kde.kirigami as Kirigami
Item {
id: appViewContainer
objectName: "ApplicationsView"
property ListView listView: applicationsView.listView
property alias currentIndex: applicationsView.currentIndex
property alias count: applicationsView.count
function decrementCurrentIndex() {
var tempIndex = applicationsView.currentIndex-1;
if(tempIndex < (crumbModel.count == 0 ? 1 : 0)) {
//applicationsView.currentIndex = applicationsView.count-1;
return;
}
applicationsView.decrementCurrentIndex();
}
function incrementCurrentIndex() {
var tempIndex = applicationsView.currentIndex+1;
if(tempIndex >= applicationsView.count) {
applicationsView.currentIndex = -1;
root.m_showAllButton.focus = true;
return;
}
applicationsView.incrementCurrentIndex();
}
function activateCurrentIndex(start) {
if (!applicationsView.currentItem.modelChildren) {
if (!start) {
return;
}
}
applicationsView.state = "OutgoingLeft";
}
function openContextMenu() {
applicationsView.currentItem.openActionMenu();
}
function deactivateCurrentIndex() {
if (crumbModel.count > 0) { // this is not the case when switching from the "Applications" to the "Favorites" tab using the "Left" key
breadcrumbsElement.children[crumbModel.count-1].clickCrumb();
applicationsView.state = "OutgoingRight";
return true;
}
return false;
}
onFocusChanged: {
if(focus)
applicationsView.currentIndex = crumbModel.count == 0 ? 1 : 0;
else applicationsView.currentIndex = -1;
}
Keys.onPressed: {
if(event.key == Qt.Key_Up) {
decrementCurrentIndex();
} else if(event.key == Qt.Key_Down) {
incrementCurrentIndex();
} else if(event.key == Qt.Key_Return || event.key == Qt.Key_Right) {
activateCurrentIndex(applicationsView.currentIndex);
} else if(event.key == Qt.Key_Menu) {
openContextMenu();
} else if(event.key == Qt.Key_Left || event.key == Qt.Key_Backspace) {
deactivateCurrentIndex();
}
}
KeyNavigation.tab: root.m_showAllButton
function reset() {
applicationsView.model = rootModel;
applicationsView.clearBreadcrumbs();
//root.resetRecents();
}
function refreshed() {
reset();
updatedLabelTimer.running = true;
}
Connections {
target: kicker
function onExpandedChanged() {
if (!plasmoid.expanded) {
reset();
}
}
}
Item {
id: crumbContainer
anchors {
top: parent.top
left: parent.left
right: parent.right
}
height: childrenRect.height
visible: false
opacity: crumbModel.count > 0
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration } }
Flickable {
id: breadcrumbFlickable
anchors {
top: parent.top
left: parent.left
right: parent.right
}
height: breadcrumbsElement.height
boundsBehavior: Flickable.StopAtBounds
contentWidth: breadcrumbsElement.width
pixelAligned: true
//contentX: contentWidth - width
// HACK: Align the content to right for RTL locales
leftMargin: LayoutMirroring.enabled ? Math.max(0, width - contentWidth) : 0
ButtonRow {
id: breadcrumbsElement
exclusive: false
Breadcrumb {
id: rootBreadcrumb
root: true
text: i18n("Back")
depth: 0
}
Repeater {
model: ListModel {
id: crumbModel
// Array of the models
property var models: []
}
Breadcrumb {
root: false
text: model.text
visible: false
}
}
onWidthChanged: {
if (LayoutMirroring.enabled) {
breadcrumbFlickable.contentX = -Math.max(0, breadcrumbsElement.width - breadcrumbFlickable.width)
} else {
breadcrumbFlickable.contentX = Math.max(0, breadcrumbsElement.width - breadcrumbFlickable.width)
}
}
}
}
Rectangle {
id: sepLine
anchors {
top: breadcrumbFlickable.bottom
topMargin: -1
left: breadcrumbFlickable.left
leftMargin: Kirigami.Units.smallSpacing*2
right: breadcrumbFlickable.right
rightMargin: Kirigami.Units.smallSpacing*2
}
height: 1
color: "#d6e5f5"
opacity: 1
z: 6
}
} // crumbContainer
KickoffListView {
id: applicationsView
anchors {
top: (crumbContainer.visible && crumbContainer.opacity) ? crumbContainer.bottom : parent.top
topMargin: Kirigami.Units.smallSpacing/ (crumbContainer.visible ? 2 : 1) + 1
bottom: parent.bottom
rightMargin: -Kirigami.Units.gridUnit
leftMargin: -Kirigami.Units.gridUnit
}
width: parent.width
small: true
property Item activatedItem: null
property var newModel: null
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration } }
focus: true
appView: true
model: rootModel
function moveLeft() {
state = "";
// newModelIndex set by clicked breadcrumb
var oldModel = applicationsView.model;
applicationsView.model = applicationsView.newModel;
var oldModelIndex = model.rowForModel(oldModel);
listView.currentIndex = oldModelIndex;
listView.positionViewAtIndex(oldModelIndex, ListView.Center);
crumbContainer.visible = false;
}
function moveRight() {
state = "";
activatedItem.activate();
applicationsView.listView.positionViewAtBeginning();
crumbContainer.visible = true;
//root.visible = false;
}
function clearBreadcrumbs() {
crumbModel.clear();
crumbModel.models = [];
applicationsView.listView.currentIndex = -1;
}
onReset: appViewContainer.reset()
onAddBreadcrumb: {
crumbModel.append({"text": title, "depth": crumbModel.count+1})
crumbModel.models.push(model);
}
states: [
State {
name: "OutgoingLeft"
PropertyChanges {
target: applicationsView
x: -parent.width
opacity: 0.0
}
},
State {
name: "OutgoingRight"
PropertyChanges {
target: applicationsView
x: parent.width
opacity: 0.0
}
}
]
transitions: [
Transition {
to: "OutgoingLeft"
SequentialAnimation {
// We need to cache the currentItem since the selection can move during animation,
// and we want the item that has been clicked on, not the one that is under the
// mouse once the animation is done
ScriptAction { script: applicationsView.activatedItem = applicationsView.currentItem }
NumberAnimation { properties: "opacity"; easing.type: Easing.InQuad; duration: 100 }
ScriptAction { script: { applicationsView.moveRight(); } }
}
},
Transition {
to: "OutgoingRight"
SequentialAnimation {
NumberAnimation { properties: "opacity"; easing.type: Easing.InQuad; duration: 100 }
ScriptAction { script: applicationsView.moveLeft() }
}
}
]
Component.onCompleted: {
applicationsView.listView.currentIndex = -1;
}
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.BackButton
onClicked: {
deactivateCurrentIndex()
}
}
Timer {
id: updatedLabelTimer
interval: 1500
running: false
repeat: true
onRunningChanged: {
if (running) {
updatedLabel.opacity = 1;
crumbContainer.opacity = 0.3;
applicationsView.scrollArea.opacity = 0.3;
}
}
onTriggered: {
updatedLabel.opacity = 0;
crumbContainer.opacity = 1;
applicationsView.scrollArea.opacity = 1;
running = false;
}
}
PlasmaComponents.Label {
id: updatedLabel
text: i18n("Applications updated.")
opacity: 0
visible: opacity != 0
anchors.centerIn: parent
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration } }
}
Component.onCompleted: {
rootModel.cleared.connect(refreshed);
}
} // appViewContainer

View file

@ -0,0 +1,96 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
//import QtQuick.Controls.Styles.Plasma as Styles
Item {
id: crumbRoot
height: crumb.implicitHeight + Kirigami.Units.smallSpacing * 2
width: crumb.implicitWidth + arrowSvg.width
property string text
property bool root: false
property int depth: model.depth
function clickCrumb() {
heading_ma.clicked(null);
}
PlasmaExtras.Heading {
id: crumb
anchors {
left: arrowSvg.right
top: parent.top
bottom: parent.bottom
topMargin: Kirigami.Units.smallSpacing
leftMargin: Kirigami.Units.smallSpacing
bottomMargin: Kirigami.Units.smallSpacing
}
horizontalAlignment: Text.AlignHCenter
text: crumbRoot.text + ""
color: "#404040"
font.underline: heading_ma.enabled && heading_ma.containsMouse
level: 5
MouseArea {
id: heading_ma
anchors.fill: parent
hoverEnabled: crumbRoot.depth < crumbModel.count
enabled: crumbRoot.depth < crumbModel.count
onClicked: {
// Remove all the breadcrumbs in front of the clicked one
while (crumbModel.count > 0 && crumbRoot.depth < crumbModel.get(crumbModel.count-1).depth) {
crumbModel.remove(crumbModel.count-1)
crumbModel.models.pop()
}
if (crumbRoot.root) {
applicationsView.newModel = rootModel;
} else {
applicationsView.newModel = crumbModel.models[index];
}
applicationsView.state = "OutgoingRight";
}
cursorShape: Qt.PointingHandCursor
z: 99
}
}
KSvg.SvgItem{
id: arrowSvg
anchors.left: parent.left
anchors.leftMargin: Kirigami.Units.smallSpacing*2
anchors.verticalCenter: parent.verticalCenter
height: crumbRoot.height / 2
width: visible ? height : 0
svg: arrowsSvg
elementId: LayoutMirroring.enabled ? "right-arrow" : "left-arrow"
}
} // crumbRoot

View file

@ -0,0 +1,149 @@
/*
SPDX-FileCopyrightText: 2011 Nokia Corporation and /or its subsidiary(-ies) <qt-info@nokia.com>
This file is part of the Qt Components project.
SPDX-License-Identifier: LGPL-2.1-only WITH Qt-LGPL-exception-1.1 OR GPL-3.0-only OR LicenseRef-Qt-Commercial
*/
var self;
var checkHandlers = [];
var visibleButtons = [];
var nonVisibleButtons = [];
var direction;
function create(that, options) {
self = that;
direction = options.direction || Qt.Horizontal;
self.childrenChanged.connect(rebuild);
self.exclusiveChanged.connect(rebuild);
// self.widthChanged.connect(resizeChildren);
build();
}
function isButton(item) {
if (item && item.hasOwnProperty("__position"))
return true;
return false;
}
function hasChecked(item) {
return (item && item.hasOwnProperty("checked"));
}
function destroy() {
self.childrenChanged.disconnect(rebuild);
// self.widthChanged.disconnect(resizeChildren);
cleanup();
}
function build() {
visibleButtons = [];
nonVisibleButtons = [];
for (var i = 0, item; (item = self.children[i]); i++) {
if (!hasChecked(item))
continue;
item.visibleChanged.connect(rebuild); // Not optimal, but hardly a bottleneck in your app
if (!item.visible) {
nonVisibleButtons.push(item);
continue;
}
visibleButtons.push(item);
if (self.exclusive && item.hasOwnProperty("checkable"))
item.checkable = true;
if (self.exclusive) {
checkHandlers.push(checkExclusive(item));
item.checkedChanged.connect(checkHandlers[checkHandlers.length - 1]);
}
if (item.checked) {
checkExclusive(item)()
if (item.checked) self.checkedButton = item
}
}
var nrButtons = visibleButtons.length;
if (nrButtons == 0)
return;
if (self.checkedButton)
self.checkedButton.checked = true;
else if (self.exclusive) {
self.checkedButton = visibleButtons[0];
self.checkedButton.checked = true;
}
if (nrButtons == 1) {
finishButton(visibleButtons[0], "only");
} else {
finishButton(visibleButtons[0], direction == Qt.Horizontal ? "leftmost" : "top");
for (var i = 1; i < nrButtons - 1; i++)
finishButton(visibleButtons[i], direction == Qt.Horizontal ? "h_middle": "v_middle");
finishButton(visibleButtons[nrButtons - 1], direction == Qt.Horizontal ? "rightmost" : "bottom");
}
}
function finishButton(button, position) {
if (isButton(button)) {
button.__position = position;
if (direction == Qt.Vertical) {
button.anchors.left = self.left //mm How to make this not cause binding loops? see QTBUG-17162
button.anchors.right = self.right
}
}
}
function cleanup() {
visibleButtons.forEach(function(item, i) {
if (checkHandlers[i])
item.checkedChanged.disconnect(checkHandlers[i]);
item.visibleChanged.disconnect(rebuild);
});
checkHandlers = [];
nonVisibleButtons.forEach(function(item, i) {
item.visibleChanged.disconnect(rebuild);
});
}
function rebuild() {
if (self == undefined)
return;
cleanup();
build();
}
function resizeChildren() {
if (direction != Qt.Horizontal)
return;
var extraPixels = self.width % visibleButtons;
var buttonSize = (self.width - extraPixels) / visibleButtons;
visibleButtons.forEach(function(item, i) {
if (!item || !item.visible)
return;
item.width = buttonSize + (extraPixels > 0 ? 1 : 0);
if (extraPixels > 0)
extraPixels--;
});
}
function checkExclusive(item) {
var button = item;
return function() {
for (var i = 0, ref; (ref = visibleButtons[i]); i++) {
if (ref.checked == (button === ref))
continue;
// Disconnect the signal to avoid recursive calls
ref.checkedChanged.disconnect(checkHandlers[i]);
ref.checked = !ref.checked;
ref.checkedChanged.connect(checkHandlers[i]);
}
self.checkedButton = button;
}
}

View file

@ -0,0 +1,57 @@
/*
SPDX-FileCopyrightText: 2011 Nokia Corporation and /or its subsidiary(-ies) <qt-info@nokia.com>
This file is part of the Qt Components project.
SPDX-License-Identifier: LGPL-2.1-only WITH Qt-LGPL-exception-1.1 OR GPL-3.0-only OR LicenseRef-Qt-Commercial
*/
import QtQuick 2.1
import org.kde.plasma.core 2.0 as PlasmaCore
import "ButtonGroup.js" as Behavior
/**
* A ButtonRow allows you to group Buttons in a row. It provides a
* selection-behavior as well.
*
* Note: This component does not support the enabled property. If you need to
* disable it you should disable all the buttons inside it.
*
* Example code:
*
* @code
* ButtonRow {
* Button { text: "Left" }
* Button { text: "Right" }
* }
* @endcode
*
* @inherit QtQuick.Row
*/
Row {
id: root
/**
* Specifies the grouping behavior. If enabled, the checked property on
* buttons contained in the group will be exclusive.The default value is true.
*
* Note that a button in an exclusive group will always be checkable
*/
property bool exclusive: true
/**
* Returns the last checked button
*/
property Item checkedButton;
spacing: PlasmaCore.Theme.defaultFont.pointSize
Component.onCompleted: {
Behavior.create(root, {direction: Qt.Horizontal});
}
Component.onDestruction: {
Behavior.destroy();
}
}

View file

@ -0,0 +1,284 @@
/***************************************************************************
* Copyright (C) 2013-2014 by Eike Hein <hein@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 2.0
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.kwindowsystem 1.0
import org.kde.kirigami as Kirigami
Item {
id: root
Layout.minimumHeight: floatingOrbPanel.buttonIconSizes.height;
Layout.maximumHeight: floatingOrbPanel.buttonIconSizes.height;
Layout.minimumWidth: floatingOrbPanel.buttonIconSizes.width;
Layout.maximumWidth: floatingOrbPanel.buttonIconSizes.width;
property bool compositing: false
/*
* The following code gets the ContainmentInterface instance which is used for keeping track of edit mode's state.
* This allows us to hide the StartOrb object so the user can actually highlight and select this plasmoid during edit mode.
*/
//property var containmentInterface: null
property QtObject contextMenu: null
property QtObject dashWindow: null
readonly property bool editMode: Plasmoid.containment.corona.editMode //containmentInterface ? containmentInterface.editMode : false
readonly property bool inPanel: (Plasmoid.location == PlasmaCore.Types.TopEdge || Plasmoid.location == PlasmaCore.Types.RightEdge || Plasmoid.location == PlasmaCore.Types.BottomEdge || Plasmoid.location == PlasmaCore.Types.LeftEdge)
property bool menuShown: dashWindow.visible
property QtObject orb: null
property alias orbTimer: orbTimer
readonly property var screenGeometry: Plasmoid.screenGeometry
// Should the orb be rendered in its own dialog window so that it can stick out of the panel?
readonly property bool stickOutOrb: Plasmoid.configuration.stickOutOrb && inPanel && !editMode
readonly property bool useCustomButtonImage: (Plasmoid.configuration.useCustomButtonImage)
readonly property bool vertical: (Plasmoid.formFactor == PlasmaCore.Types.Vertical)
//property int opacityDuration: 350
/*function createContextMenu(pos) {
contextMenu = Qt.createQmlObject("ContextMenu {}", root);
contextMenu.fillActions();
contextMenu.show();
}*/
// If the url is empty (default value), then use the fallback url. Otherwise, return the url path relative to
// the location of the source code.
function getResolvedUrl(url, fallback) {
if (url.toString() === "") {
return Qt.resolvedUrl(fallback);
}
return url;
}
function positionOrb() {
var pos = kicker.mapToGlobal(floatingOrbPanel.x, floatingOrbPanel.y);
pos.y -= 5;
//if(floatingOrbPanel.buttonIcon.implicitHeight === 54) // Using an orb with extra height around it
//var pos = kicker.mapToGlobal(kicker.x, kicker.y); // Gets the global position of this plasmoid, in screen coordinates.
orb.width = floatingOrbPanel.buttonIcon.implicitWidth// + panelSvg.margins.left;
orb.height = floatingOrbPanel.buttonIcon.implicitHeight;
orb.x = pos.x;
orb.y = pos.y;// + panelSvg.margins.bottom;
// Keep the orb positioned exactly on the bottom if it is rendered out of bounds (beyond the screen geometry)
/*if (orb.y + orb.height > kicker.screenGeometry.height) {
orb.y = kicker.screenGeometry.height - orb.height; //orb.y + orb.height - kicker.screenGeometry.height;
}*/
}
function showMenu() {
dashWindow.visible = !dashWindow.visible;
dashWindow.showingAllPrograms = false;
Plasmoid.setActiveWin(dashWindow);
console.log(floatingOrbPanel.buttonIcon.implicitHeight);
dashWindow.m_searchField.focus = true;
orb.raise();
}
function updateSizeHints() {
return;
if (useCustomButtonImage) {
if (vertical) {
var scaledHeight = Math.floor(parent.width * (floatingOrbPanel.buttonIcon.height / floatingOrbPanel.buttonIcon.width));
root.Layout.minimumHeight = scaledHeight;
root.Layout.maximumHeight = scaledHeight;
root.Layout.minimumWidth = Kirigami.Units.iconSizes.small;
root.Layout.maximumWidth = inPanel ? Kirigami.Units.iconSizes.medium : -1;
} else {
var scaledWidth = Math.floor(parent.height * (floatingOrbPanel.buttonIcon.width / floatingOrbPanel.buttonIcon.height));
root.Layout.minimumWidth = scaledWidth;
root.Layout.maximumWidth = scaledWidth;
root.Layout.minimumHeight = Kirigami.Units.iconSizes.small;
root.Layout.maximumHeight = inPanel ? Kirigami.Units.iconSizes.medium : -1;
}
} else {
root.Layout.minimumWidth = Kirigami.Units.iconSizes.small;
root.Layout.maximumWidth = inPanel ? Kirigami.Units.iconSizes.medium : -1;
root.Layout.minimumHeight = Kirigami.Units.iconSizes.small;
root.Layout.maximumHeight = inPanel ? Kirigami.Units.iconSizes.medium : -1;
}
if (stickOutOrb && orb) {
root.Layout.minimumWidth = orb.width + panelSvg.margins.right * (compositing ? 0 : 1);
root.Layout.maximumWidth = orb.width + panelSvg.margins.right * (compositing ? 0 : 1);
root.Layout.minimumHeight = orb.height;
root.Layout.maximumHeight = orb.height;
}
// This has to be done, or else the orb won't be positioned correctly. ??????????
/*orb.y += 5;
orb.y -= 5; // ??????????????????????????????????????*/
}
//kicker.status: PlasmaCore.Types.PassiveStatus
Plasmoid.status: dashWindow && dashWindow.visible ? PlasmaCore.Types.RequiresAttentionStatus : PlasmaCore.Types.PassiveStatus
//clip: true
Component.onCompleted: {
dashWindow = Qt.createQmlObject("MenuRepresentation {}", kicker);
orb = Qt.createQmlObject("StartOrb {}", kicker);
//Plasmoid.fullRepresentation = dashWindow
Plasmoid.activated.connect(function () {
showMenu();
});
}
onCompositingChanged: {
updateSizeHints();
positionOrb();
/*if (compositing) {
orb.x += panelSvg.margins.left;
}*/
compositingFix.start();
}
onHeightChanged: updateSizeHints()
onParentChanged: {
/*if (parent) {
for (var obj = root, depth = 0; !!obj; obj = obj.parent, depth++) {
if (obj.toString().startsWith('ContainmentInterface')) {
// desktop containment / plasmoidviewer
// Note: This doesn't always work. FolderViewDropArea may not yet have
// ContainmentInterface as a parent when this loop runs.
if (typeof obj['editMode'] === 'boolean') {
root.containmentInterface = obj;
break;
}
} else if (obj.toString().startsWith('DeclarativeDropArea')) {
// panel containment
if (typeof obj['Plasmoid'] !== 'undefined' && obj['Plasmoid'].toString().startsWith('ContainmentInterface')) {
if (typeof obj['Plasmoid']['editMode'] === 'boolean') {
root.containmentInterface = obj.Plasmoid;
break;
}
}
}
}
}*/
}
onStickOutOrbChanged: {
updateSizeHints();
positionOrb();
}
onWidthChanged: updateSizeHints()
/*Connections {
target: Kirigami.Units.iconSizeHints
function onPanelChanged() { updateSizeHints(); }
}*/
Connections {
target: Plasmoid.configuration
function onCustomButtonImageChanged() {
positionOrb();
console.log("AAAA")
}
}
Connections {
function onScreenChanged() {
positionOrb();
}
function onScreenGeometryChanged() {
positionOrb();
}
target: kicker
}
/*
* Three IconItems are used in order to achieve the same look and feel as Windows 7's
* orbs. When the menu is closed, hovering over the orb results in the hovered icon
* gradually appearing into view, and clicking on the orb causes an instant change in
* visibility, where the normal and hovered icons are invisible, and the pressed icon
* is visible.
*
* When they're bounded by the panel, these icons will by default try to fill up as
* much space as they can in the compact representation while preserving their aspect
* ratio.
*/
FloatingOrb {
id: floatingOrbPanel
anchors.left: parent.left
//anchors.leftMargin: -Kirigami.Units.mediumSpacing
anchors.verticalCenter: parent.verticalCenter
//anchors.verticalCenterOffset: Kirigami.Units.smallSpacing-1
//anchors.fill: parent
objectName: "innerorb"
opacity: (!stickOutOrb)
}
// Handles all mouse events for the popup orb
MouseArea {
id: mouseAreaCompositingOff
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent
hoverEnabled: true
//visible: !stickOutOrb
propagateComposedEvents: true
onPressed: mouse => {
if(mouse.button === Qt.LeftButton)
showMenu();
else
mouse.accepted = false;
}
}
// I hate this
// So the only way I could reasonably think of to make this work is running the function
// with a delay.
Timer {
id: compositingFix
interval: 150
onTriggered: {
if (!compositing) {
Plasmoid.setTransparentWindow();
}
}
}
// Even worse, this just makes things even more unsophisticated. If someone has a better
// way of solving this, I would love to know.
Timer {
id: orbTimer
interval: 15
onTriggered: {
Plasmoid.setOrb(orb);
// Currently hardcoded, will make it configurable soon, when it's been properly tested and hopefully slightly refactored.
Plasmoid.setMask(Qt.resolvedUrl("./orbs/mask.png"), false);
Plasmoid.setWinState(orb);
Plasmoid.setWinType(orb);
Plasmoid.setDashWindow(dashWindow);
updateSizeHints();
positionOrb();
}
}
}

View file

@ -0,0 +1,180 @@
/***************************************************************************
* Copyright (C) 2014 by Eike Hein <hein@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Dialogs
import QtQuick.Layouts
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.kcmutils as KCM
import org.kde.draganddrop 2.0 as DragDrop
import org.kde.kirigami 2.3 as Kirigami
import org.kde.plasma.plasmoid 2.0
import org.kde.iconthemes as KIconThemes
import org.kde.plasma.private.kicker 0.1 as Kicker
KCM.SimpleKCM {
id: configGeneral
width: childrenRect.width
height: childrenRect.height
property string cfg_icon: Plasmoid.configuration.icon
property bool cfg_useCustomButtonImage: Plasmoid.configuration.useCustomButtonImage
property string cfg_customButtonImage: Plasmoid.configuration.customButtonImage
property string cfg_customButtonImageHover: Plasmoid.configuration.customButtonImageHover
property string cfg_customButtonImageActive: Plasmoid.configuration.customButtonImageActive
property alias cfg_showRecentsView: showRecentsView.checked
property alias cfg_appNameFormat: appNameFormat.currentIndex
property alias cfg_switchCategoriesOnHover: switchCategoriesOnHover.checked
property alias cfg_stickOutOrb: stickOutOrb.checked
property alias cfg_useExtraRunners: useExtraRunners.checked
property alias cfg_numberRows: numberRows.value
component CustomGroupBox: GroupBox {
id: gbox
label: Label {
id: lbl
x: gbox.leftPadding + 2
y: lbl.implicitHeight/2-gbox.bottomPadding-1
width: lbl.implicitWidth
text: gbox.title
elide: Text.ElideRight
Rectangle {
anchors.fill: parent
anchors.leftMargin: -2
anchors.rightMargin: -2
color: Kirigami.Theme.backgroundColor
z: -1
}
}
background: Rectangle {
y: gbox.topPadding - gbox.bottomPadding*2
width: parent.width
height: parent.height - gbox.topPadding + gbox.bottomPadding*2
color: "transparent"
border.color: "#d5dfe5"
radius: 3
}
}
ColumnLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Kirigami.Units.gridUnit*4
anchors.rightMargin: Kirigami.Units.gridUnit*4
CustomGroupBox {
id: orbGroup
title: i18n("Orb texture")
Layout.fillWidth: true
IconPicker {
id: iconPickerNormal
currentIcon: cfg_customButtonImage
defaultIcon: ""
onIconChanged: iconName => { cfg_customButtonImage = iconName; }
anchors.right: parent.right
anchors.left: parent.left
}
}
CustomGroupBox {
Layout.fillWidth: true
title: i18n("Behavior")
//flat: false
ColumnLayout {
RowLayout {
visible: false
Label {
text: i18n("Show applications as:")
}
ComboBox {
id: appNameFormat
Layout.fillWidth: true
model: [i18n("Name only"), i18n("Description only"), i18n("Name (Description)"), i18n("Description (Name)")]
}
}
CheckBox {
id: switchCategoriesOnHover
visible: false
text: i18n("Switch categories on hover")
}
CheckBox {
id: useExtraRunners
visible: false
text: i18n("Expand search to bookmarks, files and emails")
}
CheckBox {
id: stickOutOrb
text: i18n("Force constant orb size")
}
CheckBox {
id: showRecentsView
text: i18n("Show recent programs")
}
RowLayout{
Layout.fillWidth: true
Label {
Layout.leftMargin: Kirigami.Units.smallSpacing
text: i18n("Number of rows:")
}
SpinBox{
id: numberRows
from: 10
to: 15
}
}
}
}
}
Component.onCompleted: {
if(Plasmoid.configuration.stickOutOrb) Plasmoid.setTransparentWindow();
}
Component.onDestruction: {
if(Plasmoid.configuration.stickOutOrb) Plasmoid.setTransparentWindow();
}
}

View file

@ -0,0 +1,141 @@
/***************************************************************************
* Copyright (C) 2014 by Eike Hein <hein@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts
import org.kde.kcmutils as KCM
import org.kde.plasma.plasmoid 2.0
import org.kde.kirigami 2.3 as Kirigami
KCM.SimpleKCM {
id: configSidepanel
width: childrenRect.width
height: childrenRect.height
property alias cfg_showHomeSidepanel: showHomeSidepanel.checked
property alias cfg_showDocumentsSidepanel: showDocumentsSidepanel.checked
property alias cfg_showPicturesSidepanel: showPicturesSidepanel.checked
property alias cfg_showMusicSidepanel: showMusicSidepanel.checked
property alias cfg_showVideosSidepanel: showVideosSidepanel.checked
property alias cfg_showDownloadsSidepanel: showDownloadsSidepanel.checked
property alias cfg_showGamesSidepanel: showGamesSidepanel.checked
property alias cfg_showRecentItemsSidepanel: showRecentItemsSidepanel.checked
property alias cfg_showRootSidepanel: showRootSidepanel.checked
property alias cfg_showNetworkSidepanel: showNetworkSidepanel.checked
property alias cfg_showSettingsSidepanel: showSettingsSidepanel.checked
property alias cfg_showDevicesSidepanel: showDevicesSidepanel.checked
property alias cfg_showDefaultsSidepanel: showDefaultsSidepanel.checked
property alias cfg_showHelpSidepanel: showHelpSidepanel.checked
ColumnLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Kirigami.Units.gridUnit*4
anchors.rightMargin: Kirigami.Units.gridUnit*4
GroupBox {
id: gbox
Layout.fillWidth: true
background: Rectangle {
color: "white"
border.color: "#bababe"
y: gbox.topPadding - gbox.bottomPadding
height: parent.height - gbox.topPadding + gbox.bottomPadding
}
label: Label {
x: gbox.leftPadding
width: gbox.availableWidth
text: gbox.title
elide: Text.ElideRight
}
title: i18n("Show sidebar items")
ColumnLayout {
CheckBox {
id: showHomeSidepanel
text: i18n("Home directory")
}
CheckBox {
id: showDocumentsSidepanel
text: i18n("Documents")
}
CheckBox {
id: showPicturesSidepanel
text: i18n("Pictures")
}
CheckBox {
id: showMusicSidepanel
text: i18n("Music")
}
CheckBox {
id: showVideosSidepanel
text: i18n("Videos")
}
CheckBox {
id: showDownloadsSidepanel
text: i18n("Downloads")
}
CheckBox {
id: showGamesSidepanel
text: i18n("Games")
}
CheckBox {
id: showRecentItemsSidepanel
text: i18n("Recent Items")
}
CheckBox {
id: showRootSidepanel
text: i18n("Computer")
}
CheckBox {
id: showNetworkSidepanel
text: i18n("Network")
}
CheckBox {
id: showSettingsSidepanel
text: i18n("Control Panel")
}
CheckBox {
id: showDevicesSidepanel
text: i18n("Devices and Printers")
}
CheckBox {
id: showDefaultsSidepanel
text: i18n("Default Programs")
}
CheckBox {
id: showHelpSidepanel
text: i18n("Help and Support")
}
}
}
}
Component.onCompleted: {
if(Plasmoid.configuration.stickOutOrb) Plasmoid.setTransparentWindow();
}
Component.onDestruction: {
if(Plasmoid.configuration.stickOutOrb) Plasmoid.setTransparentWindow();
}
}

View file

@ -0,0 +1,131 @@
/*
MIT License
Copyright (c) 2020 Pierre-Yves Siret
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import QtQuick 2.15
import QtQml 2.15
Behavior {
id: root
property QtObject fadeTarget: targetProperty.object
property string fadeProperty: "opacity"
property var fadeProperties: [fadeProperty]
property var exitValue: 0
property var enterValue: exitValue
property int fadeDuration: 300
property string easingType: "Quad"
property bool delayWhile: false
property bool sequential: false
onDelayWhileChanged: {
if (!delayWhile)
sequentialAnimation.startExitAnimation();
}
readonly property Component shaderEffectSourceWrapperComponent: Item {
property alias shaderEffectSource: shaderEffectSource
property alias sourceItem: shaderEffectSource.sourceItem
parent: sourceItem.parent
x: sourceItem.x
y: sourceItem.y
ShaderEffectSource {
id: shaderEffectSource
transformOrigin: sourceItem.transformOrigin
hideSource: true
live: false
width: sourceItem.width
height: sourceItem.height
}
}
readonly property Component defaultExitAnimation: NumberAnimation {
properties: root.fadeProperties.join(',')
duration: root.fadeDuration
to: root.exitValue
easing.type: root.easingType === "Linear" ? Easing.Linear : Easing["In"+root.easingType]
}
property Component exitAnimation: defaultExitAnimation
// bind SES properties tu function provided by user: {rotation: (t) => () => t.progress * 180, opacity: (p) => 1 - p)}
readonly property Component defaultEnterAnimation: NumberAnimation {
properties: root.fadeProperties.join(',')
duration: root.fadeDuration
from: root.enterValue
to: root.fadeTarget[root.fadeProperties[0]]
easing.type: root.easingType === "Linear" ? Easing.Linear : Easing["Out"+root.easingType]
}
property Component enterAnimation: defaultEnterAnimation
SequentialAnimation {
id: sequentialAnimation
signal startEnterAnimation()
signal startExitAnimation()
ScriptAction {
script: {
const exitItem = shaderEffectSourceWrapperComponent.createObject(null, { sourceItem: root.fadeTarget });
const exitShaderEffectSource = exitItem.shaderEffectSource;
if (exitAnimation === root.defaultExitAnimation)
root.fadeProperties.forEach(p => exitShaderEffectSource[p] = root.fadeTarget[p]);
exitShaderEffectSource.width = root.fadeTarget.width;
exitShaderEffectSource.height = root.fadeTarget.height;
const exitAnimationInstance = exitAnimation.createObject(root, { target: exitItem.shaderEffectSource });
sequentialAnimation.startExitAnimation.connect(exitAnimationInstance.start);
if (root.sequential)
exitAnimationInstance.finished.connect(sequentialAnimation.startEnterAnimation);
else
exitAnimationInstance.started.connect(sequentialAnimation.startEnterAnimation);
exitAnimationInstance.finished.connect(() => {
exitItem.destroy();
exitAnimationInstance.destroy();
});
}
}
PauseAnimation {
duration: 5 // figure out how to wait on a signal in an animation (for ShaderEffectSource update or Image loading when Behaviour on source)
}
PropertyAction {}
ScriptAction {
script: {
const enterItem = shaderEffectSourceWrapperComponent.createObject(null, { sourceItem: root.fadeTarget });
const enterShaderEffectSource = enterItem.shaderEffectSource;
if (enterAnimation === root.defaultEnterAnimation)
root.fadeProperties.forEach(p => enterShaderEffectSource[p] = root.enterValue);
enterShaderEffectSource.live = true;
const enterAnimationInstance = enterAnimation.createObject(root, { target: enterItem.shaderEffectSource });
sequentialAnimation.startEnterAnimation.connect(enterAnimationInstance.start);
enterAnimationInstance.finished.connect(() => {
enterItem.destroy();
enterAnimationInstance.destroy();
});
if (!root.delayWhile)
sequentialAnimation.startExitAnimation();
}
}
}
}

View file

@ -0,0 +1,187 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Marco Martin <mart@kde.org>
Copyright 2014 Sebastian Kügler <sebas@kde.org>
Copyright (C) 2015-2018 Eike Hein <hein@kde.org>
Copyright (C) 2016 Jonathan Liu <net147@gmail.com>
Copyright (C) 2016 Kai Uwe Broulik <kde@privat.broulik.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons
import org.kde.plasma.plasmoid
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.components as PlasmaComponents
import org.kde.draganddrop 2.0
import org.kde.plasma.private.kicker 0.1 as Kicker
Item {
property ListView listView: favoritesView.listView
function activateCurrentIndex() {
favoritesView.currentItem.activate();
}
function decrementCurrentIndex() {
if (favoritesView.currentIndex == 0)
return;
favoritesView.decrementCurrentIndex();
}
function getFavoritesCount() {
return favoritesView.count;
}
function incrementCurrentIndex() {
var tempIndex = favoritesView.currentIndex + 1;
if (tempIndex >= favoritesView.count) {
favoritesView.currentIndex = -1;
if (Plasmoid.configuration.showRecentsView) {
root.m_recents.focus = true;
root.m_recents.currentIndex = 0;
} else {
root.m_showAllButton.focus = true;
}
return;
}
favoritesView.incrementCurrentIndex();
}
// QQuickItem::isAncestorOf is not invokable...
function isChildOf(item, parent) {
if (!item || !parent) {
return false;
}
if (item.parent === parent) {
return true;
}
return isChildOf(item, item.parent);
}
function openContextMenu() {
favoritesView.currentItem.openActionMenu();
}
function resetCurrentIndex() {
favoritesView.currentIndex = -1;
}
function setCurrentIndex() {
favoritesView.currentIndex = 0;
}
KeyNavigation.tab: Plasmoid.configuration.showRecentsView ? root.m_recents : root.m_showAllButton
//anchors.fill: parent
anchors.topMargin: Kirigami.Units.smallSpacing
objectName: "FavoritesView"
Keys.onPressed: event => {
if (event.key == Qt.Key_Up) {
decrementCurrentIndex();
} else if (event.key == Qt.Key_Down) {
incrementCurrentIndex();
} else if (event.key == Qt.Key_Return) {
activateCurrentIndex();
} else if (event.key == Qt.Key_Menu) {
openContextMenu();
}
}
onFocusChanged: {
if (focus)
setCurrentIndex();
else
resetCurrentIndex();
}
DropArea {
property int startRow: -1
function syncTarget(event) {
if (favoritesView.animating) {
return;
}
var pos = mapToItem(listView.contentItem, event.x, event.y);
var above = listView.itemAt(pos.x, pos.y);
var source = kickoff.dragSource;
if (above && above !== source && isChildOf(source, favoritesView)) {
favoritesView.model.moveRow(source.itemIndex, above.itemIndex);
// itemIndex changes directly after moving,
// we can just set the currentIndex to it then.
favoritesView.currentIndex = source.itemIndex;
}
}
anchors.fill: parent
enabled: plasmoid.immutability !== PlasmaCore.Types.SystemImmutable
onDragEnter: {
syncTarget(event);
startRow = favoritesView.currentIndex;
}
onDragMove: syncTarget(event)
}
Transition {
id: moveTransition
SequentialAnimation {
PropertyAction {
property: "animating"
target: favoritesView
value: true
}
NumberAnimation {
duration: favoritesView.animationDuration
easing.type: Easing.OutQuad
properties: "x, y"
}
PropertyAction {
property: "animating"
target: favoritesView
value: false
}
}
}
Connections {
function onExpandedChanged() {
if (!plasmoid.expanded) {
favoritesView.currentIndex = -1;
}
}
target: kicker
}
KickoffListView {
id: favoritesView
property bool animating: false
property int animationDuration: resetAnimationDurationTimer.interval
anchors.fill: parent
interactive: contentHeight > height
model: globalFavorites
move: moveTransition
moveDisplaced: moveTransition
onCountChanged: {
animationDuration = 0;
resetAnimationDurationTimer.start();
}
}
Timer {
id: resetAnimationDurationTimer
interval: 150
onTriggered: favoritesView.animationDuration = interval - 20
}
}

View file

@ -0,0 +1,104 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Dialogs
import QtQuick.Window
import org.kde.plasma.plasmoid
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.extras as PlasmaExtras
import org.kde.plasma.private.kicker as Kicker
import org.kde.coreaddons as KCoreAddons // kuser
import org.kde.plasma.private.shell 2.0
import org.kde.kwindowsystem 1.0
import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.private.quicklaunch 1.0
import org.kde.kirigami 2.13 as Kirigami
import org.kde.kquickcontrolsaddons 2.0 as KQuickAddons
import org.kde.kcmutils as KCM
import org.kde.kwindowsystem 1.0
Item {
id: iconContainer
//The frame displayed on top of the user icon
height: Kirigami.Units.iconSizes.huge
//Kirigami.Units.iconSizes.huge
width: height
anchors.horizontalCenter: parent.horizontalCenter
property alias iconSource: imgAuthorIcon.source
Image {
source: "../pics/user.png"
smooth: true
z: 1
opacity: imgAuthorIcon.source === ""
Behavior on opacity {
NumberAnimation { duration: 350 }
}
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
top: parent.top
}
}
Kirigami.Icon {
id: imgAuthorIcon
source: ""
height: parent.height
width: height
smooth: true
visible: true
//usesPlasmaTheme: false
z: 99
CrossFadeBehavior on source {
fadeDuration: 350
}
}
Image {
id: imgAuthor
anchors {
top: parent.top
left: parent.left
right: parent.right
bottom: parent.bottom
topMargin: Kirigami.Units.smallSpacing*2
leftMargin: Kirigami.Units.smallSpacing*2
rightMargin: Kirigami.Units.smallSpacing*2
bottomMargin: Kirigami.Units.smallSpacing*2
}
opacity: imgAuthorIcon.source === ""
Behavior on opacity {
NumberAnimation { duration: 350 }
}
source: kuser.faceIconUrl.toString()
smooth: true
mipmap: true
visible: true
}
/*OpacityMask {
anchors.fill: imgAuthor
source: (kuser.faceIconUrl.toString() === "") ? imgAuthorIcon : imgAuthor;
maskSource: Rectangle {
width: imgAuthorIcon.source === "" ? imgAuthor.width : 0
height: imgAuthor.height
visible: false
}
}*/
MouseArea{
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onPressed: {
root.visible = false;
KCM.KCMLauncher.openSystemSettings("kcm_users")
}
cursorShape: Qt.PointingHandCursor
}
}

View file

@ -0,0 +1,90 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Dialogs
import QtQuick.Window
import org.kde.plasma.plasmoid
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.extras as PlasmaExtras
import org.kde.plasma.private.kicker as Kicker
import org.kde.coreaddons as KCoreAddons // kuser
import org.kde.plasma.private.shell 2.0
import org.kde.kwindowsystem 1.0
import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.private.quicklaunch 1.0
import org.kde.kirigami 2.13 as Kirigami
import org.kde.kquickcontrolsaddons 2.0 as KQuickAddons
import org.kde.kwindowsystem 1.0
import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons
import org.kde.kirigami as Kirigami
Item {
id: floatingOrb
width: buttonIconSizes.width
height: buttonIconSizes.height / 3
property alias buttonIconSizes: buttonIconSizes
property alias buttonIcon: buttonIcon
property alias buttonIconPressed: buttonIconPressed
property alias buttonIconHovered: buttonIconHovered
property alias mouseArea: mouseArea
property string orbTexture: getResolvedUrl(Plasmoid.configuration.customButtonImage, "orbs/orb.png")
property int opacityDuration: 300
Image {
id: buttonIconSizes
smooth: true
source: orbTexture
opacity: 0;
}
clip: false
Image {
id: buttonIcon
smooth: true
source: orbTexture
sourceClipRect: Qt.rect(0, 0, buttonIconSizes.width, buttonIconSizes.height / 3);
}
Image {
id: buttonIconPressed
visible: dashWindow.visible
smooth: true
source: orbTexture
verticalAlignment: Image.AlignBottom
sourceClipRect: Qt.rect(0, 2*buttonIconSizes.height / 3, buttonIconSizes.width, buttonIconSizes.height / 3);
}
Image {
id: buttonIconHovered
source: orbTexture
opacity: mouseArea.containsMouse || mouseAreaCompositingOff.containsMouse
visible: !dashWindow.visible
Behavior on opacity {
NumberAnimation { properties: "opacity"; easing.type: Easing.Linear; duration: opacityDuration }
}
verticalAlignment: Image.AlignVCenter
sourceClipRect: Qt.rect(0, buttonIconSizes.height / 3, buttonIconSizes.width, buttonIconSizes.height / 3);
}
MouseArea
{
id: mouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
propagateComposedEvents: true
onPressed: mouse => {
if(mouse.button === Qt.LeftButton)
root.showMenu();
else
mouse.accepted = false;
}
}
}

View file

@ -0,0 +1,199 @@
/*****************************************************************************
* Copyright (C) 2022 by Friedrich Schriewer <friedrich.schriewer@gmx.net> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
****************************************************************************/
import QtQuick 2.12
import QtQuick.Layouts 1.12
import Qt5Compat.GraphicalEffects
import QtQuick.Window 2.2
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.coreaddons 1.0 as KCoreAddons
import org.kde.kirigami 2.13 as Kirigami
import QtQuick.Controls 2.15
import "../code/tools.js" as Tools
Item {
id: allItem
width: scrollView.availableWidth - Kirigami.Units.mediumSpacing
height: Kirigami.Units.iconSizes.smallMedium
property var itemSection: model.group
property bool highlighted: false
property bool isDraging: false
property bool canDrag: true
property bool canNavigate: false
signal highlightChanged
signal aboutToShowActionMenu(variant actionMenu)
property bool hasActionList: ((model.favoriteId !== null)
|| (("hasActionList" in model) && (model.hasActionList !== null)))
property var triggerModel
onAboutToShowActionMenu: actionMenu => {
var actionList = allItem.hasActionList ? model.actionList : [];
Tools.fillActionMenu(i18n, actionMenu, actionList, globalFavorites, model.favoriteId);
}
function openActionMenu(x, y) {
aboutToShowActionMenu(actionMenu);
if(actionMenu.actionList.length === 0) return;
actionMenu.visualParent = allItem;
actionMenu.open(x, y);
}
function actionTriggered(actionId, actionArgument) {
var close = (Tools.triggerAction(triggerModel, index, actionId, actionArgument) === true);
if (close) {
//root.toggle();
root.visible = false;
}
}
function trigger() {
triggerModel.trigger(index, "", null);
root.visible = false;
}
function updateHighlight() {
if (navGrid.currentIndex == index){
highlighted = true
} else {
highlighted = false
}
}
function deselect(){
highlighted = false
listView.currentIndex = -1
}
Kirigami.Icon {
id: appicon
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Kirigami.Units.smallSpacing*2 + Kirigami.Units.iconSizes.small
width: Kirigami.Units.iconSizes.small
height: width
source: model.decoration
}
PlasmaComponents.Label {
id: appname
anchors.left: appicon.right
anchors.right: parent.right
anchors.rightMargin: Kirigami.Units.smallSpacing
anchors.leftMargin: Kirigami.Units.smallSpacing
anchors.verticalCenter: appicon.verticalCenter
text: ("name" in model ? model.name : model.display)
font.underline: ma.containsMouse
elide: Text.ElideRight
}
KickoffHighlight {
id: rectFill
anchors.fill: parent
anchors.leftMargin: Kirigami.Units.iconSizes.small
opacity: (listView.currentIndex === index) * 0.7 + ma.containsMouse * 0.3
}
Timer {
id: toolTipTimer
interval: Kirigami.Units.longDuration*4
onTriggered: {
toolTip.showToolTip();
}
}
PlasmaCore.ToolTipArea {
id: toolTip
anchors {
fill: parent
}
active: appname.truncated
interactive: false
/*location: (((Plasmoid.location === PlasmaCore.Types.RightEdge)
* || (Qt.application.layoutDirection === Qt.RightToLeft))
* ? PlasmaCore.Types.RightEdge : PlasmaCore.Types.LeftEdge)*/
mainText: appname.text
}
MouseArea {
id: ma
anchors.fill: parent
anchors.leftMargin: Kirigami.Units.iconSizes.small
z: parent.z + 1
acceptedButtons: Qt.LeftButton | Qt.RightButton
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: mouse => {
if (mouse.button == Qt.RightButton) {
if (allItem.hasActionList) {
var mapped = mapToItem(allItem, mouse.x, mouse.y);
allItem.openActionMenu(mapped.x, mapped.y);
}
} else {
trigger()
}
}
onReleased: {
isDraging: false
}
// to prevent crashing
onEntered: {
if(parent.parent) {
listView.currentIndex = index;
}
toolTipTimer.start();
}
onExited: {
if(parent.parent) {
listView.currentIndex = -1;
toolTipTimer.stop();
toolTip.hideToolTip();
}
}
onPositionChanged: {
isDraging = pressed
if (pressed && canDrag){
if ("pluginName" in model) {
dragHelper.startDrag(kicker, model.url, model.decoration,
"text/x-plasmoidservicename", model.pluginName);
} else {
dragHelper.startDrag(kicker, model.url, model.decoration);
}
}
listView.currentIndex = containsMouse ? index : -1
/*if (containsMouse) {
if (canNavigate) {
listView.currentIndex = index
//listView.focus = true
}
}*/
}
}
ActionMenu {
id: actionMenu
onActionClicked: {
visualParent.actionTriggered(actionId, actionArgument);
//root.toggle()
}
}
}

View file

@ -0,0 +1,94 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.iconthemes as KIconThemes
import org.kde.ksvg as KSvg
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.extras as PlasmaExtras
import org.kde.kirigami 2.3 as Kirigami
// basically taken from kickoff
RowLayout {
id: iconButton
property string currentIcon
property string defaultIcon
signal iconChanged(string iconName)
//Layout.minimumWidth: previewFrame.width + Kirigami.Units.smallSpacing * 2
//Layout.maximumWidth: Layout.minimumWidth
//Layout.minimumHeight: previewFrame.height + Kirigami.Units.smallSpacing * 2
//Layout.maximumHeight: Layout.minimumWidth
KIconThemes.IconDialog {
id: iconDialog
onIconNameChanged: iconName => {
iconPreview.source = iconName
iconChanged(iconName)
}
}
Layout.fillWidth: true
ColumnLayout {
Text {
Layout.fillWidth: true
Layout.fillHeight: true
wrapMode: Text.WordWrap
text: "Customize the way the menu orb looks like using ClassicShell/OpenShell-compatible PNG resources.\nOnly orb textures with three frames are supported."
}
RowLayout {
Button {
text: i18nc("@item:inmenu Open icon chooser dialog", "Choose...")
onClicked: iconDialog.open()
}
Button {
text: i18nc("@item:inmenu Reset icon to default", "Reset")
onClicked: setDefaultIcon()
}
}
}
KSvg.FrameSvgItem {
id: previewFrame
//anchors.centerIn: parent
imagePath: Plasmoid.location === PlasmaCore.Types.Vertical || Plasmoid.location === PlasmaCore.Types.Horizontal
? "widgets/panel-background" : "widgets/background"
Layout.preferredWidth: Kirigami.Units.iconSizes.large + fixedMargins.left + fixedMargins.right
Layout.preferredHeight: Kirigami.Units.iconSizes.large + fixedMargins.top + fixedMargins.bottom
Layout.bottomMargin: Kirigami.Units.smallSpacing
Kirigami.Icon {
id: iconPreview
anchors.centerIn: parent
width: Kirigami.Units.iconSizes.large
height: width
source: currentIcon
}
}
function setDefaultIcon() {
iconPreview.source = defaultIcon
iconChanged(defaultIcon)
}
// QQC Menu can only be opened at cursor position, not a random one
/*PlasmaExtras.Menu {
id: iconMenu
PlasmaExtras.MenuItem {
text: i18nc("@item:inmenu Open icon chooser dialog", "Choose...")
icon: "document-open-folder"
onClicked: iconDialog.open()
}
PlasmaExtras.MenuItem {
text: i18nc("@item:inmenu Reset icon to default", "Clear Icon")
icon: "edit-clear"
onClicked: setDefaultIcon()
}
}*/
}

View file

@ -0,0 +1,67 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.kquickcontrolsaddons 2.0
PlasmaComponents.TabButton {
id: button
objectName: "KickoffButton"
property string iconSource
property alias text: labelElement.text
implicitHeight: iconElement.height + labelElement.implicitHeight + iconElement.anchors.topMargin + labelElement.anchors.topMargin + labelElement.anchors.bottomMargin
Item {
anchors {
margins: Kirigami.Units.smallSpacing
left: parent.left
right: parent.right
verticalCenter: parent.verticalCenter
}
height: childrenRect.height
PlasmaCore.IconItem {
id: iconElement
anchors.horizontalCenter: parent.horizontalCenter
width: Kirigami.Units.iconSizes.medium
height: width
source: iconSource
}
PlasmaComponents.Label {
id: labelElement
anchors {
top: iconElement.bottom
left: parent.left
right: parent.right
}
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
wrapMode: Text.WordWrap
font: theme.smallestFont
}
}
} // button

View file

@ -0,0 +1,88 @@
/*
* Copyright 2014 Sebastian Kügler <sebas@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
Item {
id: highlight
/** true if the user is hovering over the component */
//in the case we are the highlight of a listview, it follows the mouse, so hover = true
property bool hover: ListView ? true : false
/** true if the mouse button is pressed over the component. */
property bool pressed: false
width: ListView.view ? ListView.view.width : undefined
property alias marginHints: background.margins;
Connections {
target: highlight.ListView.view
function onCurrentIndexChanged() {
if (highlight.ListView.view.currentIndex >= 0) {
background.opacity = 1
} else {
background.opacity = 0
}
}
}
Behavior on opacity {
NumberAnimation {
duration: Kirigami.Units.veryShortDuration
easing.type: Easing.OutQuad
}
}
KSvg.FrameSvgItem {
id: background
imagePath: Qt.resolvedUrl("svgs/menuitem.svg")
prefix: {
if (pressed)
return hover ? "selected+hover" : "selected";
if (hover)
return "hover";
return "normal";
}
Behavior on opacity {
NumberAnimation {
duration: Kirigami.Units.veryShortDuration
easing.type: Easing.OutQuad
}
}
anchors {
fill: parent
leftMargin: Kirigami.Units.smallSpacing
rightMargin: Kirigami.Units.smallSpacing
//FIXME: breaks listviews and highlight item
// topMargin: -background.margins.top
// leftMargin: -background.margins.left
// bottomMargin: -background.margins.bottom
// rightMargin: -background.margins.right
}
}
}

View file

@ -0,0 +1,210 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Gregor Taetzner <gregor@freenet.de>
Copyright 2014 Sebastian Kügler <sebas@kde.org>
Copyright (C) 2015-2018 Eike Hein <hein@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
//This is the generic item delegate used by FavoritesView, RecentlyUsedView and SearchView.
import QtQuick 2.0
import org.kde.plasma.plasmoid
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.draganddrop 2.0
import org.kde.kirigami as Kirigami
import org.kde.ksvg as KSvg
import "code/tools.js" as Tools
Item {
id: listItem
enabled: !model.disabled && !(model.display === "" || model.display === "Recent Applications")
visible: !(model.display === "" || model.display === "Recent Applications")
width: ListView.view.width
height: model.display === "" || model.display === "Recent Applications" ? 0 : (Kirigami.Units.smallSpacing / (small ? 2 : 1)) + Math.max(elementIcon.height, titleElement.implicitHeight /*+ subTitleElement.implicitHeight*/)
signal reset
signal actionTriggered(string actionId, variant actionArgument)
signal aboutToShowActionMenu(variant actionMenu)
signal addBreadcrumb(var model, string title)
property alias toolTip: toolTip
property bool smallIcon: false
readonly property int itemIndex: model.index
readonly property string url: model.url || ""
readonly property var decoration: model.decoration || ""
property bool dropEnabled: false
property bool appView: false
property bool modelChildren: model.hasChildren || false
property bool isCurrent: listItem.ListView.view.currentIndex === index;
property bool showAppsByName: Plasmoid.configuration.showAppsByName
property bool hasActionList: ((model.favoriteId !== null)
|| (("hasActionList" in model) && (model.hasActionList === true)))
property Item menu: actionMenu
//property alias usePlasmaIcon: elementIcon.usesPlasmaTheme
onAboutToShowActionMenu: (actionMenu) => {
var actionList = hasActionList ? model.actionList : [];
Tools.fillActionMenu(i18n, actionMenu, actionList, ListView.view.model.favoritesModel, model.favoriteId);
}
onActionTriggered: (actionId, actionArgument) => {
kicker.expanded = false;
if (Tools.triggerAction(ListView.view.model, model.index, actionId, actionArgument) === true) {
kicker.expanded = false;
}
/*if (actionId.indexOf("_kicker_favorite_") === 0) {
switchToInitial();
}*/
}
function activate() {
var view = listItem.ListView.view;
if (model.hasChildren) {
var childModel = view.model.modelForRow(index);
listItem.addBreadcrumb(childModel, model.display);
view.model = childModel;
} else {
view.model.trigger(model.index, "", null);
kicker.expanded = false;
listItem.reset();
}
}
function openActionMenu(x, y) {
aboutToShowActionMenu(actionMenu);
actionMenu.visualParent = listItem;
actionMenu.open(x, y);
}
ActionMenu {
id: actionMenu
onActionClicked: (actionId, actionArgument) => {
actionTriggered(actionId, actionArgument);
}
}
Kirigami.Icon {
id: elementIcon
anchors {
left: parent.left
leftMargin: Kirigami.Units.smallSpacing*2-1
verticalCenter: parent.verticalCenter
}
width: smallIcon ? Kirigami.Units.iconSizes.small : Kirigami.Units.iconSizes.medium
height: width
animated: false
//usesPlasmaTheme: false
source: model.decoration
}
PlasmaComponents.Label {
id: titleElement
y: Math.round((parent.height - titleElement.height - ( (subTitleElement.text != "") ? subTitleElement.implicitHeight : 0) ) / 2)
anchors {
left: elementIcon.right
right: arrow.left
leftMargin: Kirigami.Units.smallSpacing * 2 - 2
rightMargin: Kirigami.Units.smallSpacing * 2
}
height: implicitHeight //undo PC2 height override, remove when porting to PC3
// TODO: games should always show the by name!
text: model.display
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
color: "#000000"
}
PlasmaComponents.Label {
id: subTitleElement
anchors {
left: titleElement.left
right: arrow.right
top: titleElement.bottom
}
height: implicitHeight
color: "#000000"
text: ""//model.description || ""
opacity: isCurrent ? 0.8 : 0.6
font: Kirigami.Theme.smallFont
elide: Text.ElideMiddle
horizontalAlignment: Text.AlignLeft
}
KSvg.SvgItem {
id: arrow
anchors {
right: parent.right
rightMargin: Kirigami.Units.smallSpacing
verticalCenter: parent.verticalCenter
}
width: visible ? Kirigami.Units.iconSizes.small : 0
height: width
visible: (model.hasChildren === true)
opacity: (listItem.ListView.view.currentIndex === index) ? 1.0 : 0.8
svg: arrowsSvg
elementId: (Qt.application.layoutDirection == Qt.RightToLeft) ? "left-arrow-black" : "right-arrow-black"
}
Keys.onPressed: {
if (event.key === Qt.Key_Menu && hasActionList) {
event.accepted = true;
openActionMenu();
} else if ((event.key === Qt.Key_Enter || event.key === Qt.Key_Return) && !modelChildren) {
if (!modelChildren) {
event.accepted = true;
listItem.activate();
}
}
}
PlasmaCore.ToolTipArea {
id: toolTip
anchors {
fill: parent
}
active: titleElement.truncated
interactive: false
/*location: (((Plasmoid.location === PlasmaCore.Types.RightEdge)
|| (Qt.application.layoutDirection === Qt.RightToLeft))
? PlasmaCore.Types.RightEdge : PlasmaCore.Types.LeftEdge)*/
mainText: model.display
}
}

View file

@ -0,0 +1,218 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Gregor Taetzner <gregor@freenet.de>
Copyright (C) 2015-2018 Eike Hein <hein@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.components as PlasmaComponents
import org.kde.kirigami as Kirigami
FocusScope {
id: view
property bool appView: false
property alias contentHeight: listView.contentHeight
property alias count: listView.count
property alias currentIndex: listView.currentIndex
property alias currentItem: listView.currentItem
property alias delegate: listView.delegate
property alias interactive: listView.interactive
readonly property Item listView: listView
property alias model: listView.model
property alias move: listView.move
property alias moveDisplaced: listView.moveDisplaced
readonly property Item scrollView: scrollView
property bool showAppsByName: true
property bool small: false
signal addBreadcrumb(var model, string title)
signal reset
function decrementCurrentIndex() {
listView.decrementCurrentIndex();
}
function incrementCurrentIndex() {
listView.incrementCurrentIndex();
}
Connections {
function onExpandedChanged() {
if (!kicker.expanded) {
listView.positionViewAtBeginning();
}
}
target: kicker
}
Timer {
id: toolTipTimer
interval: Kirigami.Units.longDuration*4
onTriggered: {
if(listView.currentItem) listView.currentItem.toolTip.showToolTip();
}
}
PlasmaComponents.ScrollView {
id: scrollView
//frameVisible: false
anchors.fill: parent
ListView {
id: listView
boundsBehavior: Flickable.StopAtBounds
focus: true
highlightMoveDuration: 0
highlightResizeDuration: 0
keyNavigationWraps: true
spacing: small ? 0 : Kirigami.Units.smallSpacing / 2
delegate: KickoffItem {
id: delegateItem
required property var model
required property int index
appView: view.appView
showAppsByName: view.showAppsByName
smallIcon: small
onAddBreadcrumb: view.addBreadcrumb(model, title)
onReset: view.reset()
}
highlight: KickoffHighlight {
}
section.property: "group"
/*section {
criteria: ViewSection.FullString
property: "group"
delegate: SectionDelegate {
}
}*/
MouseArea {
id: mouseArea
// property Item pressed: null
property int pressX: -1
property int pressY: -1
property bool tapAndHold: false
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.left: parent.left
height: parent.height
hoverEnabled: true
width: scrollView.width
onContainsMouseChanged: {
if (!containsMouse) {
//pressed = null;
toolTipTimer.stop();
if(listView.currentItem) listView.currentItem.toolTip.hideToolTip();
pressX = -1;
pressY = -1;
tapAndHold = false;
listView.currentIndex = -1;
}
}
onPositionChanged: function(mouse) {
var mapped = listView.mapToItem(listView.contentItem, mouse.x, mouse.y);
var item = listView.itemAt(mapped.x, mapped.y);
if (item) {
toolTipTimer.stop();
if(listView.currentItem) listView.currentItem.toolTip.hideToolTip();
listView.currentIndex = item.itemIndex;
toolTipTimer.start();
//item.toolTip.showToolTip();
} else {
listView.currentIndex = -1;
}
if (mouse.source != Qt.MouseEventSynthesizedByQt || tapAndHold) {
if (pressed && pressX != -1 && pressed.url && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) {
kickoff.dragSource = item;
if (mouse.source == Qt.MouseEventSynthesizedByQt) {
dragHelper.dragIconSize = Kirigami.Units.iconSizes.huge;
dragHelper.startDrag(kickoff, pressed.url, pressed.decoration);
} else {
dragHelper.dragIconSize = Kirigami.Units.iconSizes.medium;
dragHelper.startDrag(kickoff, pressed.url, pressed.decoration);
}
//pressed = null;
pressX = -1;
pressY = -1;
tapAndHold = false;
}
}
}
onPressAndHold: function(mouse) {
if (mouse.source == Qt.MouseEventSynthesizedByQt) {
tapAndHold = true;
positionChanged(mouse);
}
}
onPressed: function(mouse) {
var mapped = listView.mapToItem(listView.contentItem, mouse.x, mouse.y);
var item = listView.itemAt(mapped.x, mapped.y);
if (!item) {
return;
}
if (mouse.buttons & Qt.RightButton) {
if (item.hasActionList) {
mapped = listView.contentItem.mapToItem(item, mapped.x, mapped.y);
listView.currentItem.openActionMenu(mapped.x, mapped.y);
}
} else {
//pressed = item;
//item.activate();
pressX = mouse.x;
pressY = mouse.y;
}
}
onReleased: function(mouse) {
var mapped = listView.mapToItem(listView.contentItem, mouse.x, mouse.y);
var item = listView.itemAt(mapped.x, mapped.y);
if (item && /*pressed === item && */!tapAndHold) {
if (item.appView) {
if (mouse.source == Qt.MouseEventSynthesizedByQt) {
positionChanged(mouse);
}
view.state = "OutgoingLeft";
} else {
item.activate();
root.visible = false;
}
listView.currentIndex = -1;
}
if (tapAndHold && mouse.source == Qt.MouseEventSynthesizedByQt) {
if (item.hasActionList) {
mapped = listView.contentItem.mapToItem(item, mapped.x, mapped.y);
listView.currentItem.openActionMenu(mapped.x, mapped.y);
}
}
//pressed = null;
pressX = -1;
pressY = -1;
tapAndHold = false;
}
}
}
}
}

View file

@ -0,0 +1,105 @@
/*
* Copyright 2015 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA.
*/
import QtQuick 2.2
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.kirigami as Kirigami
Item {
id: item
signal clicked
signal iconClicked
property alias text: label.text
// property alias subText: sublabel.text
property alias icon: icon.source
// "enabled" also affects all children
property bool interactive: true
property bool interactiveIcon: false
property bool showIcon: false
//property alias usesPlasmaTheme: icon.usesPlasmaTheme
property alias containsMouse: area.containsMouse
property alias size: icon.height
property Item highlight
Layout.fillWidth: true
height: size + 2 * Kirigami.Units.smallSpacing
width: height
MouseArea {
id: area
anchors.fill: parent
enabled: item.interactive
hoverEnabled: true
onClicked: item.clicked()
onContainsMouseChanged: {
if (!highlight) {
return
}
if (containsMouse) {
highlight.parent = item
highlight.width = item.width
highlight.height = item.height
}
highlight.visible = containsMouse
}
}
Kirigami.Icon {
id: icon
width: icon.height
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: Kirigami.Units.smallSpacing * 2
//usesPlasmaTheme: true
visible: showIcon
MouseArea {
anchors.fill: parent
visible: item.interactiveIcon
cursorShape: Qt.PointingHandCursor
onClicked: item.iconClicked()
}
}
PlasmaComponents.Label {
id: label
wrapMode: Text.NoWrap
elide: Text.ElideRight
anchors.left: showIcon ? icon.right : parent.left
anchors.leftMargin: Kirigami.Units.smallSpacing * 2
anchors.verticalCenter: icon.verticalCenter
style: Text.Sunken
styleColor: "transparent"
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,138 @@
/*****************************************************************************
* Copyright (C) 2022 by Friedrich Schriewer <friedrich.schriewer@gmx.net> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
****************************************************************************/
import QtQuick 2.12
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.kquickcontrolsaddons 2.0
import QtQuick.Controls 2.15
import org.kde.draganddrop 2.0
FocusScope {
id: navGrid
signal keyNavUp
signal keyNavDown
property alias triggerModel: listView.model
property alias count: listView.count
property alias currentIndex: listView.currentIndex
property alias currentItem: listView.currentItem
property alias contentItem: listView.contentItem
property Item flickableItem: listView
onFocusChanged: {
if (!focus) {
currentIndex = -1;
}
}
function tryActivate() {
if(currentIndex === -1 && listView.count > 0) {
listView.itemAtIndex(0).trigger();
return;
}
if (currentItem){
currentItem.trigger()
}
}
function setFocus() {
currentIndex = 0
focus = true
}
function setFocusLast() {
if (count > 0) {
currentIndex = count - 1
focus = true
} else {
setFocus()
}
}
Text {
id: noResults
opacity: 0.6
text: "No items match your search."
anchors.fill: parent
anchors.topMargin: 13
horizontalAlignment: Text.AlignHCenter
visible: listView.count === 0 && searching
}
ScrollView {
id: scrollView
anchors.fill: parent
anchors.rightMargin: 4
ListView {
anchors.fill: parent
id: listView
currentIndex: -1
focus: true
property alias scrollBar: scrollView
highlightMoveDuration: 0
highlightResizeDuration: 0
snapMode: ListView.SnapToItem
interactive: false
boundsBehavior: Flickable.StopAtBounds
section {
criteria: ViewSection.FullString
property: "group"
delegate: SectionDelegate {
sectionCount: {
var x = 0;
if(!listView) return 0;
for(var i = 0; i < listView.count; i++) {
//console.log(listView.itemAtIndex(i));
if(listView.itemAtIndex(i)) {
if(listView.itemAtIndex(i).itemSection === section) x++;
}
}
return x;
}
}
}
delegate: GenericItem {
canNavigate: true
canDrag: true
triggerModel: listView.model
//Layout.leftMargin: Kirigami.Units.iconSizes.small
//x: Kirigami.Units.iconSizes.small
}
onCurrentIndexChanged: {
if (currentIndex != -1) {
focus = true;
}
}
onModelChanged: {
currentIndex = -1;
}
onFocusChanged: {
if (!focus) {
currentIndex = -1
}
}
}
}
}

View file

@ -0,0 +1,172 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Marco Martin <mart@kde.org>
Copyright (C) 2015 Eike Hein <hein@kde.org>
Copyright (C) 2017 Ivan Cukic <ivan.cukic@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.plasma.components as PlasmaComponents
import org.kde.kitemmodels as KItemModels
import org.kde.plasma.plasmoid
import org.kde.plasma.private.kicker 0.1 as Kicker
/*
* Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
* Copyright (C) 2012 Marco Martin <mart@kde.org>
* Copyright (C) 2015-2018 Eike Hein <hein@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.draganddrop 2.0
Item {
property alias model: baseView.model
property alias delegate: baseView.delegate
property alias currentIndex: baseView.currentIndex;
property alias count: baseView.count;
objectName: "OftenUsedView"
property ListView listView: baseView.listView
function decrementCurrentIndex() {
var tempIndex = baseView.currentIndex-1;
if(tempIndex < 0) {
baseView.currentIndex = -1;
root.m_faves.focus = true;
root.m_faves.listView.currentIndex = root.m_faves.listView.count-1;
return;
}
baseView.decrementCurrentIndex();
}
KeyNavigation.tab: root.m_showAllButton
function incrementCurrentIndex() {
var tempIndex = baseView.currentIndex+1;
if(tempIndex >= baseView.count) {
baseView.currentIndex = -1;
root.m_showAllButton.focus = true;
return;
}
baseView.incrementCurrentIndex();
}
function activateCurrentIndex() {
baseView.currentItem.activate();
}
function openContextMenu() {
baseView.currentItem.openActionMenu();
}
function setCurrentIndex() {
baseView.currentIndex = 0;
}
function resetCurrentIndex() {
baseView.currentIndex = -1;
}
Connections {
target: kicker
function onExpandedChanged() {
if (!kicker.expanded) {
baseView.currentIndex = -1;
}
}
}
KickoffListView {
id: baseView
anchors.fill: parent
currentIndex: -1
interactive: contentHeight > height
model: KItemModels.KSortFilterProxyModel {
sourceModel: rootModel.modelForRow(0)
property var favoritesModel: globalFavorites
property int favoritesCount: sourceModel.favoritesModel.count
onFavoritesCountChanged: {
sourceModel.refresh();
}
function trigger(index, str, ptr) {
sourceModel.trigger(index, str, ptr);
}
filterRowCallback: function(source_row, source_parent) {
//return sourceModel.data(sourceModel.index(source_row, 0, source_parent), Qt.DisplayRole) == "...";
return source_row < Plasmoid.configuration.numberRows - sourceModel.favoritesModel.count;
};
}
}
onFocusChanged: {
if(focus) setCurrentIndex();
else resetCurrentIndex();
}
Keys.onPressed: event => {
if(event.key == Qt.Key_Up) {
decrementCurrentIndex();
} else if(event.key == Qt.Key_Down) {
incrementCurrentIndex();
} else if(event.key == Qt.Key_Return) {
activateCurrentIndex();
} else if(event.key == Qt.Key_Menu) {
openContextMenu();
}
}
}
/*
BaseView {
id: recentsModel
objectName: "OftenUsedView"
KeyNavigation.tab: root.m_showAllButton
model: KItemModels.KSortFilterProxyModel {
sourceModel: rootModel.modelForRow(0)
property var favoritesModel: globalFavorites
function trigger(index, str, ptr) {
sourceModel.trigger(index, str, ptr);
}
filterRowCallback: function(source_row, source_parent) {
//return sourceModel.data(sourceModel.index(source_row, 0, source_parent), Qt.DisplayRole) == "...";
return source_row < Plasmoid.configuration.numberRows - sourceModel.favoritesModel.count ;
};
}
}
*/

View file

@ -0,0 +1,104 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Gregor Taetzner <gregor@freenet.de>
Copyright (C) 2015-2018 Eike Hein <hein@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.private.kicker as Kicker
import org.kde.kirigami as Kirigami
Item {
id: searchViewContainer
property Item itemGrid: runnerGrid
property bool queryFinished: false
property int repeaterModelIndex: 0
function activateCurrentIndex() {
runnerGrid.tryActivate();
}
function decrementCurrentIndex() {
var listView = runnerGrid.flickableItem;
if(listView.currentIndex-1 < 0) {
listView.currentIndex = listView.count - 1;
} else {
listView.currentIndex--;
}
}
function incrementCurrentIndex() {
var listView = runnerGrid.flickableItem;
if(listView.currentIndex+1 >= listView.count) {
listView.currentIndex = 0;
} else {
listView.currentIndex++;
}
}
function onQueryChanged() {
queryFinished = false;
runnerModel.query = searchField.text;
if (!searchField.text) {
if (runnerModel.model)
runnerModel.model = null;
}
}
function openContextMenu() {
runnerModel.currentItem.openActionMenu();
}
function resetCurrentIndex() {
runnerModel.currentIndex = -1;
}
/*function setCurrentIndex() {
runnerGrid.modelIndex = 0;
}*/
objectName: "SearchView"
Connections {
function onCountChanged() {
if (runnerModel.count && !runnerGrid.model) {
runnerGrid.model = runnerModel.modelForRow(0);
}
}
function onQueryFinished() {
if (runnerModel.count) {
runnerGrid.model = null;
runnerGrid.model = runnerModel.modelForRow(0);
queryFinished = true;
var listView = runnerGrid.flickableItem;
if(listView.count > 0) listView.currentIndex = 0;
//console.log(runnerModel.modelForRow(0).modelForRow(0))
}
}
target: runnerModel
}
NavGrid {
id: runnerGrid
anchors.fill: parent
property alias model: runnerGrid.triggerModel
triggerModel: kicker.runnerModel.count ? kicker.runnerModel.modelForRow(0) : null
}
}

View file

@ -0,0 +1,61 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Marco Martin <mart@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import QtQuick.Controls 2.15
import org.kde.kirigami as Kirigami
Item {
id: sectionDelegate
width: parent.width
height: Kirigami.Units.iconSizes.medium-1 //childrenRect.height
objectName: "SectionDelegate"
function getName() {
return sectionHeading.text;
}
property int sectionCount: 0
PlasmaExtras.Heading {
id: sectionHeading
anchors {
left: parent.left
leftMargin: Kirigami.Units.smallSpacing*2
verticalCenter: parent.verticalCenter
//verticalCenterOffset: Kirigami.Units.smallSpacing/2
}
color: "#1d3287"
//y: Math.round(Kirigami.Units.gridUnit / 4)
level: 3
text: section + (sectionCount > 0 ? " (" + sectionCount + ")" : "")
}
Rectangle {
id: line
anchors.left: sectionHeading.right
anchors.leftMargin: Kirigami.Units.largeSpacing-1
anchors.rightMargin: Kirigami.Units.largeSpacing+1 + (scrollView.ScrollBar.vertical.visible ? scrollView.ScrollBar.vertical.width : 0)
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 1
height: 1
color: "#e5e5e5"
}
} // sectionDelegate

View file

@ -0,0 +1,136 @@
import QtQuick 2.4
import QtQuick.Controls
import QtQuick.Layouts 1.1
import QtQuick.Dialogs
import QtQuick.Window 2.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
Item {
id: sidePanelDelegate
objectName: "SidePanelItemDelegate"
property int iconSizeSide: Kirigami.Units.iconSizes.smallMedium
property string itemText: ""
property string itemIcon: ""
property string executableString: ""
property bool executeProgram: false
property alias textLabel: label
//text: itemText
//icon: itemIcon
width: label.implicitWidth + Kirigami.Units.largeSpacing*2
//Layout.preferredWidth: label.implicitWidth
height: 33
KeyNavigation.backtab: findPrevious();
KeyNavigation.tab: findNext();
function findItem() {
for(var i = 1; i < parent.visibleChildren.length-1; i++) {
if(sidePanelDelegate == parent.visibleChildren[i])
return i;
}
return -1;
}
function findPrevious() {
var i = findItem()-1;
if(i < 1) {
return root.m_searchField;
}
if(parent.visibleChildren[i].objectName == "SidePanelItemSeparator") {
i--;
}
return parent.visibleChildren[i];
}
function findNext() {
var i = findItem()+1;
if(i >= parent.visibleChildren.length-1) {
return root.m_shutDownButton;
}
if(parent.visibleChildren[i].objectName == "SidePanelItemSeparator") {
i++;
}
return parent.visibleChildren[i];
}
Keys.onPressed: event => {
if(event.key == Qt.Key_Return) {
sidePanelMouseArea.clicked(null);
} else if(event.key == Qt.Key_Up) {
//console.log(findPrevious());
findPrevious().focus = true;
} else if(event.key == Qt.Key_Down) {
//console.log(findNext());
findNext().focus = true;
} else if(event.key == Qt.Key_Left) {
var pos = parent.mapToItem(mainFocusScope, sidePanelDelegate.x, sidePanelDelegate.y);
var obj = mainFocusScope.childAt(Kirigami.Units.smallSpacing*10, pos.y);
if(obj.objectName == "") {
obj = root.m_recents;
}
obj.focus = true;
}
}
//For some reason this is the only thing that prevents a width reduction bug, despite it being UB in QML
/*anchors.left: parent.left;
anchors.right: parent.right;*/
KSvg.FrameSvgItem {
id: itemFrame
z: -1
opacity: sidePanelMouseArea.containsMouse || parent.focus
anchors.fill: parent
imagePath: Qt.resolvedUrl("svgs/sidebaritem.svg")
prefix: "menuitem"
}
PlasmaComponents.Label {
id: label
wrapMode: Text.NoWrap
//elide: Text.ElideRight
anchors.left: parent.left
anchors.leftMargin: Kirigami.Units.smallSpacing * 2
anchors.verticalCenter: sidePanelDelegate.verticalCenter
anchors.verticalCenterOffset: -1
style: Text.Sunken
styleColor: "transparent"
text: itemText
}
onFocusChanged: {
/*if(focus) {
root.m_sidebarIcon.source = itemIcon;
} else {
root.m_sidebarIcon.source = "";
}*/
if(root.m_delayTimer.running) root.m_delayTimer.restart();
else root.m_delayTimer.start();
}
MouseArea {
id: sidePanelMouseArea
enabled: !root.hoverDisabled
acceptedButtons: Qt.LeftButton
onEntered: {
sidePanelDelegate.focus = true;
}
onExited: {
sidePanelDelegate.focus = false;
}
onClicked: {
root.visible = false;
if(executeProgram)
executable.exec(executableString);
else {
Qt.openUrlExternally(executableString);
}
}
hoverEnabled: true
anchors.fill: parent
}
}

View file

@ -0,0 +1,55 @@
import QtQuick 2.4
import QtQuick.Controls
import QtQuick.Layouts 1.1
import QtQuick.Dialogs
import QtQuick.Window 2.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
Item {
id: sidePanelDelegate
objectName: "SidePanelItemSeparator"
//icon: itemIcon
function findItem() {
for(var i = 0; i < parent.visibleChildren.length; i++) {
if(sidePanelDelegate == parent.visibleChildren[i])
return i;
}
return -1;
}
function updateVisibility() {
if(!visible) visible = true;
var i = findItem();
var pred = i-1;
var succ = i+1;
if(pred <= 0 || succ >= parent.visibleChildren.length) {
sidePanelDelegate.visible = false;
return;
}
if(parent.visibleChildren[pred].objectName !== "SidePanelItemDelegate" || parent.visibleChildren[succ].objectName !== "SidePanelItemDelegate") {
sidePanelDelegate.visible = false;
return;
}
sidePanelDelegate.visible = true;
}
//For some reason this is the only thing that prevents a width reduction bug, despite it being UB in QML
/*anchors.left: parent.left;
anchors.right: parent.right;*/
height: 2;
KSvg.SvgItem {
id: itemFrame
anchors.fill: parent
anchors.leftMargin: Kirigami.Units.smallSpacing*2;
anchors.rightMargin: Kirigami.Units.smallSpacing*2;
svg: separatorSvg
elementId: "separator-line"
}
}

View file

@ -0,0 +1,75 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts 1.1
import QtQuick.Dialogs
import QtQuick.Window 2.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.private.kicker 0.1 as Kicker
import org.kde.coreaddons as KCoreAddons // kuser
import org.kde.plasma.private.shell 2.0
import org.kde.kwindowsystem 1.0
import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.private.quicklaunch 1.0
import org.kde.kirigami 2.13 as Kirigami
import org.kde.kquickcontrolsaddons 2.0 as KQuickAddons
import org.kde.kwindowsystem 1.0
import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons
/*
* This is the Dialog that displays the Start menu orb when it sticks out
* of the panel. In principle, it works in almost the same way as the
* Start menu user icon, in fact most of the code is directly copied from
* there.
*
* Compared to the popup avatar, this dialog window should NOT have any
* visualParent set, as it causes inexplicable behavior where the orb
* moves away during certain interactions. I have no idea why it does that.
*
* This has been developed only for the bottom/south oriented panel, and
* other orientations should receive support when I begin giving pretty
* much *everything* else support for other orientations.
*
*/
PlasmaCore.Dialog {
id: iconUser
flags: Qt.WindowStaysOnTopHint | Qt.Popup | Qt.WindowTransparentForInput
location: "Floating"
//outputOnly: true // Simplifies things, prevents accidental misclicks when clicking close to the orb.
// Positions are defined later when the plasmoid has been fully loaded, to prevent undefined behavior.
x: 0
y: 0
// Input masks won't be applied correctly when compositing is disabled unless I do this. WHY?
onYChanged: {
Plasmoid.setTransparentWindow();
}
onXChanged: {
Plasmoid.setTransparentWindow();
}
onVisibleChanged: {
if(visible) {
orbTimer.start(); // Delayed initialization, again, for what reason?
}
}
backgroundHints: PlasmaCore.Types.NoBackground // Prevents a dialog SVG background from being drawn.
visible: root.visible && stickOutOrb
opacity: iconUser.visible // To prevent even more NP-hard unpredictable behavior and visual glitches.
// The actual orb button, this dialog window is just a container for it.
mainItem: FloatingOrb {
id: floatingOrbIcon
}
}

View file

@ -0,0 +1,181 @@
/*
* SPDX-FileCopyrightText: 2013 Aurélien Gâteau <agateau@kde.org>
* SPDX-FileCopyrightText: 2013-2015 Eike Hein <hein@kde.org>
* SPDX-FileCopyrightText: 2017 Ivan Cukic <ivan.cukic@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.pragma library
function fillActionMenu(i18n, actionMenu, actionList, favoriteModel, favoriteId) {
// Accessing actionList can be a costly operation, so we don't
// access it until we need the menu.
var actions = createFavoriteActions(i18n, favoriteModel, favoriteId);
if (actions) {
if (actionList && actionList.length > 0) {
var actionListCopy = Array.from(actionList);
var separator = { "type": "separator" };
actionListCopy.push(separator);
// actionList = actions.concat(actionList); // this crashes Qt O.o
actionListCopy.push.apply(actionListCopy, actions);
actionList = actionListCopy;
} else {
actionList = actions;
}
}
actionMenu.actionList = actionList;
}
function createFavoriteActions(i18n, favoriteModel, favoriteId) {
if (!favoriteModel || !favoriteModel.enabled || !favoriteId) {
return null;
}
if (favoriteModel.activities === undefined ||
favoriteModel.activities.runningActivities.length <= 1) {
var action = {};
if (favoriteModel.isFavorite(favoriteId)) {
action.text = i18n("Unpin from Start Menu");
//action.icon = "pin";
action.actionId = "_kicker_favorite_remove";
} else if (favoriteModel.maxFavorites === -1 || favoriteModel.count < favoriteModel.maxFavorites) {
action.text = i18n("Pin to Start Menu");
//action.icon = "bookmark-new";
action.actionId = "_kicker_favorite_add";
} else {
return null;
}
action.actionArgument = { favoriteModel: favoriteModel, favoriteId: favoriteId };
return [action];
} else {
var actions = [];
var linkedActivities = favoriteModel.linkedActivitiesFor(favoriteId);
var activities = favoriteModel.activities.runningActivities;
// Adding the item to link/unlink to all activities
var linkedToAllActivities =
!(linkedActivities.indexOf(":global") === -1);
actions.push({
text : i18n("On All Activities"),
checkable : true,
actionId : linkedToAllActivities ?
"_kicker_favorite_remove_from_activity" :
"_kicker_favorite_set_to_activity",
checked : linkedToAllActivities,
actionArgument : {
favoriteModel: favoriteModel,
favoriteId: favoriteId,
favoriteActivity: ""
}
});
// Adding items for each activity separately
var addActivityItem = function(activityId, activityName) {
var linkedToThisActivity =
!(linkedActivities.indexOf(activityId) === -1);
actions.push({
text : activityName,
checkable : true,
checked : linkedToThisActivity && !linkedToAllActivities,
actionId :
// If we are on all activities, and the user clicks just one
// specific activity, unlink from everything else
linkedToAllActivities ? "_kicker_favorite_set_to_activity" :
// If we are linked to the current activity, just unlink from
// that single one
linkedToThisActivity ? "_kicker_favorite_remove_from_activity" :
// Otherwise, link to this activity, but do not unlink from
// other ones
"_kicker_favorite_add_to_activity",
actionArgument : {
favoriteModel : favoriteModel,
favoriteId : favoriteId,
favoriteActivity : activityId
}
});
};
// Adding the item to link/unlink to the current activity
addActivityItem(favoriteModel.activities.currentActivity, i18n("On the Current Activity"));
actions.push({
type: "separator",
actionId: "_kicker_favorite_separator"
});
// Adding the items for each activity
activities.forEach(function(activityId) {
addActivityItem(activityId, favoriteModel.activityNameForId(activityId));
});
return [{
text : i18n("Show in Favorites"),
icon : "favorite",
subActions : actions
}];
}
}
function triggerAction(model, index, actionId, actionArgument) {
function startsWith(txt, needle) {
return txt.substr(0, needle.length) === needle;
}
if (startsWith(actionId, "_kicker_favorite_")) {
handleFavoriteAction(actionId, actionArgument);
return;
}
var closeRequested = model.trigger(index, actionId, actionArgument);
if (closeRequested) {
return true;
}
return false;
}
function handleFavoriteAction(actionId, actionArgument) {
var favoriteId = actionArgument.favoriteId;
var favoriteModel = actionArgument.favoriteModel;
if (favoriteModel === null || favoriteId === null) {
return null;
}
if (actionId === "_kicker_favorite_remove") {
favoriteModel.removeFavorite(favoriteId);
} else if (actionId === "_kicker_favorite_add") {
favoriteModel.addFavorite(favoriteId);
} else if (actionId === "_kicker_favorite_remove_from_activity") {
favoriteModel.removeFavoriteFrom(favoriteId, actionArgument.favoriteActivity);
} else if (actionId === "_kicker_favorite_add_to_activity") {
favoriteModel.addFavoriteTo(favoriteId, actionArgument.favoriteActivity);
} else if (actionId === "_kicker_favorite_set_to_activity") {
favoriteModel.setFavoriteOn(favoriteId, actionArgument.favoriteActivity);
}
}

View file

@ -0,0 +1,291 @@
/***************************************************************************
* Copyright (C) 2014-2015 by Eike Hein <hein@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 2.0
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.private.kicker 0.1 as Kicker
import org.kde.kquickcontrolsaddons as KQuickControlsAddons
import org.kde.kwindowsystem
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
import org.kde.plasma.plasma5support as Plasma5Support
PlasmoidItem {
id: kicker
signal reset
anchors.fill: parent
property bool isDash: false
property Item dragSource: null
switchWidth: isDash || !fullRepresentationItem ? 0 :fullRepresentationItem.Layout.minimumWidth
switchHeight: isDash || !fullRepresentationItem ? 0 :fullRepresentationItem.Layout.minimumHeight
property QtObject globalFavorites: rootModel.favoritesModel
property QtObject systemFavorites: rootModel.systemFavoritesModel
// I see what you did here
//property bool compositingEnabled: kwindowsystem.compositingActive
property bool compositingEnabled: KWindowSystem.isPlatformX11 ? KX11Extras.compositingActive : true
preferredRepresentation: isDash ? menuRepresentation : null
compactRepresentation: isDash ? null : compactRepresentation
fullRepresentation: isDash ? compactRepresentation : menuRepresentation
Plasmoid.constraintHints: Plasmoid.CanFillArea
// Runs KMenuEdit.
function action_menuedit() {
processRunner.runMenuEditor();
}
function action_taskman() {
menu_executable.exec("ksysguard");
}
Component {
id: compactRepresentation
CompactRepresentation {}
}
Component {
id: menuRepresentation
MenuRepresentation { }
}
// Used to run separate programs through this plasmoid.
Plasma5Support.DataSource {
id: menu_executable
engine: "executable"
connectedSources: []
onNewData: {
var exitCode = data["exit code"]
var exitStatus = data["exit status"]
var stdout = data["stdout"]
var stderr = data["stderr"]
exited(sourceName, exitCode, exitStatus, stdout, stderr)
disconnectSource(sourceName)
}
function exec(cmd) {
if (cmd) {
connectSource(cmd)
}
}
signal exited(string cmd, int exitCode, int exitStatus, string stdout, string stderr)
}
Kicker.WindowSystem {
id: windowSystem
}
Kicker.RecentUsageModel {
id: recentUsageModel
favoritesModel: globalFavorites
ordering: 0
shownItems: Kicker.RecentUsageModel.OnlyApps
}
Kicker.RunnerModel {
id: runnerModel
appletInterface: kicker
//query: kickoff.searchField ? kickoff.searchField.text : ""
//deleteWhenEmpty: false
favoritesModel: rootModel.favoritesModel
//runners: ["Dictionary","services","calculator","shell","org.kde.windowedwidgets","org.kde.datetime","baloosearch","locations","unitconverter","bookmarks", "krunner_services", "krunner_systemsettings", "krunner_sessions", "krunner_powerdevil"]
/*runners: {
const results = ["Dictionary","services","calculator","shell","org.kde.windowedwidgets","org.kde.datetime","baloosearch","locations","unitconverter","bookmarks", "krunner_services", "krunner_systemsettings", "krunner_sessions", "krunner_powerdevil"];
if (Plasmoid.configuration.useExtraRunners) {
results.push(...Plasmoid.configuration.extraRunners);
}
return results;
}*/
mergeResults: true
}
//KWindowSystem { id: kwindowsystem } // Used for detecting compositing changes.
Kicker.RootModel {
id: rootModel
autoPopulate: false
appNameFormat: Plasmoid.configuration.appNameFormat
flat: true
sorted: true
showSeparators: false
appletInterface: kicker
paginate: false
pageSize: Plasmoid.configuration.numberColumns * Plasmoid.configuration.numberRows
showAllApps: false
showAllAppsCategorized: false
showRecentApps: true
showRecentDocs: false
//showRecentContacts: false
showPowerSession: false
onFavoritesModelChanged: {
if ("initForClient" in favoritesModel) {
favoritesModel.initForClient("org.kde.plasma.kicker.favorites.instance-" + plasmoid.id)
if (!Plasmoid.configuration.favoritesPortedToKAstats) {
favoritesModel.portOldFavorites(Plasmoid.configuration.favoriteApps);
Plasmoid.configuration.favoritesPortedToKAstats = true;
}
} else {
favoritesModel.favorites = Plasmoid.configuration.favoriteApps;
}
favoritesModel.maxFavorites = pageSize;
}
onSystemFavoritesModelChanged: {
systemFavoritesModel.enabled = false;
systemFavoritesModel.favorites = Plasmoid.configuration.favoriteSystemActions;
systemFavoritesModel.maxFavorites = 8;
}
Component.onCompleted: {
if ("initForClient" in favoritesModel) {
favoritesModel.initForClient("org.kde.plasma.kicker.favorites.instance-" + plasmoid.id)
if (!Plasmoid.configuration.favoritesPortedToKAstats) {
favoritesModel.portOldFavorites(Plasmoid.configuration.favoriteApps);
Plasmoid.configuration.favoritesPortedToKAstats = true;
}
} else {
favoritesModel.favorites = Plasmoid.configuration.favoriteApps;
}
favoritesModel.maxFavorites = pageSize;
rootModel.refresh();
}
}
Connections {
target: globalFavorites
function onFavoritesChanged() {
Plasmoid.configuration.favoriteApps = target.favorites;
}
}
Connections {
target: systemFavorites
function onFavoritesChanged() {
Plasmoid.configuration.favoriteSystemActions = target.favorites;
}
}
Connections {
target: Plasmoid.configuration
function onFavoriteAppsChanged() {
globalFavorites.favorites = Plasmoid.configuration.favoriteApps;
}
function onFavoriteSystemActionsChanged() {
systemFavorites.favorites = Plasmoid.configuration.favoriteSystemActions;
}
}
Kicker.DragHelper {
id: dragHelper
}
Kicker.ProcessRunner {
id: processRunner
}
// SVGs
KSvg.FrameSvgItem {
id : highlightItemSvg
visible: false
imagePath: Qt.resolvedUrl("svgs/menuitem.svg")
prefix: "hover"
}
KSvg.FrameSvgItem {
id : panelSvg
visible: false
imagePath: "widgets/panel-background"
}
KSvg.Svg {
id: arrowsSvg
imagePath: Qt.resolvedUrl("svgs/arrows.svgz")
size: "16x16"
}
KSvg.Svg {
id: separatorSvg
imagePath: Qt.resolvedUrl("svgs/sidebarseparator.svg")
}
KSvg.Svg {
id: lockScreenSvg
imagePath: Qt.resolvedUrl("svgs/system-lock-screen.svg")
}
PlasmaComponents.Label {
id: toolTipDelegate
width: contentWidth
height: contentHeight
property Item toolTip
text: (toolTip != null) ? toolTip.text : ""
}
function resetDragSource() {
dragSource = null;
}
function enableHideOnWindowDeactivate() {
kicker.hideOnWindowDeactivate = true;
}
Plasmoid.contextualActions: [
PlasmaCore.Action {
text: i18n("Edit Applications...")
icon.name: "application-menu"
onTriggered: menu_executable.exec("kmenuedit");
},
PlasmaCore.Action {
text: i18n("Task Manager")
icon.name: "ksysguardd"
onTriggered: menu_executable.exec("ksysguard");
}
]
Component.onCompleted: {
if (Plasmoid.hasOwnProperty("activationTogglesExpanded")) {
Plasmoid.activationTogglesExpanded = !kicker.isDash
}
windowSystem.focusIn.connect(enableHideOnWindowDeactivate);
kicker.hideOnWindowDeactivate = true;
rootModel.refreshed.connect(reset);
dragHelper.dropped.connect(resetDragSource);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 141 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 41 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 115 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 64 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 38 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 115 KiB

View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
viewBox="0 0 32 32"
id="svg7"
sodipodi:docname="system-lock-screen.svg"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview9"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
showgrid="false"
inkscape:zoom="10.0625"
inkscape:cx="9.689441"
inkscape:cy="15.204969"
inkscape:window-width="1440"
inkscape:window-height="874"
inkscape:window-x="1600"
inkscape:window-y="150"
inkscape:window-maximized="1"
inkscape:current-layer="svg7"
inkscape:showpageshadow="2"
inkscape:deskcolor="#505050" />
<defs
id="defs3">
<style
type="text/css"
id="current-color-scheme">
.ColorScheme-Text {
color:#eff0f1;
}
</style>
</defs>
<path
class="ColorScheme-Text"
d="m 16,8 c -2.216,0 -4,1.784 -4,4 v 4 h -2 v 8 H 22 V 16 H 20 V 12 C 20,9.784 18.216,8 16,8 Z m 0,1 c 1.662,0 3,1.561 3,3.5 V 16 H 13 V 12.5 C 13,10.561 14.338,9 16,9 Z"
fill="currentColor"
id="light-lock"
sodipodi:nodetypes="ssccccccssssccss" />
<path
d="m 16,8 c -2.216,0 -4,1.784 -4,4 v 4 h -2 v 8 H 22 V 16 H 20 V 12 C 20,9.784 18.216,8 16,8 Z m 0,1 c 1.662,0 3,1.561 3,3.5 V 16 H 13 V 12.5 C 13,10.561 14.338,9 16,9 Z"
fill="currentColor"
id="dark-lock"
sodipodi:nodetypes="ssccccccssssccss"
style="fill:#202020;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,27 @@
{
"KPlugin": {
"Authors": [
{
"Email": "wackyideas[at]disroot.org",
"Name": "WackyIdeas"
}
],
"Category": "Application Launchers",
"Dependencies": [
],
"Description": "Open application menu",
"EnabledByDefault": true,
"Icon": "start-here-kde",
"Id": "io.gitgud.wackyideas.SevenStart",
"License": "GPL v2+",
"Name": "Seven Start",
"Version": "1.0"
},
"X-Plasma-API-Minimum-Version": "6.0",
"KPackageStructure": "Plasma/Applet",
"X-Plasma-API": "declarativeappletscript",
"X-Plasma-MainScript": "ui/main.qml",
"X-Plasma-Provides": [
"org.kde.plasma.launchermenu"
]
}

View file

@ -0,0 +1,25 @@
{
"KPlugin": {
"Authors": [
{
"Email": "wackyideas[at]disroot.org",
"Name": "WackyIdeas"
}
],
"Category": "Application Launchers",
"Dependencies": [
],
"Description": "Open application menu",
"EnabledByDefault": true,
"Icon": "start-here-kde",
"Id": "io.gitgud.wackyideas.SevenStart",
"License": "GPL v2+",
"Name": "Seven Start",
"Version": "1.0"
},
"X-Plasma-API-Minimum-Version": "6.0",
"KPackageStructure": "Plasma/Applet",
"X-Plasma-Provides": [
"org.kde.plasma.launchermenu"
]
}

View file

@ -0,0 +1,4 @@
# Digital Clock Lite KDE Applet
org.kde.plasma.digitalclocklite
Fork from org.kde.plasma.digitalclock, with a feature to choose the size of the clock

View file

@ -0,0 +1,71 @@
/*
* Copyright 2013 Bhushan Shah <bhush94@gmail.com>
* Copyright 2015 Martin Klapetek <mklapetek@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.0
import QtQml 2.2
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.configuration 2.0
import org.kde.plasma.workspace.calendar 2.0 as PlasmaCalendar
ConfigModel {
id: configModel
ConfigCategory {
name: i18n("Appearance")
icon: "preferences-desktop-color"
source: "configAppearance.qml"
}
ConfigCategory {
name: i18n("Calendar")
icon: "preferences-system-time"
source: "configCalendar.qml"
}
ConfigCategory {
name: i18n("Time Zones")
icon: "preferences-desktop-locale"
source: "configTimeZones.qml"
}
property QtObject eventPluginsManager: PlasmaCalendar.EventPluginsManager {
Component.onCompleted: {
populateEnabledPluginsList(Plasmoid.configuration.enabledCalendarPlugins);
}
}
property Instantiator __eventPlugins: Instantiator {
model: eventPluginsManager.model
delegate: ConfigCategory {
name: model.display
icon: { console.log(model.decoration); return model.decoration }
source: model.configUi
includeMargins: false
visible: Plasmoid.configuration.enabledCalendarPlugins.indexOf(model.pluginId) > -1
}
onObjectAdded: (index, object) => configModel.appendCategory(object)
onObjectRemoved: (index, object) => configModel.removeCategory(object)
//onObjectAdded: configModel.appendCategory(object)
//onObjectRemoved: configModel.removeCategory(object)
}
}

View file

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name=""/>
<group name="Appearance">
<entry name="showLocalTimezone" type="Bool">
<label>Whether the timezone should be displayed when the clock is showing the local timezone.</label>
<default>false</default>
</entry>
<entry name="showSeconds" type="Bool">
<label>Whether seconds should be shown in the clock.</label>
<default>false</default>
</entry>
<entry name="showDate" type="Bool">
<label>Whether the date should be shown next to the clock.</label>
<default>false</default>
</entry>
<entry name="dateFormat" type="string">
<label>The date format to display. Options are: shortDate, longDate or isoDate.</label>
<default>shortDate</default>
</entry>
<entry name="fontFamily" type="string">
<label>Font family. e.g "arial". The system font is used if this is not set.</label>
<default></default>
</entry>
<entry name="fontSize" type="Int">
<label>Font size described in pixels.</label>
<default>9</default>
</entry>
<entry name="boldText" type="Bool">
<label>Sets the font to bold.</label>
<default>false</default>
</entry>
<entry name="italicText" type="Bool">
<label>Sets the font to italic.</label>
<default>false</default>
</entry>
<entry name="timeFormat" type="string">
<default>default</default>
</entry>
<entry name="selectedTimeZones" type="StringList">
<label>A list of the time zones available on mouse wheel. Requires wheelChangesTimezone to be true. Format is "Europe/London". Special entry "Local" indicates system time zone.</label>
<default>Local</default>
</entry>
<entry name="lastSelectedTimezone" type="String">
<label>When multiple time zones are configured, this is the one shown on widget restore.</label>
<default>Local</default>
</entry>
<entry name="wheelChangesTimezone" type="Bool">
<label>Whether the mouse wheel switches between the timezones configured in selectedTimeZones.</label>
<default>false</default>
</entry>
<entry name="displayTimezoneAsCode" type="Bool">
<label>Whether the timezone is displayed as a code i.e. "GMT" or full text i.e. "London".</label>
<default>true</default>
</entry>
<entry name="showWeekNumbers" type="Bool">
<label>Whether the calendar should show week numbers.</label>
<default>false</default>
</entry>
<entry name="firstDayOfWeek" type="Int">
<label>Force the calendar to use a specific week day as first day of a week. -1 means follow user locale, 0 is Sunday, 1 is Monday, etc.</label>
<default>-1</default>
</entry>
<entry name="use24hFormat" type="UInt">
<label>Force the clock to use 12/24 hour time, instead of following the user locale.</label>
<default>1</default>
</entry>
<entry name="enabledCalendarPlugins" type="StringList">
<label>A list of plugins where additional calendar event data can be sourced.</label>
<default></default>
</entry>
<entry name="pin" type="Bool">
<label>Whether the popup should remain open when another window is activated</label>
<default>false</default>
</entry>
<entry name="checkUpdateStartup" type="Bool">
<label>Notify for update on startup</label>
<default>true</default>
</entry>
</group>
</kcfg>

View file

@ -0,0 +1,586 @@
/*
* Copyright 2013 Sebastian Kügler <sebas@kde.org>
* Copyright 2015 Martin Klapetek <mklapetek@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.15
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.workspace.calendar 2.0 as PlasmaCalendar
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.ksvg 1.0 as KSvg
import org.kde.kirigami 2.20 as Kirigami
import Qt5Compat.GraphicalEffects
PlasmaCore.Dialog {
id: calendar
objectName: "popupWindow"
flags: Qt.WindowStaysOnTopHint
location: PlasmaCore.Types.Floating //To make the dialog float in the corner of the screen
hideOnWindowDeactivate: !plasmoid.configuration.pin
//Used for reading margin values
KSvg.FrameSvgItem {
id : panelSvg
visible: false
imagePath: "widgets/panel-background"
}
KSvg.FrameSvgItem {
id : dialogSvg
visible: false
imagePath: "solid/dialogs/background"
}
onVisibleChanged: {
popupPosition();
monthView.resetToToday();
holidaysList.model = null;
holidaysList.model = monthView.daysModel.eventsForDate(monthView.currentDate);
}
onHeightChanged: {
popupPosition();
}
property int flyoutMargin: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing/2
onWidthChanged: {
popupPosition();
}
function popupPosition() {
var pos = root.mapToGlobal(root.x, root.y);
var availScreen = Plasmoid.containment.availableScreenRect;
x = pos.x - calendar.width / 2 + root.width / 2
y = pos.y - calendar.height;
if(x <= 0) x += flyoutMargin;
if(x + calendar.width >= availScreen.width) {
x = availScreen.width - calendar.width - flyoutMargin;
}
if(y <= 0) y += flyoutMargin;
if(y + calendar.height >= availScreen.height) {
y = availScreen.height - calendar.height - flyoutMargin;
}
}
readonly property bool showAgenda: Plasmoid.configuration.enabledCalendarPlugins.length > 0
property int _minimumWidth: 336//(showAgenda ? agendaViewWidth : Kirigami.Units.largeSpacing) + monthViewWidth
property int _minimumHeight: 247
readonly property int agendaViewWidth: _minimumHeight
readonly property int monthViewWidth: monthView.showWeekNumbers ? Math.round(_minimumHeight * 1.25) : Math.round(_minimumHeight * 1.125)
property int boxWidth: (agendaViewWidth + monthViewWidth - ((showAgenda ? 3 : 4) * spacing)) / 2
property int spacing: Kirigami.Units.largeSpacing
property alias borderWidth: monthView.borderWidth
property alias monthView: monthView
property bool debug: false
property bool isExpanded: Plasmoid.expanded
onIsExpandedChanged: {
// clear all the selections when the plasmoid is showing/hiding
monthView.resetToToday();
}
FocusScope {
Kirigami.Theme.colorSet: Kirigami.Theme.View
Kirigami.Theme.inherit: false
Layout.minimumWidth: _minimumWidth
Layout.minimumHeight: _minimumHeight
Layout.maximumWidth: _minimumWidth
Layout.maximumHeight: _minimumHeight
Layout.preferredWidth: _minimumWidth
Layout.preferredHeight: _minimumHeight
//colorGroup: PlasmaCore.Theme.ToolTipColorGroup
anchors.fill: parent
//This is the long date that appears on top of the dialog, pressing on it will set the calendar to the current day.
ColumnLayout {
anchors {
top: parent.top
left: parent.left
right: parent.right
bottom: plasmoidFooter.top
topMargin: dialogSvg.margins.top + Kirigami.Units.mediumSpacing*2
leftMargin: dialogSvg.margins.left + Kirigami.Units.mediumSpacing*2
bottomMargin: Kirigami.Units.mediumSpacing*2
rightMargin: dialogSvg.margins.right + Kirigami.Units.mediumSpacing*2
}
PlasmaExtras.Heading {
id: longDateLabel
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
/*anchors {
left: parent.left
right: parent.right
top: parent.top
topMargin: Kirigami.Units.smallSpacing*2
}*/
width: paintedWidth
horizontalAlignment: Text.AlignHCenter
text: agenda.todayDateString("dddd") + ", " + Qt.locale().standaloneMonthName(monthView.today.getMonth()) + agenda.todayDateString(" dd") + ", " + agenda.todayDateString("yyyy")
color: "#0066cc" //heading_ma.containsPress ? "#90e7ff" : (heading_ma.containsMouse ? "#b6ffff" : Kirigami.Theme.textColor)
font.underline: heading_ma.containsMouse
level: 5
MouseArea {
id: heading_ma
anchors.fill: parent
hoverEnabled: true
onClicked: monthView.resetToToday()
cursorShape: Qt.PointingHandCursor
z: 5
}
}
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 0
//The calendar itself, on the left side of the dialog
Item {
id: cal
Layout.preferredWidth: 168
Layout.preferredHeight: 150
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Layout.topMargin: Kirigami.Units.largeSpacing + Kirigami.Units.mediumSpacing
CustomMonthView {
id: monthView
today: root.tzDate
showWeekNumbers: Plasmoid.configuration.showWeekNumbers
firstDayOfWeek: Plasmoid.configuration.firstDayOfWeek
anchors.fill: parent
}
}
Item {
id: testRect
visible: !calendar.showAgenda
Layout.fillWidth: true
Layout.fillHeight: true
Layout.bottomMargin: Kirigami.Units.mediumSpacing
Clock {
id: clockWidget
//anchors.fill: parent
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenterOffset: Kirigami.Units.largeSpacing
anchors.verticalCenterOffset: -Kirigami.Units.largeSpacing
width: 128
height: 128
//Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
//Layout.leftMargin: Kirigami.Units.largeSpacing
}
DropShadow {
anchors.fill: clockWidget
horizontalOffset: 2
verticalOffset: 2
radius: 3.0
color: "#10000000"
source: clockWidget
}
Text {
id: clockTime
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing*2
//anchors.bottomMargin: Kirigami.Units.mediumSpacing
horizontalAlignment: Text.AlignHCenter
text: Qt.formatTime(clockWidget.currentDate, main.use24hFormat ? "hh:mm:ss" : "h:mm:ss AP")
}
}
//This is the side panel that appears on the right of the calendar view, showing holidays, events, reminders, etc. in a list.
//Replaces the large graphical clock on the right on Windows 7's equivalent panel.
Item {
id: agenda
visible: calendar.showAgenda
Layout.fillWidth: true
Layout.fillHeight: true
Layout.leftMargin: Kirigami.Units.largeSpacing
function todayDateString(format) {
return Qt.formatDate(monthView.today, format);
}
function dateString(format) {
return Qt.formatDate(monthView.currentDate, format);
}
function formatDateWithoutYear(date) {
// Unfortunatelly Qt overrides ECMA's Date.toLocaleDateString(),
// which is able to return locale-specific date-and-month-only date
// formats, with its dumb version that only supports Qt::DateFormat
// enum subset. So to get a day-and-month-only date format string we
// must resort to this magic and hope there are no locales that use
// other separators...
var format = Qt.locale().dateFormat(Locale.ShortFormat).replace(/[./ ]*Y{2,4}[./ ]*/i, '');
return Qt.formatDate(date, format);
}
Connections {
target: monthView
function onCurrentDateChanged() {
// Apparently this is needed because this is a simple QList being
// returned and if the list for the current day has 1 event and the
// user clicks some other date which also has 1 event, QML sees the
// sizes match and does not update the labels with the content.
// Resetting the model to null first clears it and then correct data
// are displayed.
holidaysList.model = null;
holidaysList.model = monthView.daysModel.eventsForDate(monthView.currentDate);
}
}
Connections {
target: monthView.daysModel
function onAgendaUpdated(updatedDate) {
// Checks if the dates are the same, comparing the date objects
// directly won't work and this does a simple integer subtracting
// so should be fastest. One of the JS weirdness.
if (updatedDate - monthView.currentDate === 0) {
holidaysList.model = null;
holidaysList.model = monthView.daysModel.eventsForDate(monthView.currentDate);
}
}
}
Connections {
target: Plasmoid.configuration
function onEnabledCalendarPluginsChanged() {
PlasmaCalendar.EventPluginsManager.enabledPlugins = Plasmoid.configuration.enabledCalendarPlugins;
eventPluginsManager.enabledPlugins = Plasmoid.configuration.enabledCalendarPlugins;
//console.log(PlasmaCalendar.EventPluginsManager.enabledPlugins);
//console.log(eventPluginsManager.enabledPlugins);
}
}
/*Binding {
target: Plasmoid
property: "hideOnWindowDeactivate"
value: !Plasmoid.configuration.pin
}*/
TextMetrics {
id: dateLabelMetrics
// Date/time are arbitrary values with all parts being two-digit
readonly property string timeString: Qt.formatTime(new Date(2000, 12, 12, 12, 12, 12, 12))
readonly property string dateString: agenda.formatDateWithoutYear(new Date(2000, 12, 12, 12, 12, 12))
font: Kirigami.Theme.defaultFont
text: timeString.length > dateString.length ? timeString : dateString
}
PlasmaComponents3.ScrollView {
id: holidaysView
anchors {
fill: parent
topMargin: Kirigami.Units.largeSpacing
}
ListView {
id: holidaysList
spacing: Kirigami.Units.smallSpacing
highlightFollowsCurrentItem: false
highlight: Item {
opacity: 0
}
delegate: PlasmaComponents3.ItemDelegate {
id: eventItem
width: parent.width
height: eventGrid.height
property bool hasTime: {
// Explicitly all-day event
if (modelData.isAllDay) {
return false;
}
// Multi-day event which does not start or end today (so
// is all-day from today's point of view)
if (modelData.startDateTime - monthView.currentDate < 0 &&
modelData.endDateTime - monthView.currentDate > 86400000) { // 24hrs in ms
return false;
}
// Non-explicit all-day event
var startIsMidnight = modelData.startDateTime.getHours() == 0
&& modelData.startDateTime.getMinutes() == 0;
var endIsMidnight = modelData.endDateTime.getHours() == 0
&& modelData.endDateTime.getMinutes() == 0;
var sameDay = modelData.startDateTime.getDate() == modelData.endDateTime.getDate()
&& modelData.startDateTime.getDay() == modelData.endDateTime.getDay()
if (startIsMidnight && endIsMidnight && sameDay) {
return false
}
return true;
}
PlasmaCore.ToolTipArea {
//anchors.fill: parent
width: parent.width
height: eventGrid.height
active: eventTitle.truncated || eventDescription.truncated
mainText: active ? eventTitle.text : ""
subText: active ? eventDescription.text : ""
textFormat: Text.RichText
GridLayout {
id: eventGrid
columns: 3
rows: 2
rowSpacing: 0
columnSpacing: Kirigami.Units.smallSpacing
width: parent.width
Rectangle {
id: eventColor
Layout.row: 0
Layout.column: 0
Layout.rowSpan: 2
Layout.fillHeight: true
color: modelData.eventColor
width: 3
visible: modelData.eventColor !== ""
}
PlasmaComponents3.Label {
id: startTimeLabel
readonly property bool startsToday: modelData.startDateTime - monthView.currentDate >= 0
readonly property bool startedYesterdayLessThan12HoursAgo: modelData.startDateTime - monthView.currentDate >= -43200000 //12hrs in ms
Layout.row: 0
Layout.column: 1
Layout.minimumWidth: dateLabelMetrics.width
text: startsToday || startedYesterdayLessThan12HoursAgo
? Qt.formatTime(modelData.startDateTime)
: agenda.formatDateWithoutYear(modelData.startDateTime)
horizontalAlignment: Qt.AlignRight
visible: eventItem.hasTime
}
PlasmaComponents3.Label {
id: endTimeLabel
readonly property bool endsToday: modelData.endDateTime - monthView.currentDate <= 86400000 // 24hrs in ms
readonly property bool endsTomorrowInLessThan12Hours: modelData.endDateTime - monthView.currentDate <= 86400000 + 43200000 // 36hrs in ms
Layout.row: 1
Layout.column: 1
Layout.minimumWidth: dateLabelMetrics.width
text: endsToday || endsTomorrowInLessThan12Hours
? Qt.formatTime(modelData.endDateTime)
: agenda.formatDateWithoutYear(modelData.endDateTime)
horizontalAlignment: Qt.AlignRight
enabled: false
visible: eventItem.hasTime
}
PlasmaComponents3.Label {
id: eventTitle
readonly property bool wrap: eventDescription.text === ""
Layout.row: 0
Layout.rowSpan: wrap ? 2 : 1
Layout.column: 2
Layout.fillWidth: true
elide: Text.ElideRight
text: modelData.title
verticalAlignment: Text.AlignVCenter
maximumLineCount: 2
wrapMode: wrap ? Text.Wrap : Text.NoWrap
}
TextEdit {
id: descriptionHelper
visible: false
text: modelData.description
textFormat: Text.RichText
}
PlasmaComponents3.Label {
id: eventDescription
Layout.row: 1
Layout.column: 2
Layout.fillWidth: true
elide: Text.ElideRight
text: descriptionHelper.getText(0, descriptionHelper.length)
verticalAlignment: Text.AlignVCenter
enabled: false
textFormat: Text.PlainText
maximumLineCount: 1
visible: text !== ""
}
}
}
}
section.property: "eventType"
section.delegate:
PlasmaExtras.Heading {
width: holidaysList.width
bottomPadding: Kirigami.Units.smallSpacing
level: 5
elide: Text.ElideRight
text: section
font.weight: Font.Bold
}
}
}
PlasmaExtras.Heading {
anchors.fill: holidaysView
horizontalAlignment: Text.AlignHCenter
//anchors.rightMargin: Kirigami.Units.largeSpacing
text: monthView.isToday(monthView.currentDate) ? i18n("No events for today") + "\n"
: i18n("No events for this day") + "\n";
level: 5
opacity: 0.8
visible: holidaysList.count == 0
}
}
}
}
Rectangle {
id: plasmoidFooter
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
leftMargin: dialogSvg.margins.left
rightMargin: dialogSvg.margins.right
bottomMargin: dialogSvg.margins.bottom
}
//visible: container.appletHasFooter
height: 40 + Kirigami.Units.smallSpacing / 2 //+ container.footerHeight + Kirigami.Units.smallSpacing
//height: trayHeading.height + container.headingHeight + (container.headingHeight === 0 ? 0 : Kirigami.Units.smallSpacing/2)
color: "#f1f5fb"
Rectangle {
id: plasmoidFooterBorder
anchors {
top: parent.top
left: parent.left
right: parent.right
}
gradient: Gradient {
GradientStop { position: 0.0; color: "#ccd9ea" }
GradientStop { position: 1.0; color: "#f1f5fb" }
}
height: Kirigami.Units.smallSpacing
}
PlasmaExtras.Heading {
id: settingsLink
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
horizontalAlignment: Text.AlignHCenter
text: "Change date and time settings..."
color: "#0066cc" //heading_ma.containsPress ? "#90e7ff" : (heading_ma.containsMouse ? "#b6ffff" : Kirigami.Theme.textColor)
font.underline: link_ma.containsMouse
level: 5
MouseArea {
id: link_ma
anchors.fill: parent
hoverEnabled: true
onClicked: Plasmoid.internalAction("configure").trigger()
cursorShape: Qt.PointingHandCursor
z: 5
}
}
z: -9999
}
ToolButton {
id: pinButton
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.rightMargin: dialogSvg.margins.right + Kirigami.Units.mediumSpacing + 2
anchors.bottomMargin: dialogSvg.margins.bottom + Kirigami.Units.mediumSpacing + 2
width: Kirigami.Units.iconSizes.small+1;
height: Kirigami.Units.iconSizes.small;
checkable: true
checked: Plasmoid.configuration.pin
onClicked: (mouse) => {
Plasmoid.configuration.pin = !Plasmoid.configuration.pin;
}
buttonIcon: "pin"
z: 9999
}
}
Component.onCompleted: {
calendar.backgroundHints = 2; //Sets the background type to 'Solid' in order to make use of the alternative dialog style.
//The same is done to the system tray, giving the two plasmoids a consistent look and feel.
popupPosition();
//x = pos.x;
//y = pos.y;
}
}

View file

@ -0,0 +1,117 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts 1.1
import QtQuick.Window 2.15
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.plasmoid 2.0
import org.kde.ksvg 1.0 as KSvg
import org.kde.kirigami 2.5 as Kirigami // For Settings.tabletMode
Item {
id: clockItem
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
property date currentDate: {
// get the time for the given timezone from the dataengine
var now = dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["DateTime"];
// get current UTC time
var msUTC = now.getTime() + (now.getTimezoneOffset() * 60000);
// add the dataengine TZ offset to it
var currentTime = new Date(msUTC + (dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Offset"] * 1000));
return currentTime
}
KSvg.SvgItem {
id: clockface
svg: clockSvg
elementId: "clockface"
anchors.fill: parent
/*anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter*/
}
// Rects
Rectangle {
id: secondHand
color: "#bf546770"
width: 1
height: 65
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 15
anchors.horizontalCenterOffset: 1
antialiasing: true
transform: Rotation {
origin.x: 0
origin.y: 18
angle: 360 * (currentDate.getSeconds() / 60) + 180
}
}
Rectangle {
id: minuteHand
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0; color: "#df5c6c74" }
GradientStop { position: 0.5; color: "#ef5c6c74" }
GradientStop { position: 1; color: "#df5c6c74" }
}
radius: 1
//color: "#bf546770"
width: 2
height: 47
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: minuteHand.height/2
anchors.horizontalCenterOffset: currentDate.getMinutes() > 45 || currentDate.getMinutes() <= 15 ? 2 : 0
antialiasing: true
transform: Rotation {
origin.x: 0
origin.y: 0
angle: 360 * (currentDate.getMinutes() / 60) + 180
}
}
Rectangle {
id: hourHand
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0; color: "#df5c6c74" }
GradientStop { position: 0.5; color: "#ef5c6c74" }
GradientStop { position: 1; color: "#df5c6c74" }
}
radius: 1
//color: "#bf546770"
width: 2
height: 36
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: hourHand.height/2
anchors.horizontalCenterOffset: 1
antialiasing: true
transform: Rotation {
origin.x: 0
origin.y: 0
angle: 360 * ((currentDate.getHours() % 12) / 12 + currentDate.getMinutes() / (12*60)) + 180
}
}
KSvg.SvgItem {
id: clockdot
svg: clockSvg
elementId: "clockdot"
width: 5
height: 5
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
KSvg.SvgItem {
id: clockshine
svg: clockSvg
elementId: "clockshine"
anchors.fill: parent
}
}

View file

@ -0,0 +1,379 @@
/*
SPDX-FileCopyrightText: 2013 Heena Mahour <heena393@gmail.com>
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
SPDX-FileCopyrightText: 2015 Kai Uwe Broulik <kde@privat.broulik.de>
SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.15
import QtQuick.Layouts 1.1
import org.kde.plasma.workspace.calendar 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.kirigami as Kirigami
Item { // TODO KF6 switch to Item
id: root
//anchors.fill: parent // TODO KF6 don't use anchors
//enabled: false
/**
* Currently selected month name.
* \property string MonthView::selectedMonth
*/
property alias selectedMonth: calendarBackend.monthName
/**
* Currently selected month year.
* \property int MonthView::selectedYear
*/
property alias selectedYear: calendarBackend.year
/**
* The start day of a week.
* \property int MonthView::firstDayOfWeek
* \sa Calendar::firstDayOfWeek
*/
property alias firstDayOfWeek: calendarBackend.firstDayOfWeek
property QtObject date
property date currentDate
property date showDate: new Date()
property int borderWidth: 1
property real borderOpacity: 0.4
property int columns: calendarBackend.days
property int rows: calendarBackend.weeks
property Item selectedItem
property int week;
property int firstDay: new Date(showDate.getFullYear(), showDate.getMonth(), 1).getDay()
property alias today: calendarBackend.today
property bool showWeekNumbers: false
property bool showCustomHeader: false
/**
* SwipeView currentIndex needed for binding a TabBar to the MonthView.
*/
property int currentIndex: swipeView.currentIndex
property alias cellHeight: mainDaysCalendar.cellHeight
property QtObject daysModel: calendarBackend.daysModel
function isToday(date) {
return date.toDateString() === new Date().toDateString();
}
function eventDate(yearNumber,monthNumber,dayNumber) {
const d = new Date(yearNumber, monthNumber-1, dayNumber);
return Qt.formatDate(d, "dddd dd MMM yyyy");
}
/**
* Move calendar to month view showing today's date.
*/
function resetToToday() {
calendarBackend.resetToToday();
root.currentDate = root.today;
swipeView.currentIndex = 0;
}
function updateYearOverview() {
const date = calendarBackend.displayedDate;
const day = date.getDate();
const year = date.getFullYear();
for (let i = 0, j = monthModel.count; i < j; ++i) {
monthModel.setProperty(i, "yearNumber", year);
}
}
function updateDecadeOverview() {
const date = calendarBackend.displayedDate;
const day = date.getDate();
const month = date.getMonth() + 1;
const year = date.getFullYear();
const decade = year - year % 10;
for (let i = 0, j = yearModel.count; i < j; ++i) {
const label = decade - 1 + i;
yearModel.setProperty(i, "yearNumber", label);
yearModel.setProperty(i, "label", label);
}
}
/**
* Possible calendar views
*/
enum CalendarView {
DayView,
MonthView,
YearView
}
/**
* Go to the next month/year/decade depending on the current
* calendar view displayed.
*/
function nextView() {
if (swipeView.currentIndex === 0) {
calendarBackend.nextMonth();
} else if (swipeView.currentIndex === 1) {
calendarBackend.nextYear();
} else if (swipeView.currentIndex === 2) {
calendarBackend.nextDecade();
}
}
/**
* Go to the previous month/year/decade depending on the current
* calendar view displayed.
*/
function previousView() {
if (swipeView.currentIndex === 0) {
calendarBackend.previousMonth();
} else if (swipeView.currentIndex === 1) {
calendarBackend.previousYear();
} else if (swipeView.currentIndex === 2) {
calendarBackend.previousDecade();
}
}
/**
* \return CalendarView
*/
readonly property var calendarViewDisplayed: {
if (swipeView.currentIndex === 0) {
return MonthView.CalendarView.DayView;
} else if (swipeView.currentIndex === 1) {
return MonthView.CalendarView.MonthView;
} else if (swipeView.currentIndex === 2) {
return MonthView.CalendarView.YearView;
}
}
/**
* Show month view.
*/
function showMonthView() {
swipeView.currentIndex = 0;
}
/**
* Show year view.
*/
function showYearView() {
swipeView.currentIndex = 1;
}
/**
* Show month view.
*/
function showDecadeView() {
swipeView.currentIndex = 2;
}
//property QtObject eventPluginsManager: EventPluginsManager {}
Calendar {
id: calendarBackend
days: 7
weeks: 6
firstDayOfWeek: Qt.locale().firstDayOfWeek
today: root.today
Component.onCompleted: {
daysModel.setPluginsManager(eventPluginsManager);
}
onYearChanged: {
updateYearOverview()
updateDecadeOverview()
}
}
ListModel {
id: monthModel
Component.onCompleted: {
for (let i = 0; i < 12; ++i) {
append({
label: Qt.locale(Qt.locale().uiLanguages[0]).standaloneMonthName(i, Locale.LongFormat),
monthNumber: i + 1,
yearNumber: 2050,
isCurrent: true
})
}
updateYearOverview()
}
}
ListModel {
id: yearModel
Component.onCompleted: {
for (let i = 0; i < 12; ++i) {
append({
label: 2050, // this value will be overwritten, but it set the type of the property to int
yearNumber: 2050,
isCurrent: (i > 0 && i < 11) // first and last year are outside the decade
})
}
updateDecadeOverview()
}
}
ColumnLayout {
id: viewHeader
visible: !showCustomHeader
// Make sure the height of the invisible item is zero, otherwise anchoring to the item will
// include the height even if it is invisible.
height: !visible ? 0 : implicitHeight
width: parent.width
anchors {
top: parent.top
}
RowLayout {
spacing: 0
ToolButton {
id: previousButton
flat: true
buttonIcon: (previousButton.containsMouse && !previousButton.containsPress) ? "left-active" : "left"
onClicked: root.previousView()
Layout.leftMargin: Kirigami.Units.smallSpacing
}
PlasmaExtras.Heading {
id: heading
text: {
if(swipeView.currentIndex == 0)
return i18ndc("libplasma5", "Format: month year", "%1, %2", root.selectedMonth, root.selectedYear.toString());
else if(swipeView.currentIndex == 1)
return i18ndc("libplasma5", "Format: year", "%1", root.selectedYear.toString());
else if(swipeView.currentIndex == 2) {
var decade = root.selectedYear - root.selectedYear % 10;
var nextDecade = decade+9;
return i18ndc("libplasma5", "Format: year-year", "%1-%2", decade.toString(), nextDecade.toString());
}
}
level: 5
font.capitalization: Font.Capitalize
horizontalAlignment: Text.AlignHCenter
Layout.fillWidth: true
color: heading_ma.containsMouse && !heading_ma.containsPress ? "#0066cc" : Kirigami.Theme.textColor
MouseArea {
id: heading_ma
anchors.fill: parent
hoverEnabled: true
onClicked: if(swipeView.currentIndex != 2) swipeView.currentIndex++;
//cursorShape: Qt.PointingHandCursor
z: 5
}
}
ToolButton {
id: nextButton
flat: true
buttonIcon: (nextButton.containsMouse && !nextButton.containsPress) ? "right-active" : "right"
onClicked: root.nextView()
}
}
}
PlasmaComponents3.SwipeView {
id: swipeView
anchors {
top: viewHeader.bottom
topMargin: Kirigami.Units.mediumSpacing
left: parent.left
right: parent.right
bottom: parent.bottom
}
clip: true
onCurrentIndexChanged: if (currentIndex > 1) {
updateDecadeOverview();
}
// MonthView
DaysCalendar {
id: mainDaysCalendar
columns: calendarBackend.days
rows: calendarBackend.weeks
showWeekNumbers: root.showWeekNumbers
headerModel: calendarBackend.days
gridModel: calendarBackend.daysModel
dateMatchingPrecision: Calendar.MatchYearMonthAndDay
onActivated: (index, date) => {
const rowNumber = Math.floor(index / columns);
week = 1 + calendarBackend.weeksModel[rowNumber];
root.currentDate = new Date(date.yearNumber, date.monthNumber - 1, date.dayNumber)
}
onScrollUp: root.nextView()
onScrollDown: root.previousView()
}
// YearView
DaysCalendar {
columns: 4
rows: 3
dateMatchingPrecision: Calendar.MatchYearAndMonth
gridModel: monthModel
onActivated: (index, date, item) => {
calendarBackend.goToMonth(date.monthNumber);
swipeView.currentIndex = 0;
}
onScrollUp: calendarBackend.nextYear()
onScrollDown: calendarBackend.previousYear()
}
// DecadeView
DaysCalendar {
readonly property int decade: {
const year = calendarBackend.displayedDate.getFullYear()
return year - year % 10
}
columns: 4
rows: 3
dateMatchingPrecision: Calendar.MatchYear
gridModel: yearModel
onActivated: (index, date, item) => {
calendarBackend.goToYear(date.yearNumber);
swipeView.currentIndex = 1;
}
onScrollUp: calendarBackend.nextDecade()
onScrollDown: calendarBackend.previousDecade()
}
}
Component.onCompleted: {
root.currentDate = calendarBackend.today
}
}

View file

@ -0,0 +1,113 @@
/*
SPDX-FileCopyrightText: 2013 Heena Mahour <heena393@gmail.com>
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
SPDX-FileCopyrightText: 2015 Kai Uwe Broulik <kde@privat.broulik.de>
SPDX-FileCopyrightText: 2021 Jan Blackquill <uhhadd@gmail.com>
SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.2
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.extras 2.0 as PlasmaExtras
import QtQml.Models 2.15
import Qt5Compat.GraphicalEffects
import org.kde.kirigami as Kirigami
import org.kde.ksvg as KSvg
import org.kde.plasma.workspace.calendar 2.0
PlasmaComponents3.AbstractButton {
id: dayStyle
hoverEnabled: true
property var dayModel: null
signal activated
readonly property date thisDate: new Date(yearNumber, typeof monthNumber !== "undefined" ? monthNumber - 1 : 0, typeof dayNumber !== "undefined" ? dayNumber : 1)
readonly property bool today: {
const today = root.today;
let result = true;
if (dateMatchingPrecision >= Calendar.MatchYear) {
result = result && today.getFullYear() === thisDate.getFullYear()
}
if (dateMatchingPrecision >= Calendar.MatchYearAndMonth) {
result = result && today.getMonth() === thisDate.getMonth()
}
if (dateMatchingPrecision >= Calendar.MatchYearMonthAndDay) {
result = result && today.getDate() === thisDate.getDate()
}
return result
}
readonly property bool selected: {
const current = root.currentDate;
let result = true;
if (dateMatchingPrecision >= Calendar.MatchYear) {
result = result && current.getFullYear() === thisDate.getFullYear()
}
if (dateMatchingPrecision >= Calendar.MatchYearAndMonth) {
result = result && current.getMonth() === thisDate.getMonth()
}
if (dateMatchingPrecision >= Calendar.MatchYearMonthAndDay) {
result = result && current.getDate() === thisDate.getDate()
}
return result
}
PlasmaExtras.Highlight {
id: todayRect
anchors.fill: parent
hovered: true
opacity: {
if (today && !dayStyle.hovered && !selected) {
return 0;
} else if (selected) {
return 0.8;
} else if (dayStyle.pressed) {
return 0.3;
} else if (dayStyle.hovered) {
return 0.6;
}
return 0;
}
z: -1;
}
Rectangle {
id: currentDayRect
anchors.fill: parent
visible: today
radius: 2
border.color: "#0066cc"
color: "transparent"
}
contentItem: PlasmaExtras.Heading {
id: label
horizontalAlignment: dateMatchingPrecision != Calendar.MatchYearMonthAndDay ? Text.AlignHCenter: Text.AlignRight
verticalAlignment: Text.AlignVCenter
bottomPadding: dateMatchingPrecision != Calendar.MatchYearMonthAndDay ? 0 : 1
rightPadding: dateMatchingPrecision != Calendar.MatchYearMonthAndDay ? 0 : Kirigami.Units.smallSpacing+1
wrapMode: Text.NoWrap
elide: Text.ElideRight
font.bold: calendar.showAgenda && model.eventCount !== undefined && model.eventCount > 0
fontSizeMode: Text.Fit
color: today || (!dayStyle.pressed && dayStyle.hovered) ? "#0066cc" : Kirigami.Theme.textColor
text: {
if(model.label) {
if(dateMatchingPrecision == Calendar.MatchYearAndMonth) return model.label.substring(0, 3);
return model.label;
}
return dayNumber;
}
opacity: isCurrent ? 1.0 : 0.5
level: 5
}
}

View file

@ -0,0 +1,152 @@
/*
SPDX-FileCopyrightText: 2013 Heena Mahour <heena393@gmail.com>
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
SPDX-FileCopyrightText: 2015, 2016 Kai Uwe Broulik <kde@privat.broulik.de>
SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls as QQC1
import org.kde.plasma.workspace.calendar 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
Item {
id: daysCalendar
signal headerClicked
signal scrollUp
signal scrollDown
signal activated(int index, var date, var item)
// so it forwards it to the delegate which then emits activated with all the necessary data
signal activateHighlightedItem
readonly property int gridColumns: showWeekNumbers ? calendarGrid.columns + 1 : calendarGrid.columns
property int rows
property int columns
property bool showWeekNumbers
// how precise date matching should be, 3 = day+month+year, 2 = month+year, 1 = just year
property int dateMatchingPrecision
property alias headerModel: days.model
property alias gridModel: repeater.model
// Take the calendar width, subtract the inner and outer spacings and divide by number of columns (==days in week)
readonly property int cellWidth: Math.floor((swipeView.width - (daysCalendar.columns + 1) * root.borderWidth) / (daysCalendar.columns + (showWeekNumbers ? 1 : 0)))
// Take the calendar height, subtract the inner spacings and divide by number of rows (root.weeks + one row for day names)
readonly property int cellHeight: Math.floor((swipeView.height - heading.height - calendarGrid.rows * root.borderWidth) / calendarGrid.rows)
KSvg.Svg {
id: calendarSvg
imagePath: "widgets/calendar"
}
Column {
id: weeksColumn
visible: showWeekNumbers
anchors {
top: parent.top
left: parent.left
bottom: parent.bottom
// The borderWidth needs to be counted twice here because it goes
// in fact through two lines - the topmost one (the outer edge)
// and then the one below weekday strings
topMargin: daysCalendar.cellHeight + root.borderWidth + root.borderWidth
}
spacing: root.borderWidth
Repeater {
model: showWeekNumbers ? calendarBackend.weeksModel : []
PlasmaComponents3.Label {
height: daysCalendar.cellHeight
width: daysCalendar.cellWidth
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
opacity: 0.4
text: modelData
font.pixelSize: Math.max(Kirigami.Theme.smallestFont.pixelSize, daysCalendar.cellHeight / 3)
}
}
}
Rectangle {
visible: days.count > 0
anchors.top: calendarGrid.top
anchors.topMargin: daysCalendar.cellHeight
height: 1
anchors.left: calendarGrid.left
anchors.right: calendarGrid.right
color: "#f5f5f5"
}
Grid {
id: calendarGrid
anchors {
top: parent.top
right: parent.right
rightMargin: root.borderWidth
bottom: parent.bottom
bottomMargin: root.borderWidth
}
columns: daysCalendar.columns
rows: daysCalendar.rows + (daysCalendar.headerModel ? 1 : 0)
spacing: 0//root.borderWidth
columnSpacing: parent.squareCell ? (daysCalendar.width - daysCalendar.columns * (daysCalendar.cellWidth - root.borderWidth)) / daysCalendar.columns : root.borderWidth
property bool containsEventItems: false // FIXME
property bool containsTodoItems: false // FIXME
Repeater {
id: days
PlasmaComponents3.Label {
width: daysCalendar.cellWidth
height: daysCalendar.cellHeight
text: (Qt.locale(Qt.locale().uiLanguages[0]).dayName(((calendarBackend.firstDayOfWeek + index) % days.count), Locale.ShortFormat)).substring(0, 2);
font.pixelSize: Math.max(Kirigami.Theme.smallestFont.pixelSize, daysCalendar.cellHeight / 3)
//opacity: 0.8
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
fontSizeMode: Text.HorizontalFit
}
}
Repeater {
id: repeater
DayDelegate {
id: delegate
width: daysCalendar.cellWidth
height: daysCalendar.cellHeight
dayModel: repeater.model
Connections {
target: daysCalendar
function onActivateHighlightedItem(delegate) {
if (delegate.containsMouse) {
delegate.clicked(null)
}
}
}
onClicked: {
daysCalendar.activated(index, model, delegate);
}
}
}
}
}

View file

@ -0,0 +1,788 @@
/*
* Copyright 2013 Heena Mahour <heena393@gmail.com>
* Copyright 2013 Sebastian Kügler <sebas@kde.org>
* Copyright 2013 Martin Klapetek <mklapetek@kde.org>
* Copyright 2014 David Edmundson <davidedmundson@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.6
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.plasmoid
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.private.digitalclock 1.0
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
Item {
id: main
property string timeFormat
property date currentTime
property bool showSeconds: Plasmoid.configuration.showSeconds
property bool showLocalTimezone: Plasmoid.configuration.showLocalTimezone
property bool showDate: Plasmoid.configuration.showDate
property int dateFormat: {
if (Plasmoid.configuration.dateFormat === "longDate") {
return Qt.SystemLocaleLongDate;
} else if (Plasmoid.configuration.dateFormat === "isoDate") {
return Qt.ISODate;
}
return Qt.SystemLocaleShortDate;
}
property string lastSelectedTimezone: Plasmoid.configuration.lastSelectedTimezone
property bool displayTimezoneAsCode: Plasmoid.configuration.displayTimezoneAsCode
property int use24hFormat: Plasmoid.configuration.use24hFormat
property string lastDate: ""
property int tzOffset
// This is the index in the list of user selected timezones
property int tzIndex: 0
// if the date/timezone cannot be fit with the smallest font to its designated space
readonly property bool oneLineMode: Plasmoid.formFactor == PlasmaCore.Types.Horizontal &&
main.height <= 2 * Kirigami.Theme.smallestFont.pixelSize &&
(main.showDate || timezoneLabel.visible)
property QtObject dashWindow: null
function getCurrentTime(): date {
const data = dataSource.data[Plasmoid.configuration.lastSelectedTimezone];
// The order of signal propagation is unspecified, so we might get
// here before the dataSource has updated. Alternatively, a buggy
// configuration view might set lastSelectedTimezone to a new time
// zone before applying the new list, or it may just be set to
// something invalid in the config file.
if (data === undefined) {
return new Date();
}
// get the time for the given time zone from the dataengine
const now = data["DateTime"];
// get current UTC time
const msUTC = now.getTime() + (now.getTimezoneOffset() * 60000);
// add the dataengine TZ offset to it
const currentTime = new Date(msUTC + (data["Offset"] * 1000));
return currentTime;
}
onDateFormatChanged: {
setupLabels();
}
onDisplayTimezoneAsCodeChanged: { setupLabels(); }
onStateChanged: { setupLabels(); }
onLastSelectedTimezoneChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
onShowSecondsChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
onShowLocalTimezoneChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
onShowDateChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
onUse24hFormatChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
Connections {
target: Plasmoid.configuration
function onSelectedTimeZonesChanged() {
// If the currently selected timezone was removed,
// default to the first one in the list
var lastSelectedTimezone = Plasmoid.configuration.lastSelectedTimezone;
if (Plasmoid.configuration.selectedTimeZones.indexOf(lastSelectedTimezone) == -1) {
Plasmoid.configuration.lastSelectedTimezone = Plasmoid.configuration.selectedTimeZones[0];
}
setupLabels();
setTimezoneIndex();
}
}
states: [
State {
name: "horizontalPanel"
when: Plasmoid.formFactor == PlasmaCore.Types.Horizontal && !main.oneLineMode
PropertyChanges {
target: main
Layout.fillHeight: true
Layout.fillWidth: false
Layout.minimumWidth: contentItem.width + 2
Layout.maximumWidth: Layout.minimumWidth
}
PropertyChanges {
target: contentItem
height: timeLabel.height + (main.showDate || timezoneLabel.visible ? 0.8 * timeLabel.height : 0)
width: Math.max(labelsGrid.width, timezoneLabel.paintedWidth, dateLabel.paintedWidth)
}
PropertyChanges {
target: labelsGrid
rows: main.showDate ? 1 : 2
}
AnchorChanges {
target: labelsGrid
anchors.horizontalCenter: contentItem.horizontalCenter
}
PropertyChanges {
target: timeLabel
height: sizehelper.height
//width: sizehelper.contentWidth
font.pointSize: Math.min(Plasmoid.configuration.fontSize || Kirigami.Theme.defaultFont.pointSize, Math.round(timeLabel.height * 72 / 96))
}
PropertyChanges {
target: timezoneLabel
//height: main.showDate ? 0.7 * timeLabel.height : 0.8 * timeLabel.height
//width: main.showDate ? timezoneLabel.paintedWidth : timeLabel.width
font.pointSize: Math.min(Plasmoid.configuration.fontSize || Kirigami.Theme.defaultFont.pointSize, Math.round(timezoneLabel.height * 72 / 96))
}
PropertyChanges {
target: dateLabel
height: 0.8 * timeLabel.height
width: dateLabel.paintedWidth
font.pointSize: Math.min(Plasmoid.configuration.fontSize || Kirigami.Theme.defaultFont.pointSize, Math.round(dateLabel.height * 72 / 96))
}
AnchorChanges {
target: dateLabel
anchors.top: labelsGrid.bottom
anchors.horizontalCenter: labelsGrid.horizontalCenter
}
PropertyChanges {
target: sizehelper
/*
* The value 0.71 was picked by testing to give the clock the right
* size (aligned with tray icons).
* Value 0.56 seems to be chosen rather arbitrary as well such that
* the time label is slightly larger than the date or timezone label
* and still fits well into the panel with all the applied margins.
*/
height: Math.min(main.showDate || timezoneLabel.visible ? main.height * 0.56 : main.height * 0.71,
3 * Kirigami.Theme.defaultFont.pixelSize)
font.pixelSize: sizehelper.height
}
},
State {
name: "horizontalPanelSmall"
when: Plasmoid.formFactor == PlasmaCore.Types.Horizontal && main.oneLineMode
PropertyChanges {
target: main
Layout.fillHeight: true
Layout.fillWidth: false
Layout.minimumWidth: contentItem.width
Layout.maximumWidth: Layout.minimumWidth
}
PropertyChanges {
target: contentItem
height: sizehelper.height
width: dateLabel.width + dateLabel.anchors.rightMargin + labelsGrid.width
}
AnchorChanges {
target: labelsGrid
anchors.right: contentItem.right
}
PropertyChanges {
target: dateLabel
height: timeLabel.height
width: dateLabel.paintedWidth
anchors.rightMargin: labelsGrid.columnSpacing
fontSizeMode: Text.VerticalFit
}
AnchorChanges {
target: dateLabel
anchors.right: labelsGrid.left
anchors.verticalCenter: labelsGrid.verticalCenter
}
PropertyChanges {
target: timeLabel
height: sizehelper.height
width: sizehelper.contentWidth
fontSizeMode: Text.VerticalFit
}
PropertyChanges {
target: timezoneLabel
height: 0.7 * timeLabel.height
width: timezoneLabel.paintedWidth
fontSizeMode: Text.VerticalFit
horizontalAlignment: Text.AlignHCenter
}
PropertyChanges {
target: sizehelper
height: Math.min(main.height, 3 * Kirigami.Theme.defaultFont.pixelSize)
fontSizeMode: Text.VerticalFit
font.pixelSize: 3 * Kirigami.Theme.defaultFont.pixelSize
}
},
State {
name: "verticalPanel"
when: Plasmoid.formFactor == PlasmaCore.Types.Vertical
PropertyChanges {
target: main
Layout.fillHeight: false
Layout.fillWidth: true
Layout.maximumHeight: contentItem.height
Layout.minimumHeight: Layout.maximumHeight
}
PropertyChanges {
target: contentItem
height: main.showDate ? labelsGrid.height + dateLabel.height : labelsGrid.height
width: main.width
}
PropertyChanges {
target: labelsGrid
rows: 2
}
PropertyChanges {
target: timeLabel
height: sizehelper.contentHeight
width: main.width
fontSizeMode: Text.HorizontalFit
}
PropertyChanges {
target: timezoneLabel
height: Math.max(0.7 * timeLabel.height, minimumPixelSize)
width: main.width
fontSizeMode: Text.Fit
minimumPixelSize: dateLabel.minimumPixelSize
elide: Text.ElideRight
}
PropertyChanges {
target: dateLabel
// this can be marginal bigger than contentHeight because of the horizontal fit
height: Math.max(0.8 * timeLabel.height, minimumPixelSize)
width: main.width
fontSizeMode: Text.Fit
minimumPixelSize: Math.min(0.7 * Kirigami.Theme.smallestFont.pixelSize, timeLabel.height)
elide: Text.ElideRight
}
AnchorChanges {
target: dateLabel
anchors.top: labelsGrid.bottom
anchors.horizontalCenter: labelsGrid.horizontalCenter
}
PropertyChanges {
target: sizehelper
width: main.width
fontSizeMode: Text.HorizontalFit
font.pixelSize: 3 * Kirigami.Theme.defaultFont.pixelSize
}
},
State {
name: "other"
when: Plasmoid.formFactor != PlasmaCore.Types.Vertical && Plasmoid.formFactor != PlasmaCore.Types.Horizontal
PropertyChanges {
target: main
Layout.fillHeight: false
Layout.fillWidth: false
Layout.minimumWidth: Kirigami.Units.iconSizes.small * 3
Layout.minimumHeight: Kirigami.Units.iconSizes.small * 3
}
PropertyChanges {
target: contentItem
height: main.height
width: main.width
}
PropertyChanges {
target: labelsGrid
rows: 2
}
PropertyChanges {
target: timeLabel
height: sizehelper.height
width: main.width
fontSizeMode: Text.Fit
}
PropertyChanges {
target: timezoneLabel
height: 0.7 * timeLabel.height
width: main.width
fontSizeMode: Text.Fit
minimumPixelSize: 1
}
PropertyChanges {
target: dateLabel
height: 0.8 * timeLabel.height
width: Math.max(timeLabel.contentWidth, Kirigami.Units.iconSizes.small * 3)
fontSizeMode: Text.Fit
minimumPixelSize: 1
}
AnchorChanges {
target: dateLabel
anchors.top: labelsGrid.bottom
anchors.horizontalCenter: labelsGrid.horizontalCenter
}
PropertyChanges {
target: sizehelper
height: {
if (main.showDate) {
if (timezoneLabel.visible) {
return 0.4 * main.height
}
return 0.56 * main.height
} else if (timezoneLabel.visible) {
return 0.59 * main.height
}
return main.height
}
width: main.width
fontSizeMode: Text.Fit
font.pixelSize: 1024
}
}
]
Timer {
id: tooltipTimer
interval: 750
repeat: false
running: false
onTriggered: if(!dashWindow.visible) timeToolTip.showToolTip();
}
MouseArea {
id: mouseArea
property int wheelDelta: 0
hoverEnabled: true
anchors.fill: parent
onClicked: {
Plasmoid.expanded = !Plasmoid.expanded
dashWindow.visible = !dashWindow.visible;
if(dashWindow.visible) timeToolTip.hideImmediately();
}
onEntered: {
tooltipTimer.start();
}
onExited: {
tooltipTimer.stop();
timeToolTip.hideToolTip();
}
onWheel: {
if (!Plasmoid.configuration.wheelChangesTimezone) {
return;
}
var delta = wheel.angleDelta.y || wheel.angleDelta.x
var newIndex = main.tzIndex;
wheelDelta += delta;
// magic number 120 for common "one click"
// See: http://qt-project.org/doc/qt-5/qml-qtquick-wheelevent.html#angleDelta-prop
while (wheelDelta >= 120) {
wheelDelta -= 120;
newIndex--;
}
while (wheelDelta <= -120) {
wheelDelta += 120;
newIndex++;
}
if (newIndex >= Plasmoid.configuration.selectedTimeZones.length) {
newIndex = 0;
} else if (newIndex < 0) {
newIndex = Plasmoid.configuration.selectedTimeZones.length - 1;
}
if (newIndex != main.tzIndex) {
Plasmoid.configuration.lastSelectedTimezone = Plasmoid.configuration.selectedTimeZones[newIndex];
main.tzIndex = newIndex;
dataSource.dataChanged();
setupLabels();
}
}
PlasmaCore.ToolTipArea {
id: timeToolTip
mainText: {
var now = dataSource.data[plasmoid.configuration.lastSelectedTimezone]["DateTime"];
return Qt.formatDate(now, "dddd, MMMM dd, yyyy");
}
}
}
/*
* Visible elements
*
*/
//This FrameSvgItem uses a non-standard variant of the tabbar SVG file that includes a "pressed" state
KSvg.FrameSvgItem {
id: hoverIndicator
imagePath: Qt.resolvedUrl("svgs/tabbar.svgz")
visible: mouseArea.containsMouse || dashWindow.visible
anchors.fill: parent
anchors.leftMargin: -Kirigami.Units.smallSpacing
anchors.rightMargin: -Kirigami.Units.smallSpacing+2
z: -1
prefix: mouseArea.containsPress ? "pressed-tab" : "active-tab";
}
Item {
id: contentItem
anchors.verticalCenter: main.verticalCenter
Grid {
id: labelsGrid
rows: 1
horizontalItemAlignment: Grid.AlignHCenter
verticalItemAlignment: Grid.AlignVCenter
flow: Grid.TopToBottom
columnSpacing: Kirigami.Units.smallSpacing
Rectangle {
height: 0.8 * sizehelper.height
width: 1
visible: main.showDate && main.oneLineMode
color: Kirigami.Theme.textColor
opacity: 0.4
}
PlasmaComponents3.Label {
id: timeLabel
renderType: Text.NativeRendering
font {
family: Plasmoid.configuration.fontFamily || Kirigami.Theme.defaultFont.family
weight: Plasmoid.configuration.boldText ? Font.Bold : Kirigami.Theme.defaultFont.weight
italic: Plasmoid.configuration.italicText
pointSize: Plasmoid.configuration.fontSize || Kirigami.Theme.defaultFont.pointSize
hintingPreference: Font.PreferFullHinting
}
minimumPixelSize: 1
style: Text.Outline
styleColor: "transparent"
text: {
// get the time for the given timezone from the dataengine
var now = dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["DateTime"];
// get current UTC time
var msUTC = now.getTime() + (now.getTimezoneOffset() * 60000);
// add the dataengine TZ offset to it
var currentTime = new Date(msUTC + (dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Offset"] * 1000));
main.currentTime = currentTime;
var showTimezone = main.showLocalTimezone || (plasmoid.configuration.lastSelectedTimezone != "Local"
&& dataSource.data["Local"]["Timezone City"] != dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone City"]);
var timezoneString = "";
var timezoneResult = "";
if (showTimezone) {
timezoneString = Plasmoid.configuration.displayTimezoneAsCode ? dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone Abbreviation"]
: TimezonesI18n.i18nCity(dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone City"]);
timezoneResult = (main.showDate || main.oneLineMode) && Plasmoid.formFactor == PlasmaCore.Types.Horizontal ? timezoneString : timezoneString;
} else {
// this clears the label and that makes it hidden
timezoneResult = timezoneString;
}
return Qt.formatTime(currentTime, main.timeFormat) + (showTimezone ? (" " + timezoneResult) : "");
}
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
PlasmaComponents3.Label {
id: timezoneLabel
renderType: Text.NativeRendering
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
font.pixelSize: timeLabel.font.pixelSize
font.hintingPreference: Font.PreferFullHinting
minimumPixelSize: 1
style: Text.Outline
styleColor: "transparent"
visible: false
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
PlasmaComponents3.Label {
id: dateLabel
visible: main.showDate
renderType: Text.NativeRendering
font.family: timeLabel.font.family
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
font.pixelSize: timeLabel.font.pixelSize
font.hintingPreference: Font.PreferFullHinting
minimumPixelSize: 1
style: Text.Outline
styleColor: "transparent"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
/*
* end: Visible Elements
*
*/
PlasmaComponents3.Label {
id: sizehelper
font.family: timeLabel.font.family
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
minimumPixelSize: 1
visible: false
}
FontMetrics {
id: timeMetrics
font.family: timeLabel.font.family
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
}
// Qt's QLocale does not offer any modular time creating like Klocale did
// eg. no "gimme time with seconds" or "gimme time without seconds and with timezone".
// QLocale supports only two formats - Long and Short. Long is unusable in many situations
// and Short does not provide seconds. So if seconds are enabled, we need to add it here.
//
// What happens here is that it looks for the delimiter between "h" and "m", takes it
// and appends it after "mm" and then appends "ss" for the seconds.
function timeFormatCorrection(timeFormatString) {
var regexp = /(hh*)(.+)(mm)/i
var match = regexp.exec(timeFormatString);
var hours = match[1];
var delimiter = match[2];
var minutes = match[3]
var seconds = "ss";
var amPm = "AP";
var uses24hFormatByDefault = timeFormatString.toLowerCase().indexOf("ap") == -1;
// because QLocale is incredibly stupid and does not convert 12h/24h clock format
// when uppercase H is used for hours, needs to be h or hh, so toLowerCase()
var result = hours.toLowerCase() + delimiter + minutes;
if (main.showSeconds) {
result += delimiter + seconds;
}
// add "AM/PM" either if the setting is the default and locale uses it OR if the user unchecked "use 24h format"
if ((main.use24hFormat == Qt.PartiallyChecked && !uses24hFormatByDefault) || main.use24hFormat == Qt.Unchecked) {
result += " " + amPm;
}
main.timeFormat = result;
setupLabels();
}
function setupLabels() {
/*var showTimezone = main.showLocalTimezone || (plasmoid.configuration.lastSelectedTimezone != "Local"
&& dataSource.data["Local"]["Timezone City"] != dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone City"]);
var timezoneString = "";
if (showTimezone) {
timezoneString = Plasmoid.configuration.displayTimezoneAsCode ? dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone Abbreviation"]
: TimezonesI18n.i18nCity(dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone City"]);
timezoneLabel.text = (main.showDate || main.oneLineMode) && Plasmoid.formFactor == PlasmaCore.Types.Horizontal ? "(" + timezoneString + ")" : timezoneString;
} else {
// this clears the label and that makes it hidden
timezoneLabel.text = timezoneString;
}*/
if (main.showDate) {
dateLabel.text = Qt.formatDate(main.currentTime, main.dateFormat);
} else {
// clear it so it doesn't take space in the layout
dateLabel.text = "";
}
// find widest character between 0 and 9
var maximumWidthNumber = 0;
var maximumAdvanceWidth = 0;
for (var i = 0; i <= 9; i++) {
var advanceWidth = timeMetrics.advanceWidth(i);
if (advanceWidth > maximumAdvanceWidth) {
maximumAdvanceWidth = advanceWidth;
maximumWidthNumber = i;
}
}
// replace all placeholders with the widest number (two digits)
var format = main.timeFormat.replace(/(h+|m+|s+)/g, "" + maximumWidthNumber + maximumWidthNumber); // make sure maximumWidthNumber is formatted as string
// build the time string twice, once with an AM time and once with a PM time
var date = new Date(2000, 0, 1, 1, 0, 0);
var timeAm = Qt.formatTime(date, format);
var advanceWidthAm = timeMetrics.advanceWidth(timeAm);
date.setHours(13);
var timePm = Qt.formatTime(date, format);
var advanceWidthPm = timeMetrics.advanceWidth(timePm);
// set the sizehelper's text to the widest time string
if (advanceWidthAm > advanceWidthPm) {
sizehelper.text = timeAm;
} else {
sizehelper.text = timePm;
}
}
function dateTimeChanged()
{
var doCorrections = false;
if (main.showDate) {
// If the date has changed, force size recalculation, because the day name
// or the month name can now be longer/shorter, so we need to adjust applet size
var currentDate = Qt.formatDateTime(getCurrentTime(), "yyyy-mm-dd");
if (main.lastDate != currentDate) {
doCorrections = true;
main.lastDate = currentDate
}
}
var currentTZOffset = dataSource.data["Local"]["Offset"] / 60;
if (currentTZOffset != tzOffset) {
doCorrections = true;
tzOffset = currentTZOffset;
Date.timeZoneUpdated(); // inform the QML JS engine about TZ change
}
if (doCorrections) {
timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat));
}
}
function setTimezoneIndex() {
for (var i = 0; i < Plasmoid.configuration.selectedTimeZones.length; i++) {
if (Plasmoid.configuration.selectedTimeZones[i] == Plasmoid.configuration.lastSelectedTimezone) {
main.tzIndex = i;
break;
}
}
}
Component.onCompleted: {
root.initTimezones();
// Sort the timezones according to their offset
// Calling sort() directly on plasmoid.configuration.selectedTimeZones
// has no effect, so sort a copy and then assign the copy to it
var sortArray = Plasmoid.configuration.selectedTimeZones;
sortArray.sort(function(a, b) {
return dataSource.data[a]["Offset"] - dataSource.data[b]["Offset"];
});
Plasmoid.configuration.selectedTimeZones = sortArray;
setTimezoneIndex();
tzOffset = -(new Date().getTimezoneOffset());
dateTimeChanged();
timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat));
dataSource.onDataChanged.connect(dateTimeChanged);
dashWindow = Qt.createQmlObject("CalendarView {}", root);
}
}

View file

@ -0,0 +1,802 @@
/*
SPDX-FileCopyrightText: 2013 Heena Mahour <heena393@gmail.com>
SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
SPDX-FileCopyrightText: 2013 Martin Klapetek <mklapetek@kde.org>
SPDX-FileCopyrightText: 2014 David Edmundson <davidedmundson@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components 3.0 as Components
import org.kde.plasma.private.digitalclock 1.0
import org.kde.kirigami 2.20 as Kirigami
import org.kde.ksvg as KSvg
MouseArea {
id: main
objectName: "digital-clock-compactrepresentation"
hoverEnabled: true
property QtObject dashWindow: null
onClicked: {
Plasmoid.expanded = !Plasmoid.expanded
dashWindow.visible = !dashWindow.visible;
}
onEntered: {
tooltipTimer.start();
}
onExited: {
tooltipTimer.stop();
timeToolTip.hideToolTip();
}
Timer {
id: tooltipTimer
interval: 750
repeat: false
running: false
onTriggered: if(!dashWindow.visible) timeToolTip.showToolTip();
}
PlasmaCore.ToolTipArea {
id: timeToolTip
mainText: {
var now = dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["DateTime"];
return Qt.formatDate(now, "dddd, MMMM dd, yyyy");
}
/*mainItem: PlasmaExtras.Heading {
* level: 5
* elide: Text.ElideRight
* wrapMode: Text.Wrap
* text: {
* var now = dataSource.data[plasmoid.configuration.lastSelectedTimezone]["DateTime"];
* return Qt.formatDate(now, "dddd, MMMM yyyy");
}
textFormat: Text.PlainText
}*/
}
property string timeFormat
property string timeFormatWithSeconds
property bool showLocalTimezone: Plasmoid.configuration.showLocalTimezone
property bool showDate: Plasmoid.configuration.showDate
// This is quite convoluted in Qt 6:
// Qt.formatDate with locale only accepts Locale.FormatType as format type,
// no Qt.DateFormat (ISODate) and no format string.
// Locale.toString on the other hand only formats a date *with* time...
property var dateFormatter: {
if (Plasmoid.configuration.dateFormat === "custom") {
Plasmoid.configuration.customDateFormat; // create a binding dependency on this property.
return (d) => {
return Qt.locale().toString(d, Plasmoid.configuration.customDateFormat);
};
} else if (Plasmoid.configuration.dateFormat === "isoDate") {
return (d) => {
return Qt.formatDate(d, Qt.ISODate);
};
} else if (Plasmoid.configuration.dateFormat === "longDate") {
return (d) => {
return Qt.formatDate(d, Qt.locale(), Locale.LongFormat);
};
} else {
return (d) => {
return Qt.formatDate(d, Qt.locale(), Locale.ShortFormat);
};
}
}
property string lastSelectedTimezone: Plasmoid.configuration.lastSelectedTimezone
property int displayTimezoneFormat: Plasmoid.configuration.displayTimezoneFormat
property int use24hFormat: Plasmoid.configuration.use24hFormat
property string lastDate: ""
property int tzOffset
// This is the index in the list of user selected timezones
property int tzIndex: 0
// if showing the date and the time in one line or
// if the date/timezone cannot be fit with the smallest font to its designated space
property bool oneLineMode: {
if (Plasmoid.configuration.dateDisplayFormat === 1) {
// BesideTime
return true;
} else if (Plasmoid.configuration.dateDisplayFormat === 2) {
// BelowTime
return false;
} else {
// Adaptive
return Plasmoid.formFactor === PlasmaCore.Types.Horizontal &&
main.height <= 2 * Kirigami.Theme.smallFont.pixelSize &&
(main.showDate || timezoneLabel.visible);
}
}
property bool wasExpanded
property int wheelDelta: 0
Accessible.role: Accessible.Button
Accessible.onPressAction: main.clicked(null)
onDateFormatterChanged: {
setupLabels();
}
onDisplayTimezoneFormatChanged: { setupLabels(); }
onStateChanged: { setupLabels(); }
onLastSelectedTimezoneChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
onShowLocalTimezoneChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
onShowDateChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
onUse24hFormatChanged: { timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat)) }
Connections {
target: Plasmoid
function onContextualActionsAboutToShow() {
ClipboardMenu.secondsIncluded = (Plasmoid.configuration.showSeconds === 2);
ClipboardMenu.currentDate = main.getCurrentTime();
}
}
Connections {
target: Plasmoid.configuration
function onSelectedTimeZonesChanged() {
// If the currently selected timezone was removed,
// default to the first one in the list
const lastSelectedTimezone = Plasmoid.configuration.lastSelectedTimezone;
if (Plasmoid.configuration.selectedTimeZones.indexOf(lastSelectedTimezone) === -1) {
Plasmoid.configuration.lastSelectedTimezone = Plasmoid.configuration.selectedTimeZones[0];
}
setupLabels();
setTimezoneIndex();
}
}
function getCurrentTime() {
// get the time for the given timezone from the dataengine
var now = dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["DateTime"];
// get current UTC time
var msUTC = now.getTime() + (now.getTimezoneOffset() * 60000);
// add the dataengine TZ offset to it
var currentTime = new Date(msUTC + (dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Offset"] * 1000));
return currentTime;
}
function pointToPixel(pointSize) {
var pixelsPerInch = Screen.pixelDensity * 25.4
return Math.round(pointSize / 72 * pixelsPerInch)
}
states: [
State {
name: "horizontalPanel"
when: Plasmoid.formFactor === PlasmaCore.Types.Horizontal && !main.oneLineMode
PropertyChanges {
target: main
Layout.fillHeight: true
Layout.fillWidth: false
Layout.minimumWidth: contentItem.width
Layout.maximumWidth: Layout.minimumWidth
}
PropertyChanges {
target: contentItem
height: timeLabel.height + (main.showDate || timezoneLabel.visible ? 0.8 * timeLabel.height : 0)
width: Math.max(timeLabel.width + (main.showDate ? timezoneLabel.paintedWidth : 0),
timezoneLabel.paintedWidth, dateLabel.paintedWidth) + Kirigami.Units.largeSpacing
}
PropertyChanges {
target: labelsGrid
rows: main.showDate ? 1 : 2
}
AnchorChanges {
target: labelsGrid
anchors.horizontalCenter: contentItem.horizontalCenter
}
PropertyChanges {
target: timeLabel
height: sizehelper.height
width: timeLabel.paintedWidth
font.pixelSize: timeLabel.height
}
PropertyChanges {
target: timezoneLabel
height: main.showDate ? 0.7 * timeLabel.height : 0.8 * timeLabel.height
width: main.showDate ? timezoneLabel.paintedWidth : timeLabel.width
font.pixelSize: timezoneLabel.height
}
PropertyChanges {
target: dateLabel
height: 0.8 * timeLabel.height
width: dateLabel.paintedWidth
verticalAlignment: Text.AlignVCenter
font.pixelSize: dateLabel.height
}
AnchorChanges {
target: dateLabel
anchors.top: labelsGrid.bottom
anchors.horizontalCenter: labelsGrid.horizontalCenter
}
PropertyChanges {
target: sizehelper
/*
* The value 0.71 was picked by testing to give the clock the right
* size (aligned with tray icons).
* Value 0.56 seems to be chosen rather arbitrary as well such that
* the time label is slightly larger than the date or timezone label
* and still fits well into the panel with all the applied margins.
*/
height: Math.min(main.showDate || timezoneLabel.visible ? main.height * 0.56 : main.height * 0.71,
fontHelper.font.pixelSize)
font.pixelSize: sizehelper.height
}
},
State {
name: "oneLineDate"
// the one-line mode has no effect on a vertical panel because it would never fit
when: Plasmoid.formFactor !== PlasmaCore.Types.Vertical && main.oneLineMode
PropertyChanges {
target: main
Layout.fillHeight: true
Layout.fillWidth: false
Layout.minimumWidth: contentItem.width
Layout.maximumWidth: Layout.minimumWidth
}
PropertyChanges {
target: contentItem
height: sizehelper.height
width: dateLabel.width + dateLabel.anchors.rightMargin + labelsGrid.width
}
AnchorChanges {
target: labelsGrid
anchors.right: contentItem.right
}
PropertyChanges {
target: dateLabel
height: timeLabel.height
width: dateLabel.paintedWidth
font.pixelSize: 1024
verticalAlignment: Text.AlignVCenter
anchors.rightMargin: labelsGrid.columnSpacing
fontSizeMode: Text.VerticalFit
}
AnchorChanges {
target: dateLabel
anchors.right: labelsGrid.left
anchors.verticalCenter: labelsGrid.verticalCenter
}
PropertyChanges {
target: timeLabel
height: sizehelper.height
width: timeLabel.paintedWidth
fontSizeMode: Text.VerticalFit
}
PropertyChanges {
target: timezoneLabel
height: 0.7 * timeLabel.height
width: timezoneLabel.paintedWidth
fontSizeMode: Text.VerticalFit
horizontalAlignment: Text.AlignHCenter
}
PropertyChanges {
target: sizehelper
height: Math.min(main.height, fontHelper.contentHeight)
fontSizeMode: Text.VerticalFit
font.pixelSize: fontHelper.font.pixelSize
}
},
State {
name: "verticalPanel"
when: Plasmoid.formFactor === PlasmaCore.Types.Vertical
PropertyChanges {
target: main
Layout.fillHeight: false
Layout.fillWidth: true
Layout.maximumHeight: contentItem.height
Layout.minimumHeight: Layout.maximumHeight
}
PropertyChanges {
target: contentItem
height: main.showDate ? labelsGrid.height + dateLabel.contentHeight : labelsGrid.height
width: main.width
}
PropertyChanges {
target: labelsGrid
rows: 2
}
PropertyChanges {
target: timeLabel
height: sizehelper.contentHeight
width: main.width
font.pixelSize: Math.min(timeLabel.height, fontHelper.font.pixelSize)
fontSizeMode: Text.VerticalFit
}
PropertyChanges {
target: timezoneLabel
height: Math.max(0.7 * timeLabel.height, minimumPixelSize)
width: main.width
fontSizeMode: Text.Fit
minimumPixelSize: dateLabel.minimumPixelSize
elide: Text.ElideRight
}
PropertyChanges {
target: dateLabel
width: main.width
//NOTE: in order for Text.Fit to work as intended, the actual height needs to be quite big, in order for the font to enlarge as much it needs for the available width, and then request a sensible height, for which contentHeight will need to be considered as opposed to height
height: Kirigami.Units.iconSizes.small * 10
fontSizeMode: Text.Fit
verticalAlignment: Text.AlignTop
// Those magic numbers are purely what looks nice as maximum size, here we have it the smallest
// between slightly bigger than the default font (1.4 times) and a bit smaller than the time font
font.pixelSize: Math.min(0.7 * timeLabel.height, Kirigami.Theme.defaultFont.pixelSize * 1.4)
elide: Text.ElideRight
wrapMode: Text.WordWrap
}
AnchorChanges {
target: dateLabel
anchors.top: labelsGrid.bottom
anchors.horizontalCenter: labelsGrid.horizontalCenter
}
PropertyChanges {
target: sizehelper
width: main.width
fontSizeMode: Text.HorizontalFit
font.pixelSize: fontHelper.font.pixelSize
}
},
State {
name: "other"
when: Plasmoid.formFactor !== PlasmaCore.Types.Vertical && Plasmoid.formFactor !== PlasmaCore.Types.Horizontal
PropertyChanges {
target: main
Layout.fillHeight: false
Layout.fillWidth: false
Layout.minimumWidth: Kirigami.Units.iconSizes.small * 3
Layout.minimumHeight: Kirigami.Units.iconSizes.small * 3
}
PropertyChanges {
target: contentItem
height: main.height
width: main.width
}
PropertyChanges {
target: labelsGrid
rows: 2
}
PropertyChanges {
target: timeLabel
height: sizehelper.height
width: main.width
fontSizeMode: Text.Fit
}
PropertyChanges {
target: timezoneLabel
height: 0.7 * timeLabel.height
width: main.width
fontSizeMode: Text.Fit
minimumPixelSize: 1
}
PropertyChanges {
target: dateLabel
height: 0.7 * timeLabel.height
font.pixelSize: 1024
width: Math.max(timeLabel.contentWidth, Kirigami.Units.iconSizes.small * 3)
verticalAlignment: Text.AlignVCenter
fontSizeMode: Text.Fit
minimumPixelSize: 1
wrapMode: Text.WordWrap
}
AnchorChanges {
target: dateLabel
anchors.top: labelsGrid.bottom
anchors.horizontalCenter: labelsGrid.horizontalCenter
}
PropertyChanges {
target: sizehelper
height: {
if (main.showDate) {
if (timezoneLabel.visible) {
return 0.4 * main.height
}
return 0.56 * main.height
} else if (timezoneLabel.visible) {
return 0.59 * main.height
}
return main.height
}
width: main.width
fontSizeMode: Text.Fit
font.pixelSize: 1024
}
}
]
//onPressed: wasExpanded = root.expanded
//onClicked: root.expanded = !wasExpanded
onWheel: wheel => {
if (!Plasmoid.configuration.wheelChangesTimezone) {
return;
}
var delta = (wheel.inverted ? -1 : 1) * (wheel.angleDelta.y ? wheel.angleDelta.y : wheel.angleDelta.x);
var newIndex = main.tzIndex;
wheelDelta += delta;
// magic number 120 for common "one click"
// See: https://doc.qt.io/qt-5/qml-qtquick-wheelevent.html#angleDelta-prop
while (wheelDelta >= 120) {
wheelDelta -= 120;
newIndex--;
}
while (wheelDelta <= -120) {
wheelDelta += 120;
newIndex++;
}
if (newIndex >= Plasmoid.configuration.selectedTimeZones.length) {
newIndex = 0;
} else if (newIndex < 0) {
newIndex = Plasmoid.configuration.selectedTimeZones.length - 1;
}
if (newIndex !== main.tzIndex) {
Plasmoid.configuration.lastSelectedTimezone = Plasmoid.configuration.selectedTimeZones[newIndex];
main.tzIndex = newIndex;
dataSource.dataChanged();
setupLabels();
}
}
/*
* Visible elements
*
*/
KSvg.FrameSvgItem {
id: hoverIndicator
imagePath: Qt.resolvedUrl("svgs/tabbar.svgz")
visible: main.containsMouse || dashWindow.visible
anchors.fill: parent
anchors.leftMargin: main.showSeconds ? 0 : -Kirigami.Units.smallSpacing //To compensate for the shorter width of the clock when seconds are disabled
anchors.rightMargin:main.showSeconds ? 0 : -Kirigami.Units.smallSpacing
z: -1
prefix: main.containsPress ? "pressed-tab" : "active-tab";
}
Item {
id: contentItem
anchors.verticalCenter: main.verticalCenter
Grid {
id: labelsGrid
rows: 1
horizontalItemAlignment: Grid.AlignHCenter
verticalItemAlignment: Grid.AlignVCenter
flow: Grid.TopToBottom
columnSpacing: Kirigami.Units.smallSpacing
Components.Label {
id: timeLabel
font {
family: fontHelper.font.family
weight: fontHelper.font.weight
italic: fontHelper.font.italic
pixelSize: 1024
pointSize: -1 // Because we're setting the pixel size instead
// TODO: remove once this label is ported to PC3
}
minimumPixelSize: 1
text: Qt.formatTime(main.getCurrentTime(), Plasmoid.configuration.showSeconds === 2 ? main.timeFormatWithSeconds : main.timeFormat)
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
Components.Label {
id: timezoneLabel
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
font.pixelSize: 1024
font.pointSize: -1 // Because we're setting the pixel size instead
// TODO: remove once this label is ported to PC3
minimumPixelSize: 1
visible: text.length > 0
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Components.Label {
id: dateLabel
visible: main.showDate
font.family: timeLabel.font.family
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
font.pixelSize: 1024
font.pointSize: -1 // Because we're setting the pixel size instead
// TODO: remove once this label is ported to PC3
minimumPixelSize: 1
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
/*
* end: Visible Elements
*
*/
Components.Label {
id: sizehelper
font.family: timeLabel.font.family
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
minimumPixelSize: 1
visible: false
}
// To measure Label.height for maximum-sized font in VerticalFit mode
Components.Label {
id: fontHelper
height: 1024
font.family: (Plasmoid.configuration.autoFontAndSize || Plasmoid.configuration.fontFamily.length === 0) ? Kirigami.Theme.defaultFont.family : Plasmoid.configuration.fontFamily
font.weight: Plasmoid.configuration.autoFontAndSize ? Kirigami.Theme.defaultFont.weight : Plasmoid.configuration.fontWeight
font.italic: Plasmoid.configuration.autoFontAndSize ? Kirigami.Theme.defaultFont.italic : Plasmoid.configuration.italicText
font.pixelSize: Plasmoid.configuration.autoFontAndSize ? 3 * Kirigami.Theme.defaultFont.pixelSize : pointToPixel(Plasmoid.configuration.fontSize)
font.pointSize: -1
fontSizeMode: Text.VerticalFit
visible: false
}
FontMetrics {
id: timeMetrics
font.family: timeLabel.font.family
font.weight: timeLabel.font.weight
font.italic: timeLabel.font.italic
}
// Qt's QLocale does not offer any modular time creating like Klocale did
// eg. no "gimme time with seconds" or "gimme time without seconds and with timezone".
// QLocale supports only two formats - Long and Short. Long is unusable in many situations
// and Short does not provide seconds. So if seconds are enabled, we need to add it here.
//
// What happens here is that it looks for the delimiter between "h" and "m", takes it
// and appends it after "mm" and then appends "ss" for the seconds.
function timeFormatCorrection(timeFormatString) {
const regexp = /(hh*)(.+)(mm)/i
const match = regexp.exec(timeFormatString);
const hours = match[1];
const delimiter = match[2];
const minutes = match[3]
const seconds = "ss";
const amPm = "AP";
const uses24hFormatByDefault = timeFormatString.toLowerCase().indexOf("ap") === -1;
// because QLocale is incredibly stupid and does not convert 12h/24h clock format
// when uppercase H is used for hours, needs to be h or hh, so toLowerCase()
let result = hours.toLowerCase() + delimiter + minutes;
let result_sec = result + delimiter + seconds;
// add "AM/PM" either if the setting is the default and locale uses it OR if the user unchecked "use 24h format"
if ((main.use24hFormat == Qt.PartiallyChecked && !uses24hFormatByDefault) || main.use24hFormat == Qt.Unchecked) {
result += " " + amPm;
result_sec += " " + amPm;
}
main.timeFormat = result;
main.timeFormatWithSeconds = result_sec;
setupLabels();
}
function setupLabels() {
const showTimezone = main.showLocalTimezone || (Plasmoid.configuration.lastSelectedTimezone !== "Local"
&& dataSource.data["Local"]["Timezone City"] !== dataSource.data[Plasmoid.configuration.lastSelectedTimezone]["Timezone City"]);
let timezoneString = "";
if (showTimezone) {
// format timezone as tz code, city or UTC offset
if (displayTimezoneFormat === 0) {
timezoneString = dataSource.data[lastSelectedTimezone]["Timezone Abbreviation"]
} else if (displayTimezoneFormat === 1) {
timezoneString = TimezonesI18n.i18nCity(dataSource.data[lastSelectedTimezone]["Timezone"]);
} else if (displayTimezoneFormat === 2) {
const lastOffset = dataSource.data[lastSelectedTimezone]["Offset"];
const symbol = lastOffset > 0 ? '+' : '';
const hours = Math.floor(lastOffset / 3600);
const minutes = Math.floor(lastOffset % 3600 / 60);
timezoneString = "UTC" + symbol + hours.toString().padStart(2, '0') + ":" + minutes.toString().padStart(2, '0');
}
timezoneLabel.text = (main.showDate || main.oneLineMode) && Plasmoid.formFactor === PlasmaCore.Types.Horizontal ? "(" + timezoneString + ")" : timezoneString;
} else {
// this clears the label and that makes it hidden
timezoneLabel.text = timezoneString;
}
if (main.showDate) {
dateLabel.text = main.dateFormatter(main.getCurrentTime());
} else {
// clear it so it doesn't take space in the layout
dateLabel.text = "";
}
// find widest character between 0 and 9
let maximumWidthNumber = 0;
let maximumAdvanceWidth = 0;
for (let i = 0; i <= 9; i++) {
const advanceWidth = timeMetrics.advanceWidth(i);
if (advanceWidth > maximumAdvanceWidth) {
maximumAdvanceWidth = advanceWidth;
maximumWidthNumber = i;
}
}
// replace all placeholders with the widest number (two digits)
const format = main.timeFormat.replace(/(h+|m+|s+)/g, "" + maximumWidthNumber + maximumWidthNumber); // make sure maximumWidthNumber is formatted as string
// build the time string twice, once with an AM time and once with a PM time
const date = new Date(2000, 0, 1, 1, 0, 0);
const timeAm = Qt.formatTime(date, format);
const advanceWidthAm = timeMetrics.advanceWidth(timeAm);
date.setHours(13);
const timePm = Qt.formatTime(date, format);
const advanceWidthPm = timeMetrics.advanceWidth(timePm);
// set the sizehelper's text to the widest time string
if (advanceWidthAm > advanceWidthPm) {
sizehelper.text = timeAm;
} else {
sizehelper.text = timePm;
}
fontHelper.text = sizehelper.text
}
function dateTimeChanged() {
let doCorrections = false;
if (main.showDate) {
// If the date has changed, force size recalculation, because the day name
// or the month name can now be longer/shorter, so we need to adjust applet size
const currentDate = Qt.formatDateTime(main.getCurrentTime(), "yyyy-MM-dd");
if (main.lastDate !== currentDate) {
doCorrections = true;
main.lastDate = currentDate
}
}
const currentTZOffset = dataSource.data["Local"]["Offset"] / 60;
if (currentTZOffset !== tzOffset) {
doCorrections = true;
tzOffset = currentTZOffset;
Date.timeZoneUpdated(); // inform the QML JS engine about TZ change
}
if (doCorrections) {
timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat));
}
}
function setTimezoneIndex() {
main.tzIndex = Plasmoid.configuration.selectedTimeZones.indexOf(Plasmoid.configuration.lastSelectedTimezone);
}
Component.onCompleted: {
// Sort the timezones according to their offset
// Calling sort() directly on Plasmoid.configuration.selectedTimeZones
// has no effect, so sort a copy and then assign the copy to it
const sortedTimeZones = Plasmoid.configuration.selectedTimeZones;
const byOffset = (a, b) => dataSource.data[a]["Offset"] - dataSource.data[b]["Offset"];
sortedTimeZones.sort(byOffset);
Plasmoid.configuration.selectedTimeZones = sortedTimeZones;
setTimezoneIndex();
tzOffset = -(new Date().getTimezoneOffset());
dateTimeChanged();
timeFormatCorrection(Qt.locale().timeFormat(Locale.ShortFormat));
dataSource.onDataChanged.connect(dateTimeChanged);
dashWindow = Qt.createQmlObject("CalendarView {}", root);
}
}

View file

@ -0,0 +1,20 @@
/*
* Copyright 2013 Sebastian Kügler <sebas@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.0
import org.kde.plasma.calendar 2.0 as PlasmaCalendar
PlasmaCalendar.MonthMenu { }

View file

@ -0,0 +1,58 @@
/*import QtQuick 2.6
import QtQuick.Layouts 1.1
import QtGraphicalEffects 1.0
import QtQml.Models 2.2
import org.kde.plasma.core 2.0 as PlasmaCore
// for Highlight
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons
*/
import QtQuick 2.5
import QtQuick.Layouts 1.1
import QtQuick.Window 2.15
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.plasmoid 2.0
import org.kde.ksvg 1.0 as KSvg
import org.kde.kirigami 2.5 as Kirigami // For Settings.tabletMode
MouseArea {
id: toolButton
Layout.maximumWidth: Kirigami.Units.iconSizes.small+1;
Layout.maximumHeight: Kirigami.Units.iconSizes.small;
Layout.preferredWidth: Kirigami.Units.iconSizes.small+1;
Layout.preferredHeight: Kirigami.Units.iconSizes.small;
//signal clicked
property string buttonIcon: ""
property bool checkable: false
property bool checked: false
property bool flat: false
hoverEnabled: true
KSvg.FrameSvgItem {
id: normalButton
imagePath: Qt.resolvedUrl("svgs/button.svgz")
anchors.fill: parent
prefix: {
if(parent.containsPress || (checkable && checked)) return "toolbutton-pressed";
else return "toolbutton-hover";
}
visible: (parent.containsMouse || (checkable && checked)) && !flat
}
KSvg.SvgItem {
id: buttonIconSvg
svg: buttonIcons
elementId: buttonIcon
width: 10;
height: 10;
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}

View file

@ -0,0 +1,145 @@
/*
* Copyright 2015 by Martin Klapetek <mklapetek@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA.
*/
import QtQuick 2.0
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.private.digitalclock 1.0
Item {
id: tooltipContentItem
property int preferredTextWidth: units.gridUnit * 20
width: childrenRect.width + units.gridUnit
height: childrenRect.height + units.gridUnit
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
LayoutMirroring.childrenInherit: true
function timeForZone(zone) {
var compactRepresentationItem = plasmoid.compactRepresentationItem;
if (!compactRepresentationItem) {
return "";
}
// get the time for the given timezone from the dataengine
var now = dataSource.data[zone]["DateTime"];
// get current UTC time
var msUTC = now.getTime() + (now.getTimezoneOffset() * 60000);
// add the dataengine TZ offset to it
var dateTime = new Date(msUTC + (dataSource.data[zone]["Offset"] * 1000));
var formattedTime = Qt.formatTime(dateTime, compactRepresentationItem.timeFormat);
if (dateTime.getDay() != dataSource.data["Local"]["DateTime"].getDay()) {
formattedTime += " (" + Qt.formatDate(dateTime, compactRepresentationItem.dateFormat) + ")";
}
return formattedTime;
}
function nameForZone(zone) {
// add the timezone string to the clock
var timezoneString = plasmoid.configuration.displayTimezoneAsCode ? dataSource.data[zone]["Timezone Abbreviation"]
: TimezonesI18n.i18nCity(dataSource.data[zone]["Timezone City"]);
return timezoneString;
}
RowLayout {
anchors {
left: parent.left
top: parent.top
margins: units.gridUnit / 2
}
spacing: units.largeSpacing
PlasmaCore.IconItem {
id: tooltipIcon
source: "preferences-system-time"
Layout.alignment: Qt.AlignTop
visible: true
implicitWidth: units.iconSizes.medium
Layout.preferredWidth: implicitWidth
Layout.preferredHeight: implicitWidth
}
ColumnLayout {
PlasmaExtras.Heading {
id: tooltipMaintext
level: 3
Layout.minimumWidth: Math.min(implicitWidth, preferredTextWidth)
Layout.maximumWidth: preferredTextWidth
elide: Text.ElideRight
text: Qt.formatDate(tzDate,"dddd")
}
PlasmaComponents.Label {
id: tooltipSubtext
Layout.minimumWidth: Math.min(implicitWidth, preferredTextWidth)
Layout.maximumWidth: preferredTextWidth
text: Qt.formatDate(tzDate, dateFormatString)
opacity: 0.6
}
GridLayout {
Layout.minimumWidth: Math.min(implicitWidth, preferredTextWidth)
Layout.maximumWidth: preferredTextWidth
Layout.maximumHeight: childrenRect.height
columns: 2
visible: plasmoid.configuration.selectedTimeZones.length > 1
Repeater {
model: {
// The timezones need to be duplicated in the array
// because we need their data twice - once for the name
// and once for the time and the Repeater delegate cannot
// be one Item with two Labels because that wouldn't work
// in a grid then
var timezones = [];
for (var i = 0; i < plasmoid.configuration.selectedTimeZones.length; i++) {
timezones.push(plasmoid.configuration.selectedTimeZones[i]);
timezones.push(plasmoid.configuration.selectedTimeZones[i]);
}
return timezones;
}
PlasmaComponents.Label {
id: timezone
// Layout.fillWidth is buggy here
Layout.alignment: index % 2 === 0 ? Qt.AlignRight : Qt.AlignLeft
wrapMode: Text.NoWrap
text: index % 2 == 0 ? nameForZone(modelData) : timeForZone(modelData)
font.weight: modelData === plasmoid.configuration.lastSelectedTimezone ? Font.Bold : Font.Normal
height: paintedHeight
elide: Text.ElideNone
opacity: 0.6
}
}
}
}
}
}

View file

@ -0,0 +1,288 @@
/*
* Copyright 2013 Bhushan Shah <bhush94@gmail.com>
* Copyright 2013 Sebastian Kügler <sebas@kde.org>
* Copyright 2015 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.15
import QtQuick.Controls as QtControls
import QtQuick.Layouts 1.15 as QtLayouts
import QtQuick.Dialogs 6.3 as QtDialogs
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core as PlasmaCore
import org.kde.kcmutils // For KCMLauncher
import org.kde.config // For KAuthorized
import org.kde.kirigami 2.20 as Kirigami
import org.kde.plasma.workspace.calendar 2.0 as PlasmaCalendar
SimpleKCM {
id: appearancePage
width: childrenRect.width
height: childrenRect.height
signal configurationChanged
property string cfg_fontFamily
property string cfg_fontSize
property alias cfg_boldText: boldCheckBox.checked
property string cfg_timeFormat: ""
property alias cfg_italicText: italicCheckBox.checked
property alias cfg_showLocalTimezone: showLocalTimezone.checked
property alias cfg_displayTimezoneAsCode: timezoneCodeRadio.checked
property alias cfg_showSeconds: showSeconds.checked
property alias cfg_showDate: showDate.checked
property string cfg_dateFormat: "shortDate"
property alias cfg_use24hFormat: use24hFormat.checkState
onCfg_fontFamilyChanged: {
// HACK by the time we populate our model and/or the ComboBox is finished the value is still undefined
if (cfg_fontFamily) {
for (var i = 0, j = fontsModel.count; i < j; ++i) {
if (fontsModel.get(i).value == cfg_fontFamily) {
fontFamilyComboBox.currentIndex = i
break
}
}
}
}
ListModel {
id: fontsModel
Component.onCompleted: {
var arr = [] // use temp array to avoid constant binding stuff
arr.push({text: i18nc("Use default font", "Default"), value: ""})
var fonts = Qt.fontFamilies()
var foundIndex = 0
for (var i = 0, j = fonts.length; i < j; ++i) {
arr.push({text: fonts[i], value: fonts[i]})
}
append(arr)
}
}
ListModel {
id: fontSizesModel
Component.onCompleted: {
var arr = [] // use temp array to avoid constant binding stuff
arr.push({text: i18n("Use default font size"), value: ""})
var sizes = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '14', '16', '18', '20', '22', '24', '26', '28', '36', '48', '72']
for (var i = 0, j = sizes.length; i < j; ++i) {
arr.push({text: sizes[i], value: sizes[i]})
}
append(arr)
}
}
QtLayouts.ColumnLayout {
anchors.left: parent.left
QtControls.GroupBox {
QtLayouts.Layout.fillWidth: true
title: i18n("Information")
//flat: true
QtLayouts.ColumnLayout {
QtControls.CheckBox {
id: showDate
text: i18n("Show date")
}
QtControls.CheckBox {
id: showSeconds
text: i18n("Show seconds")
}
QtControls.CheckBox {
id: use24hFormat
text: i18nc("Checkbox label; means 24h clock format, without am/pm", "Use 24-hour Clock")
}
QtControls.CheckBox {
id: showLocalTimezone
text: i18n("Show local time zone")
}
/*QtControls.Label {
text: i18n("Display time zone as:")
}*/
QtControls.ButtonGroup {
buttons: timezoneColumn.children
}
QtControls.GroupBox {
QtLayouts.Layout.fillWidth: true
visible: false
//flat: true
QtLayouts.ColumnLayout {
id: timezoneColumn
//QtControls.ExclusiveGroup { id: timezoneDisplayType }
QtControls.RadioButton {
id: timezoneCityRadio
text: i18n("Time zone city")
//exclusiveGroup: timezoneDisplayType
}
QtControls.RadioButton {
id: timezoneCodeRadio
text: i18n("Time zone code")
//exclusiveGroup: timezoneDisplayType
}
}
}
QtLayouts.RowLayout {
QtControls.Label {
text: i18n("Date format:")
}
QtControls.ComboBox {
id: dateFormat
enabled: showDate.checked
textRole: "label"
model: [
{
'label': i18n("Long Date"),
'name': "longDate"
},
{
'label': i18n("Short Date"),
'name': "shortDate"
},
{
'label': i18n("ISO Date"),
'name': "isoDate"
}
]
onCurrentIndexChanged: cfg_dateFormat = model[currentIndex]["name"]
Component.onCompleted: {
for (var i = 0; i < model.length; i++) {
if (model[i]["name"] == Plasmoid.configuration.dateFormat) {
dateFormat.currentIndex = i;
}
}
}
}
}
}
}
QtLayouts.RowLayout {
QtLayouts.Layout.fillWidth: true
QtControls.Label {
text: i18n(" Font size px: ")
}
QtControls.ComboBox {
id: fontSizeComboBox
QtLayouts.Layout.fillWidth: true
// ComboBox's sizing is just utterly broken
QtLayouts.Layout.minimumWidth: Kirigami.Units.iconSizes.small * 10
model: fontSizesModel
// doesn't autodeduce from model because we manually populate it
textRole: "text"
onCurrentIndexChanged: {
var current = model.get(currentIndex)
if (current) {
cfg_fontSize = current.value
appearancePage.configurationChanged()
}
}
}
}
QtLayouts.RowLayout {
QtLayouts.Layout.fillWidth: true
QtControls.Label {
text: i18n(" Font style:")
}
QtControls.ComboBox {
id: fontFamilyComboBox
QtLayouts.Layout.fillWidth: true
// ComboBox's sizing is just utterly broken
QtLayouts.Layout.minimumWidth: Kirigami.Units.iconSizes.small * 10
model: fontsModel
// doesn't autodeduce from model because we manually populate it
textRole: "text"
onCurrentIndexChanged: {
var current = model.get(currentIndex)
if (current) {
cfg_fontFamily = current.value
appearancePage.configurationChanged()
}
}
}
QtControls.Button {
id: boldCheckBox
//tooltip: i18n("Bold text")
icon.name: "format-text-bold"
checkable: true
//Accessible.name: tooltip
}
QtControls.Button {
id: italicCheckBox
//tooltip: i18n("Italic text")
icon.name: "format-text-italic"
checkable: true
//Accessible.name: tooltip
}
}
}
Component.onCompleted: {
if (Plasmoid.configuration.displayTimezoneAsCode) {
timezoneCodeRadio.checked = true;
} else {
timezoneCityRadio.checked = true;
}
for(var i = 0; i < fontsModel.count; i++) {
if(fontsModel.get(i).value == Plasmoid.configuration.fontFamily) {
fontFamilyComboBox.currentIndex = i;
break;
}
}
for(var i = 0; i < fontSizesModel.count; i++) {
if(fontSizesModel.get(i).value == Plasmoid.configuration.fontSize) {
fontSizeComboBox.currentIndex = i;
break;
}
}
boldCheckBox.checked = Plasmoid.configuration.boldText;
italicCheckBox.checked = Plasmoid.configuration.italicText;
}
}

View file

@ -0,0 +1,106 @@
/*
* Copyright 2015 Martin Klapetek <mklapetek@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.0
import QtQuick.Controls as QtControls
import QtQuick.Layouts 1.0 as QtLayouts
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.workspace.calendar 2.0 as PlasmaCalendar
import org.kde.kcmutils as KCM
import org.kde.kirigami 2.20 as Kirigami
KCM.SimpleKCM {
id: calendarPage
width: childrenRect.width
height: childrenRect.height
signal configurationChanged()
property alias cfg_showWeekNumbers: showWeekNumbers.checked
property int cfg_firstDayOfWeek
PlasmaCalendar.EventPluginsManager {
id: eventPluginsManager
Component.onCompleted: {
populateEnabledPluginsList(Plasmoid.configuration.enabledCalendarPlugins);
}
}
function saveConfig()
{
Plasmoid.configuration.enabledCalendarPlugins = eventPluginsManager.enabledPlugins;
}
QtLayouts.ColumnLayout {
anchors.left: parent.left
QtControls.CheckBox {
id: showWeekNumbers
text: i18n("Show week numbers in Calendar")
}
QtLayouts.RowLayout {
QtLayouts.Layout.fillWidth: true
Text {
text: i18n("First day of week:")
}
//Kirigami.FormData.label: i18n("First day of week:")
QtControls.ComboBox {
id: firstDayOfWeekCombo
textRole: "text"
model: [-1, 0, 1, 5, 6].map(day => ({
day,
text: day === -1 ? i18n("Use Region Defaults") : Qt.locale().dayName(day),
}))
onActivated: cfg_firstDayOfWeek = model[index].day
currentIndex: model.findIndex(item => item.day === cfg_firstDayOfWeek)
}
}
QtControls.GroupBox {
QtLayouts.Layout.fillWidth: true
title: i18n("Available Calendar Plugins")
//flat: true
QtLayouts.ColumnLayout {
Repeater {
id: calendarPluginsRepeater
model: eventPluginsManager.model
delegate: QtLayouts.RowLayout {
QtControls.CheckBox {
text: model.display
checked: model.checked
onClicked: {
//needed for model's setData to be called
model.checked = checked;
calendarPage.configurationChanged();
}
}
}
}
}
}
}
Component.onCompleted: {
eventPluginsManager.populateEnabledPluginsList(Plasmoid.configuration.enabledCalendarPlugins);
}
}

View file

@ -0,0 +1,251 @@
/*
* SPDX-FileCopyrightText: 2013 Kai Uwe Broulik <kde@privat.broulik.de>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
import QtQuick
import QtQuick.Controls 2.15 as QQC2
import QtQuick.Layouts 1.15
import org.kde.kquickcontrolsaddons 2.0 // For kcmshell
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.private.digitalclock 1.0
import org.kde.kirigami as Kirigami
import org.kde.kcmutils as KCMUtils
import org.kde.config // KAuthorized
KCMUtils.ScrollViewKCM {
id: timeZonesPage
property alias cfg_selectedTimeZones: timeZones.selectedTimeZones
property alias cfg_wheelChangesTimezone: enableWheelCheckBox.checked
TimeZoneModel {
id: timeZones
onSelectedTimeZonesChanged: {
if (selectedTimeZones.length === 0) {
// Don't let the user remove all time zones
messageWidget.visible = true;
timeZones.selectLocalTimeZone();
}
}
}
header: ColumnLayout {
spacing: Kirigami.Units.smallSpacing
QQC2.Label {
Layout.fillWidth: true
text: i18n("Tip: if you travel frequently, add your home time zone to this list. It will only appear when you change the systemwide time zone to something else.")
wrapMode: Text.Wrap
}
}
view: ListView {
id: configuredTimezoneList
clip: true // Avoid visual glitches
focus: true // keyboard navigation
activeFocusOnTab: true // keyboard navigation
model: TimeZoneFilterProxy {
sourceModel: timeZones
onlyShowChecked: true
}
// We have no concept of selection in this list, so don't pre-select
// the first item
currentIndex: -1
delegate: Kirigami.RadioSubtitleDelegate {
id: timeZoneListItem
readonly property bool isCurrent: Plasmoid.configuration.lastSelectedTimezone === model.timeZoneId
readonly property bool isIdenticalToLocal: !model.isLocalTimeZone && model.city === timeZones.localTimeZoneCity()
width: ListView.view.width
font.bold: isCurrent
// Stripes help the eye line up the text on the left and the button on the right
Kirigami.Theme.useAlternateBackgroundColor: true
text: model.city
subtitle: {
if (configuredTimezoneList.count > 1) {
if (isCurrent) {
return i18n("Clock is currently using this time zone");
} else if (isIdenticalToLocal) {
return i18nc("@label This list item shows a time zone city name that is identical to the local time zone's city, and will be hidden in the timezone display in the plasmoid's popup", "Hidden while this is the local time zone's city");
}
}
return "";
}
checked: isCurrent
onToggled: Plasmoid.configuration.lastSelectedTimezone = model.timeZoneId
contentItem: RowLayout {
spacing: Kirigami.Units.smallSpacing
Kirigami.TitleSubtitle {
Layout.fillWidth: true
opacity: timeZoneListItem.isIdenticalToLocal ? 0.6 : 1.0
title: timeZoneListItem.text
subtitle: timeZoneListItem.subtitle
reserveSpaceForSubtitle: true
}
QQC2.Button {
visible: model.isLocalTimeZone && KAuthorized.authorizeControlModule("kcm_clock.desktop")
text: i18n("Switch Systemwide Time Zone…")
icon.name: "preferences-system-time"
font.bold: false
onClicked: KCMUtils.KCMLauncher.openSystemSettings("kcm_clock")
}
QQC2.Button {
visible: !model.isLocalTimeZone && configuredTimezoneList.count > 1
icon.name: "edit-delete"
font.bold: false
onClicked: model.checked = false;
QQC2.ToolTip {
text: i18n("Remove this time zone")
}
}
}
}
section {
property: "isLocalTimeZone"
delegate: Kirigami.ListSectionHeader {
width: configuredTimezoneList.width
label: section === "true" ? i18n("Systemwide Time Zone") : i18n("Additional Time Zones")
}
}
Kirigami.PlaceholderMessage {
visible: configuredTimezoneList.count === 1
anchors {
top: parent.verticalCenter // Visual offset for system timezone and header
left: parent.left
right: parent.right
leftMargin: Kirigami.Units.largeSpacing * 6
rightMargin: Kirigami.Units.largeSpacing * 6
}
text: i18n("Add more time zones to display all of them in the applet's pop-up, or use one of them for the clock itself")
}
}
footer: ColumnLayout {
spacing: Kirigami.Units.smallSpacing
QQC2.Button {
Layout.alignment: Qt.AlignLeft // Explicitly set so it gets reversed for LTR mode
text: i18n("Add Time Zones…")
icon.name: "list-add"
onClicked: timezoneSheet.open()
}
QQC2.CheckBox {
id: enableWheelCheckBox
enabled: configuredTimezoneList.count > 1
Layout.fillWidth: true
Layout.topMargin: Kirigami.Units.largeSpacing
text: i18n("Switch displayed time zone by scrolling over clock applet")
}
QQC2.Label {
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing * 2
Layout.rightMargin: Kirigami.Units.largeSpacing * 2
text: i18n("Using this feature does not change the systemwide time zone. When you travel, switch the systemwide time zone instead.")
font: Kirigami.Theme.smallFont
wrapMode: Text.Wrap
}
}
Kirigami.OverlaySheet {
id: timezoneSheet
parent: timeZonesPage.QQC2.Overlay.overlay
onVisibleChanged: {
filter.text = "";
messageWidget.visible = false;
if (visible) {
filter.forceActiveFocus()
}
}
header: ColumnLayout {
Kirigami.Heading {
Layout.fillWidth: true
text: i18n("Add More Timezones")
wrapMode: Text.Wrap
}
Kirigami.SearchField {
id: filter
Layout.fillWidth: true
}
Kirigami.InlineMessage {
id: messageWidget
Layout.fillWidth: true
type: Kirigami.MessageType.Warning
text: i18n("At least one time zone needs to be enabled. Your local timezone was enabled automatically.")
showCloseButton: true
}
}
footer: QQC2.DialogButtonBox {
standardButtons: QQC2.DialogButtonBox.Ok
onAccepted: timezoneSheet.close()
}
ListView {
focus: true // keyboard navigation
activeFocusOnTab: true // keyboard navigation
clip: true
implicitWidth: Math.max(timeZonesPage.width/2, Kirigami.Units.iconSizes.small * 25)
model: TimeZoneFilterProxy {
sourceModel: timeZones
filterString: filter.text
}
delegate: QQC2.CheckDelegate {
required property int index
required property var model
required checked
required property string city
required property string comment
required property string region
width: ListView.view.width
focus: true // keyboard navigation
text: {
if (!city || city.indexOf("UTC") === 0) {
return comment;
} else if (comment) {
return i18n("%1, %2 (%3)", city, region, comment);
} else {
return i18n("%1, %2", city, region)
}
}
onToggled: {
model.checked = checked
ListView.view.currentIndex = index // highlight
ListView.view.forceActiveFocus() // keyboard navigation
}
highlighted: ListView.isCurrentItem
}
}
}
}

View file

@ -0,0 +1,55 @@
/*
* Copyright (C) 2019 by intika <intika@librefox.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.5
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
Item {
id: configPageUpdater
property alias cfg_checkUpdateStartup: checkUpdateStartupBox.checked
ColumnLayout {
GroupBox {
flat: true
ColumnLayout {
Label {
text: i18n("\nUpdater")
font.weight: Font.Bold
}
Label {
text: i18n("Plasmoid: Digital Clock Lite\n")
}
Label {
text: i18n("Version: 5.5")
}
Label {
text: i18n("Author: Intika")
}
TextField {
Layout.minimumWidth: 450
text: 'https://github.com/Intika-Linux-Plasmoid/plasmoid-digital-clock-lite'
}
CheckBox {
id: checkUpdateStartupBox
text: i18n("Notify for update on startup (checked once on github, 5 min after startup)")
}
}
}
}
}

View file

@ -0,0 +1,165 @@
/*
* Copyright 2013 Heena Mahour <heena393@gmail.com>
* Copyright 2013 Sebastian Kügler <sebas@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.15
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.plasma5support as P5Support
import org.kde.kirigami 2.20 as Kirigami
import org.kde.plasma.private.digitalclock 1.0
import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.workspace.calendar 2.0 as PlasmaCalendar
import org.kde.ksvg 1.0 as KSvg
import org.kde.kcmutils // KCMLauncher
import org.kde.config // KAuthorized
//import org.kde.plasma.components 2.0 as PlasmaComponents
//import org.kde.plasma.extras 2.0 as PlasmaExtras
//import org.kde.plasma.calendar 2.0 as PlasmaCalendar
PlasmoidItem {
id: root
anchors.fill: parent
width: Kirigami.Units.iconSizes.small * 10
height: Kirigami.Units.iconSizes.small * 4
property string dateFormatString: setDateFormatString()
property date tzDate: {
const data = dataSource.data[Plasmoid.configuration.lastSelectedTimezone];
if (data === undefined) {
return new Date();
}
// get the time for the given timezone from the dataengine
const now = data["DateTime"];
// get current UTC time
const msUTC = now.getTime() + (now.getTimezoneOffset() * 60000);
// add the dataengine TZ offset to it
return new Date(msUTC + (data["Offset"] * 1000));
}
function initTimezones() {
const tz = []
if (Plasmoid.configuration.selectedTimeZones.indexOf("Local") === -1) {
tz.push("Local");
}
root.allTimezones = tz.concat(Plasmoid.configuration.selectedTimeZones);
dataSource.connectedSources = root.allTimezones;
}
//This is done to better control how the plasmoid should look and feel in a panel.
//preferredRepresentation: fullRepresentation
//compactRepresentation: null
//fullRepresentation: smallRepresentation
preferredRepresentation: fullRepresentation
compactRepresentation: null
fullRepresentation: smallRepresentation
/*toolTipItem: Loader {
id: tooltipLoader
Layout.minimumWidth: item ? item.width : 0
Layout.maximumWidth: item ? item.width : 0
Layout.minimumHeight: item ? item.height : 0
Layout.maximumHeight: item ? item.height : 0
source: "Tooltip.qml"
}*/
KSvg.Svg {
id: buttonIcons
imagePath: Qt.resolvedUrl("svgs/icons.svg");
}
KSvg.Svg {
id: clockSvg
imagePath: Qt.resolvedUrl("svgs/clock.svg");
}
//We need Local to be *always* present, even if not disaplayed as
//it's used for formatting in ToolTip.dateTimeChanged()
property var allTimezones
Connections {
target: Plasmoid.configuration
function onSelectedTimeZonesChanged() { root.initTimezones(); }
}
Component {
id: mainRepresentation
CalendarView {
}
}
Component {
id: smallRepresentation
DigitalClock
{}
}
hideOnWindowDeactivate: !Plasmoid.configuration.pin
P5Support.DataSource {
id: dataSource
engine: "time"
connectedSources: allTimezones
interval: Plasmoid.configuration.showSeconds ? 1000 : 60000
intervalAlignment: Plasmoid.configuration.showSeconds ? P5Support.Types.NoAlignment : P5Support.Types.AlignToMinute
}
function setDateFormatString() {
// remove "dddd" from the locale format string
// /all/ locales in LongFormat have "dddd" either
// at the beginning or at the end. so we just
// remove it + the delimiter and space
var format = Qt.locale().dateFormat(Locale.LongFormat);
format = format.replace(/(^dddd.?\s)|(,?\sdddd$)/, "");
return format;
}
Plasmoid.contextualActions: [
PlasmaCore.Action {
text: i18n("Adjust Date and Time…")
icon.name: "clock"
visible: KAuthorized.authorize("kcm_clock")
onTriggered: KCMLauncher.openSystemSettings("kcm_clock")
},
PlasmaCore.Action {
text: i18n("Set Time Format…")
icon.name: "gnumeric-format-thousand-separator"
visible: KAuthorized.authorizeControlModule("kcm_regionandlang")
onTriggered: KCMLauncher.openSystemSettings("kcm_regionandlang")
}
]
PlasmaCalendar.EventPluginsManager {
id: eventPluginsManager
enabledPlugins: Plasmoid.configuration.enabledCalendarPlugins
}
Component.onCompleted: {
root.initTimezones();
// Set the list of enabled plugins from config
// to the manager
eventPluginsManager.enabledPlugins = Plasmoid.configuration.enabledCalendarPlugins;
}
}

View file

@ -0,0 +1,701 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="129"
height="129"
viewBox="0 0 129 129"
fill="none"
version="1.1"
id="svg63"
sodipodi:docname="clock.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview63"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="5.6568543"
inkscape:cx="78.400464"
inkscape:cy="70.799066"
inkscape:window-width="1880"
inkscape:window-height="1032"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg63"
showgrid="false"
showguides="true"><inkscape:grid
id="grid42"
units="px"
originx="0"
originy="0"
spacingx="1"
spacingy="1"
empcolor="#0099e5"
empopacity="0.30196078"
color="#e50000"
opacity="0.14901961"
empspacing="1"
dotted="false"
gridanglex="30"
gridanglez="30"
visible="true"
snapvisiblegridlinesonly="true" /></sodipodi:namedview><g
filter="url(#filter0_d_3_129)"
id="clockface"
style="display:inline"><mask
id="path-1-inside-1_3_129"
fill="#ffffff"><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 63.5,0 C 28.9822,0 1,27.9822 1,62.5 1,97.0178 28.9822,125 63.5,125 98.0178,125 126,97.0178 126,62.5 126,27.9822 98.0178,0 63.5,0 Z m 0,4 C 31.1913,4 5,30.1913 5,62.5 5,94.8087 31.1913,121 63.5,121 95.8087,121 122,94.8087 122,62.5 122,30.1913 95.8087,4 63.5,4 Z"
id="path1" /></mask><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 63.5,0 C 28.9822,0 1,27.9822 1,62.5 1,97.0178 28.9822,125 63.5,125 98.0178,125 126,97.0178 126,62.5 126,27.9822 98.0178,0 63.5,0 Z m 0,4 C 31.1913,4 5,30.1913 5,62.5 5,94.8087 31.1913,121 63.5,121 95.8087,121 122,94.8087 122,62.5 122,30.1913 95.8087,4 63.5,4 Z"
fill="url(#paint0_linear_3_129)"
id="path2"
style="display:inline;fill:url(#paint0_linear_3_129)" /><path
d="M 2,62.5 C 2,28.5345 29.5345,1 63.5,1 V -1 C 28.4299,-1 0,27.4299 0,62.5 Z M 63.5,124 C 29.5345,124 2,96.4655 2,62.5 H 0 C 0,97.5701 28.4299,126 63.5,126 Z M 125,62.5 C 125,96.4655 97.4655,124 63.5,124 v 2 C 98.5701,126 127,97.5701 127,62.5 Z M 63.5,1 C 97.4655,1 125,28.5345 125,62.5 h 2 C 127,27.4299 98.5701,-1 63.5,-1 Z M 6,62.5 C 6,30.7436 31.7436,5 63.5,5 V 3 C 30.6391,3 4,29.6391 4,62.5 Z M 63.5,120 C 31.7436,120 6,94.2564 6,62.5 H 4 C 4,95.3609 30.6391,122 63.5,122 Z M 121,62.5 C 121,94.2564 95.2564,120 63.5,120 v 2 C 96.3609,122 123,95.3609 123,62.5 Z M 63.5,5 C 95.2564,5 121,30.7436 121,62.5 h 2 C 123,29.6391 96.3609,3 63.5,3 Z"
fill="#798183"
mask="url(#path-1-inside-1_3_129)"
id="path3"
style="display:inline" /><g
filter="url(#filter1_i_3_129)"
id="g3"
style="display:inline"><circle
cx="63.5"
cy="62.5"
r="58.5"
fill="url(#paint1_linear_3_129)"
id="circle3"
style="display:inline" /></g><g
filter="url(#filter2_f_3_129)"
id="g4"><circle
cx="63.5"
cy="62.5"
r="56"
stroke="url(#paint2_linear_3_129)"
stroke-opacity="0.3"
id="circle4"
style="display:inline;stroke:url(#paint2_linear_3_129)" /></g><mask
id="mask0_3_129"
maskUnits="userSpaceOnUse"
x="11"
y="10"
width="105"
height="105"><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 63.5,115 C 92.4949,115 116,91.4949 116,62.5 116,33.5051 92.4949,10 63.5,10 34.5051,10 11,33.5051 11,62.5 11,91.4949 34.5051,115 63.5,115 Z m 0,-8 C 88.0767,107 108,87.0767 108,62.5 108,37.9233 88.0767,18 63.5,18 38.9233,18 19,37.9233 19,62.5 19,87.0767 38.9233,107 63.5,107 Z"
fill="#d9d9d9"
id="path4" /></mask><g
mask="url(#mask0_3_129)"
id="g10"
style="display:inline"><path
d="M 64,10 V 115"
stroke="#4b6b6e"
stroke-width="2"
id="path5" /><path
d="m 37.75,17.0337 52.5,90.9323"
stroke="#4b6b6e"
stroke-width="2"
id="path6" /><path
d="m 18.5337,36.25 90.9323,52.5"
stroke="#4b6b6e"
stroke-width="2"
id="path7" /><path
d="m 11.5,62.5 h 105"
stroke="#4b6b6e"
stroke-width="2"
id="path8" /><path
d="M 18.5337,88.75 109.466,36.25"
stroke="#4b6b6e"
stroke-width="2"
id="path9"
style="display:inline" /><path
d="M 37.75,107.966 90.25,17.0337"
stroke="#4b6b6e"
stroke-width="2"
id="path10"
style="display:inline" /></g><g
filter="url(#filter3_di_3_129)"
id="g42"
style="display:inline"><mask
id="mask1_3_129"
maskUnits="userSpaceOnUse"
x="10"
y="9"
width="107"
height="107"><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 68.9895,114.712 C 97.8255,111.68 118.744,85.8466 115.712,57.0106 112.68,28.1746 86.8466,7.25606 58.0106,10.2878 29.1745,13.3195 8.25605,39.1535 11.2878,67.9895 14.3195,96.8255 40.1534,117.744 68.9895,114.712 Z M 68.692,111.883 C 95.9656,109.016 115.751,84.5816 112.883,57.308 110.016,30.0344 85.5816,10.2493 58.308,13.1168 31.0344,15.9843 11.2493,40.4184 14.1168,67.692 c 2.8675,27.2736 27.3016,47.059 54.5752,44.191 z"
fill="#d9d9d9"
id="path11" /></mask><g
mask="url(#mask1_3_129)"
id="g41"
style="display:inline"><path
d="M 58.5078,10.2355 69.4867,114.66"
stroke="#4b6b6e"
id="path12" /><path
d="M 33.1371,19.9753 94.8574,104.92"
stroke="#4b6b6e"
id="path13" /><path
d="M 16.0354,41.0956 111.959,83.7998"
stroke="#4b6b6e"
id="path14" /><path
d="M 11.785,67.9372 116.209,56.9583"
stroke="#4b6b6e"
id="path15" /><path
d="M 21.5249,93.3078 106.47,31.5876"
stroke="#4b6b6e"
id="path16" /><path
d="M 42.6451,110.41 85.3494,14.4859"
stroke="#4b6b6e"
id="path17" /><path
d="M 58.5078,10.2355 69.4867,114.66"
stroke="#4b6b6e"
id="path18" /><path
d="M 33.1371,19.9753 94.8574,104.92"
stroke="#4b6b6e"
id="path19" /><path
d="M 16.0354,41.0956 111.959,83.7998"
stroke="#4b6b6e"
id="path20" /><path
d="M 11.785,67.9372 116.209,56.9583"
stroke="#4b6b6e"
id="path21" /><path
d="M 21.5249,93.3078 106.47,31.5876"
stroke="#4b6b6e"
id="path22" /><path
d="M 42.6451,110.41 85.3494,14.4859"
stroke="#4b6b6e"
id="path23" /><path
d="M 53.0737,11.0433 74.9045,113.749"
stroke="#4b6b6e"
id="path24" /><path
d="m 28.8597,23.381 70.2587,78.03"
stroke="#4b6b6e"
id="path25" /><path
d="M 14.0586,46.1727 113.92,78.6194"
stroke="#4b6b6e"
id="path26" /><path
d="M 12.6364,73.3114 115.342,51.4807"
stroke="#4b6b6e"
id="path27" /><path
d="m 24.974,97.5254 78.03,-70.2587"
stroke="#4b6b6e"
id="path28" /><path
d="M 47.7657,112.327 80.2125,12.4656"
stroke="#4b6b6e"
id="path29" /><path
d="m 47.7521,12.415 32.4468,99.861"
stroke="#4b6b6e"
id="path30" /><path
d="M 24.9604,27.2161 102.991,97.4749"
stroke="#4b6b6e"
id="path31" /><path
d="M 12.6228,51.4301 115.328,73.2609"
stroke="#4b6b6e"
id="path32" /><path
d="M 14.0451,78.5689 113.906,46.1221"
stroke="#4b6b6e"
id="path33" /><path
d="M 28.8462,101.361 99.1049,23.3304"
stroke="#4b6b6e"
id="path34" /><path
d="M 53.0602,113.698 74.8909,10.9928"
stroke="#4b6b6e"
id="path35" /><path
d="M 42.6031,14.3355 85.3105,110.258"
stroke="#4b6b6e"
id="path36" /><path
d="M 21.4834,31.4379 106.43,93.1554"
stroke="#4b6b6e"
id="path37" /><path
d="M 11.7444,56.8089 116.169,67.7844"
stroke="#4b6b6e"
id="path38" /><path
d="M 15.9956,83.6503 111.918,40.943"
stroke="#4b6b6e"
id="path39" /><path
d="M 33.0981,104.77 94.8155,19.8232"
stroke="#4b6b6e"
id="path40" /><path
d="M 58.4691,114.509 69.4446,10.0842"
stroke="#4b6b6e"
id="path41" /></g></g></g><g
style="display:inline;fill:none"
id="g44"
transform="translate(4,3)"><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 119,59.5 C 119,92.3609 92.3609,119 59.5,119 43.1967,119 28.4249,112.443 17.6779,101.822 7.05708,91.0751 0.5,76.3033 0.5,60 0.5,27.1391 27.1391,0.5 60,0.5 76.3033,0.5 91.0751,7.05708 101.822,17.6779 112.443,28.4249 119,43.1967 119,59.5 Z M 118.5,60 C 118.5,92.3087 92.3087,118.5 60,118.5 27.6913,118.5 1.5,92.3087 1.5,60 1.5,27.6913 27.6913,1.5 60,1.5 c 32.3087,0 58.5,26.1913 58.5,58.5 z"
fill="#b3b6bc"
id="path1-3" /><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 59.5,118 C 91.8087,118 118,91.8087 118,59.5 118,27.1913 91.8087,1 59.5,1 27.1913,1 1,27.1913 1,59.5 1,91.8087 27.1913,118 59.5,118 Z m 0,1 C 92.3609,119 119,92.3609 119,59.5 119,26.6391 92.3609,0 59.5,0 26.6391,0 0,26.6391 0,59.5 0,92.3609 26.6391,119 59.5,119 Z"
fill="#8892a3"
id="path2-7" /></g><defs
id="defs63"><filter
id="filter0_d_3_129"
x="0"
y="0"
width="129"
height="129"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood43" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix43" /><feOffset
dx="1"
dy="2"
id="feOffset43" /><feGaussianBlur
stdDeviation="1"
id="feGaussianBlur43" /><feComposite
in2="hardAlpha"
operator="out"
id="feComposite43" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
id="feColorMatrix44" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_129"
id="feBlend44" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_129"
result="shape"
id="feBlend45" /></filter><filter
id="filter1_i_3_129"
x="5"
y="4"
width="117"
height="117"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood45" /><feBlend
mode="normal"
in="SourceGraphic"
in2="BackgroundImageFix"
result="shape"
id="feBlend46" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix46" /><feOffset
id="feOffset46" /><feGaussianBlur
stdDeviation="1.5"
id="feGaussianBlur46" /><feComposite
in2="hardAlpha"
operator="arithmetic"
k2="-1"
k3="1"
id="feComposite46" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"
id="feColorMatrix47" /><feBlend
mode="normal"
in2="shape"
result="effect1_innerShadow_3_129"
id="feBlend47" /></filter><filter
id="filter2_f_3_129"
x="6"
y="5"
width="115"
height="115"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood47" /><feBlend
mode="normal"
in="SourceGraphic"
in2="BackgroundImageFix"
result="shape"
id="feBlend48" /><feGaussianBlur
stdDeviation="0.5"
result="effect1_foregroundBlur_3_129"
id="feGaussianBlur48" /></filter><filter
id="filter3_di_3_129"
x="10.8921"
y="9.23197"
width="105.312"
height="105.68"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood48" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix48" /><feOffset
dx="-0.8"
dy="-0.8"
id="feOffset48" /><feComposite
in2="hardAlpha"
operator="out"
id="feComposite48" /><feColorMatrix
type="matrix"
values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
id="feColorMatrix49" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_129"
id="feBlend49" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_129"
result="shape"
id="feBlend50" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix50" /><feOffset
dx="0.2"
dy="0.2"
id="feOffset50" /><feGaussianBlur
stdDeviation="0.25"
id="feGaussianBlur50" /><feComposite
in2="hardAlpha"
operator="arithmetic"
k2="-1"
k3="1"
id="feComposite50" /><feColorMatrix
type="matrix"
values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
id="feColorMatrix51" /><feBlend
mode="normal"
in2="shape"
result="effect2_innerShadow_3_129"
id="feBlend51" /></filter><linearGradient
id="paint0_linear_3_129"
x1="9.2331963"
y1="19.919386"
x2="86.97599"
y2="68.179153"
gradientUnits="userSpaceOnUse"><stop
stop-color="#F8FEFF"
id="stop51" /><stop
offset="0.486626"
stop-color="#E1E3E7"
id="stop52" /><stop
offset="0.782747"
stop-color="#C2C6C7"
id="stop53" /></linearGradient><linearGradient
id="paint1_linear_3_129"
x1="19.5"
y1="18.5"
x2="107.5"
y2="106.5"
gradientUnits="userSpaceOnUse"><stop
stop-color="#E2EBEF"
id="stop54" /><stop
offset="0.23"
stop-color="#ECF0F1"
id="stop55" /><stop
offset="0.38"
stop-color="#D7E0E2"
id="stop56" /><stop
offset="0.5"
stop-color="#CDD8DB"
id="stop57" /><stop
offset="0.63"
stop-color="#D6DFE2"
id="stop58" /><stop
offset="0.91"
stop-color="#FCFEFF"
id="stop59" /></linearGradient><linearGradient
id="paint2_linear_3_129"
x1="47.008453"
y1="30.222439"
x2="82.889488"
y2="91.564278"
gradientUnits="userSpaceOnUse"><stop
stop-color="#26444E"
id="stop60" /><stop
offset="0.5"
stop-color="#26444E"
stop-opacity="0"
id="stop61" /></linearGradient><radialGradient
id="paint3_radial_3_129"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(62.5 61.5) rotate(45) scale(3.53553)"><stop
offset="0.025"
stop-color="#579FA4"
id="stop62" /><stop
offset="0.64"
stop-color="#213C3E"
id="stop63" /></radialGradient><filter
id="filter1_df_3_182"
x="2"
y="2"
width="117.681"
height="97.7024"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood4" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix4" /><feOffset
dy="4"
id="feOffset4" /><feGaussianBlur
stdDeviation="1"
id="feGaussianBlur5" /><feComposite
in2="hardAlpha"
operator="out"
id="feComposite5" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix5" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend5" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend6" /><feGaussianBlur
stdDeviation="1"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur6" /></filter><linearGradient
id="paint1_linear_3_182"
x1="37"
y1="10.5"
x2="67"
y2="72.5"
gradientUnits="userSpaceOnUse"><stop
stop-color="white"
stop-opacity="0"
id="stop8" /><stop
offset="1"
stop-color="white"
id="stop9" /></linearGradient><filter
id="filter0_df_3_182"
x="2"
y="3"
width="114.604"
height="110.884"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood2" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix2" /><feOffset
dy="4"
id="feOffset2" /><feGaussianBlur
stdDeviation="1"
id="feGaussianBlur2" /><feComposite
in2="hardAlpha"
operator="out"
id="feComposite2" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix3" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend3" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend4" /><feGaussianBlur
stdDeviation="0.5"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur4" /></filter><filter
id="filter1_df_3_182-3"
x="2"
y="2"
width="117.681"
height="97.7024"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood4-6" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix4-7" /><feOffset
dy="4"
id="feOffset4-5" /><feGaussianBlur
stdDeviation="1"
id="feGaussianBlur5-3" /><feComposite
in2="hardAlpha"
operator="out"
id="feComposite5-5" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix5-6" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend5-2" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend6-9" /><feGaussianBlur
stdDeviation="1"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur6-1" /></filter><filter
id="filter0_df_3_182-0"
x="2"
y="3"
width="114.604"
height="110.884"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood2-9" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix2-3" /><feOffset
dy="4"
id="feOffset2-6" /><feGaussianBlur
stdDeviation="1"
id="feGaussianBlur2-0" /><feComposite
in2="hardAlpha"
operator="out"
id="feComposite2-6" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix3-2" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend3-6" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend4-1" /><feGaussianBlur
stdDeviation="0.5"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur4-8" /></filter><linearGradient
inkscape:collect="always"
xlink:href="#paint1_linear_3_182"
id="linearGradient1"
gradientUnits="userSpaceOnUse"
x1="37"
y1="10.5"
x2="67"
y2="72.5" /><linearGradient
inkscape:collect="always"
xlink:href="#paint1_linear_3_182"
id="linearGradient2"
gradientUnits="userSpaceOnUse"
x1="37"
y1="10.5"
x2="67"
y2="72.5" /><filter
id="filter1_i_3_129-2"
x="5"
y="4"
width="117"
height="117"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood45-0" /><feBlend
mode="normal"
in="SourceGraphic"
in2="BackgroundImageFix"
result="shape"
id="feBlend46-2" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix46-3" /><feOffset
id="feOffset46-7" /><feGaussianBlur
stdDeviation="1.5"
id="feGaussianBlur46-5" /><feComposite
in2="hardAlpha"
operator="arithmetic"
k2="-1"
k3="1"
id="feComposite46-9"
k1="0"
k4="0" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"
id="feColorMatrix47-2" /><feBlend
mode="normal"
in2="shape"
result="effect1_innerShadow_3_129"
id="feBlend47-2" /></filter></defs><circle
cx="63.5"
cy="62.5"
r="2.5"
fill="url(#paint3_radial_3_129)"
id="clockdot" /><g
id="clockshine"><g
opacity="0.14"
filter="url(#filter0_df_3_182)"
id="g2"
style="filter:url(#filter0_df_3_182-0)"><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 114.604,35.8755 C 98.6369,29.2336 73.1157,37.2154 52.1952,56.76 35.0872,72.7428 25.4849,92.3203 25.5839,107.884 12.4127,97.1568 4,80.8109 4,62.5 4,30.1913 30.1913,4 62.5,4 c 22.7201,0 42.415,12.9521 52.104,31.8755 z"
fill="url(#paint0_linear_3_182)"
shape-rendering="crispEdges"
id="path1-7"
style="fill:url(#linearGradient1)" /></g><g
opacity="0.6"
filter="url(#filter1_df_3_182)"
id="g3-9"
style="filter:url(#filter1_df_3_182-3)"><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 117.681,43.0287 C 104.615,41.2781 88.9173,42.3436 72.6911,46.6914 39.2424,55.6539 14.7141,75.572 13.0071,93.7024 7.30188,84.6718 4,73.9715 4,62.5 4,30.1913 30.1913,4 62.5,4 c 25.482,0 47.159,16.2924 55.181,39.0287 z"
fill="url(#paint1_linear_3_182)"
shape-rendering="crispEdges"
id="path2-2"
style="fill:url(#linearGradient2)" /></g><rect
style="opacity:0;fill:#2c2c2c;stroke:#2c2c2c;stroke-width:0;stroke-opacity:0.984036"
id="rect5"
width="129"
height="129"
x="0"
y="0" /></g></svg>

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -0,0 +1,809 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="129"
height="129"
viewBox="0 0 129 129"
fill="none"
version="1.1"
id="svg63"
sodipodi:docname="clock.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview63"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="5.4983399"
inkscape:cx="83.388806"
inkscape:cy="82.206631"
inkscape:window-width="1600"
inkscape:window-height="838"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="clockface" />
<g
filter="url(#filter0_d_3_129)"
id="clockface">
<mask
id="path-1-inside-1_3_129"
fill="white">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M63.5 0C28.9822 0 1 27.9822 1 62.5C1 97.0178 28.9822 125 63.5 125C98.0178 125 126 97.0178 126 62.5C126 27.9822 98.0178 0 63.5 0ZM63.5 4C31.1913 4 5 30.1913 5 62.5C5 94.8087 31.1913 121 63.5 121C95.8087 121 122 94.8087 122 62.5C122 30.1913 95.8087 4 63.5 4Z"
id="path1" />
</mask>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M63.5 0C28.9822 0 1 27.9822 1 62.5C1 97.0178 28.9822 125 63.5 125C98.0178 125 126 97.0178 126 62.5C126 27.9822 98.0178 0 63.5 0ZM63.5 4C31.1913 4 5 30.1913 5 62.5C5 94.8087 31.1913 121 63.5 121C95.8087 121 122 94.8087 122 62.5C122 30.1913 95.8087 4 63.5 4Z"
fill="url(#paint0_linear_3_129)"
id="path2" />
<path
d="M2 62.5C2 28.5345 29.5345 1 63.5 1V-1C28.4299 -1 0 27.4299 0 62.5H2ZM63.5 124C29.5345 124 2 96.4655 2 62.5H0C0 97.5701 28.4299 126 63.5 126V124ZM125 62.5C125 96.4655 97.4655 124 63.5 124V126C98.5701 126 127 97.5701 127 62.5H125ZM63.5 1C97.4655 1 125 28.5345 125 62.5H127C127 27.4299 98.5701 -1 63.5 -1V1ZM6 62.5C6 30.7436 31.7436 5 63.5 5V3C30.6391 3 4 29.6391 4 62.5H6ZM63.5 120C31.7436 120 6 94.2564 6 62.5H4C4 95.3609 30.6391 122 63.5 122V120ZM121 62.5C121 94.2564 95.2564 120 63.5 120V122C96.3609 122 123 95.3609 123 62.5H121ZM63.5 5C95.2564 5 121 30.7436 121 62.5H123C123 29.6391 96.3609 3 63.5 3V5Z"
fill="#798183"
mask="url(#path-1-inside-1_3_129)"
id="path3" />
<g
filter="url(#filter1_i_3_129)"
id="g3">
<circle
cx="63.5"
cy="62.5"
r="58.5"
fill="url(#paint1_linear_3_129)"
id="circle3" />
</g>
<g
filter="url(#filter2_f_3_129)"
id="g4">
<circle
cx="63.5"
cy="62.5"
r="56"
stroke="url(#paint2_linear_3_129)"
stroke-opacity="0.3"
id="circle4" />
</g>
<mask
id="mask0_3_129"
maskUnits="userSpaceOnUse"
x="11"
y="10"
width="105"
height="105"
style="mask-type:alpha">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M63.5 115C92.4949 115 116 91.4949 116 62.5C116 33.5051 92.4949 10 63.5 10C34.5051 10 11 33.5051 11 62.5C11 91.4949 34.5051 115 63.5 115ZM63.5 107C88.0767 107 108 87.0767 108 62.5C108 37.9233 88.0767 18 63.5 18C38.9233 18 19 37.9233 19 62.5C19 87.0767 38.9233 107 63.5 107Z"
fill="#D9D9D9"
id="path4" />
</mask>
<g
mask="url(#mask0_3_129)"
id="g10">
<path
d="M64 10V115"
stroke="#4B6B6E"
stroke-width="2"
id="path5" />
<path
d="M37.75 17.0337L90.25 107.966"
stroke="#4B6B6E"
stroke-width="2"
id="path6" />
<path
d="M18.5337 36.25L109.466 88.75"
stroke="#4B6B6E"
stroke-width="2"
id="path7" />
<path
d="M11.5 62.5L116.5 62.5"
stroke="#4B6B6E"
stroke-width="2"
id="path8" />
<path
d="M18.5337 88.75L109.466 36.25"
stroke="#4B6B6E"
stroke-width="2"
id="path9" />
<path
d="M37.75 107.966L90.25 17.0337"
stroke="#4B6B6E"
stroke-width="2"
id="path10" />
</g>
<g
filter="url(#filter3_di_3_129)"
id="g42">
<mask
id="mask1_3_129"
maskUnits="userSpaceOnUse"
x="10"
y="9"
width="107"
height="107"
style="mask-type:alpha">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M68.9895 114.712C97.8255 111.68 118.744 85.8466 115.712 57.0106C112.68 28.1746 86.8466 7.25606 58.0106 10.2878C29.1745 13.3195 8.25605 39.1535 11.2878 67.9895C14.3195 96.8255 40.1534 117.744 68.9895 114.712ZM68.692 111.883C95.9656 109.016 115.751 84.5816 112.883 57.308C110.016 30.0344 85.5816 10.2493 58.308 13.1168C31.0344 15.9843 11.2493 40.4184 14.1168 67.692C16.9843 94.9656 41.4184 114.751 68.692 111.883Z"
fill="#D9D9D9"
id="path11" />
</mask>
<g
mask="url(#mask1_3_129)"
id="g41">
<path
d="M58.5078 10.2355L69.4867 114.66"
stroke="#4B6B6E"
id="path12" />
<path
d="M33.1371 19.9753L94.8574 104.92"
stroke="#4B6B6E"
id="path13" />
<path
d="M16.0354 41.0956L111.959 83.7998"
stroke="#4B6B6E"
id="path14" />
<path
d="M11.785 67.9372L116.209 56.9583"
stroke="#4B6B6E"
id="path15" />
<path
d="M21.5249 93.3078L106.47 31.5876"
stroke="#4B6B6E"
id="path16" />
<path
d="M42.6451 110.41L85.3494 14.4859"
stroke="#4B6B6E"
id="path17" />
<path
d="M58.5078 10.2355L69.4867 114.66"
stroke="#4B6B6E"
id="path18" />
<path
d="M33.1371 19.9753L94.8574 104.92"
stroke="#4B6B6E"
id="path19" />
<path
d="M16.0354 41.0956L111.959 83.7998"
stroke="#4B6B6E"
id="path20" />
<path
d="M11.785 67.9372L116.209 56.9583"
stroke="#4B6B6E"
id="path21" />
<path
d="M21.5249 93.3078L106.47 31.5876"
stroke="#4B6B6E"
id="path22" />
<path
d="M42.6451 110.41L85.3494 14.4859"
stroke="#4B6B6E"
id="path23" />
<path
d="M53.0737 11.0433L74.9045 113.749"
stroke="#4B6B6E"
id="path24" />
<path
d="M28.8597 23.381L99.1184 101.411"
stroke="#4B6B6E"
id="path25" />
<path
d="M14.0586 46.1727L113.92 78.6194"
stroke="#4B6B6E"
id="path26" />
<path
d="M12.6364 73.3114L115.342 51.4807"
stroke="#4B6B6E"
id="path27" />
<path
d="M24.974 97.5254L103.004 27.2667"
stroke="#4B6B6E"
id="path28" />
<path
d="M47.7657 112.327L80.2125 12.4656"
stroke="#4B6B6E"
id="path29" />
<path
d="M47.7521 12.415L80.1989 112.276"
stroke="#4B6B6E"
id="path30" />
<path
d="M24.9604 27.2161L102.991 97.4749"
stroke="#4B6B6E"
id="path31" />
<path
d="M12.6228 51.4301L115.328 73.2609"
stroke="#4B6B6E"
id="path32" />
<path
d="M14.0451 78.5689L113.906 46.1221"
stroke="#4B6B6E"
id="path33" />
<path
d="M28.8462 101.361L99.1049 23.3304"
stroke="#4B6B6E"
id="path34" />
<path
d="M53.0602 113.698L74.8909 10.9928"
stroke="#4B6B6E"
id="path35" />
<path
d="M42.6031 14.3355L85.3105 110.258"
stroke="#4B6B6E"
id="path36" />
<path
d="M21.4834 31.4379L106.43 93.1554"
stroke="#4B6B6E"
id="path37" />
<path
d="M11.7444 56.8089L116.169 67.7844"
stroke="#4B6B6E"
id="path38" />
<path
d="M15.9956 83.6503L111.918 40.943"
stroke="#4B6B6E"
id="path39" />
<path
d="M33.0981 104.77L94.8155 19.8232"
stroke="#4B6B6E"
id="path40" />
<path
d="M58.4691 114.509L69.4446 10.0842"
stroke="#4B6B6E"
id="path41" />
</g>
</g>
</g>
<defs
id="defs63">
<filter
id="filter0_d_3_129"
x="0"
y="0"
width="129"
height="129"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood43" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix43" />
<feOffset
dx="1"
dy="2"
id="feOffset43" />
<feGaussianBlur
stdDeviation="1"
id="feGaussianBlur43" />
<feComposite
in2="hardAlpha"
operator="out"
id="feComposite43" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
id="feColorMatrix44" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_129"
id="feBlend44" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_129"
result="shape"
id="feBlend45" />
</filter>
<filter
id="filter1_i_3_129"
x="5"
y="4"
width="117"
height="117"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood45" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="BackgroundImageFix"
result="shape"
id="feBlend46" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix46" />
<feOffset
id="feOffset46" />
<feGaussianBlur
stdDeviation="1.5"
id="feGaussianBlur46" />
<feComposite
in2="hardAlpha"
operator="arithmetic"
k2="-1"
k3="1"
id="feComposite46" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"
id="feColorMatrix47" />
<feBlend
mode="normal"
in2="shape"
result="effect1_innerShadow_3_129"
id="feBlend47" />
</filter>
<filter
id="filter2_f_3_129"
x="6"
y="5"
width="115"
height="115"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood47" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="BackgroundImageFix"
result="shape"
id="feBlend48" />
<feGaussianBlur
stdDeviation="0.5"
result="effect1_foregroundBlur_3_129"
id="feGaussianBlur48" />
</filter>
<filter
id="filter3_di_3_129"
x="10.8921"
y="9.23197"
width="105.312"
height="105.68"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood48" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix48" />
<feOffset
dx="-0.8"
dy="-0.8"
id="feOffset48" />
<feComposite
in2="hardAlpha"
operator="out"
id="feComposite48" />
<feColorMatrix
type="matrix"
values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
id="feColorMatrix49" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_129"
id="feBlend49" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_129"
result="shape"
id="feBlend50" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix50" />
<feOffset
dx="0.2"
dy="0.2"
id="feOffset50" />
<feGaussianBlur
stdDeviation="0.25"
id="feGaussianBlur50" />
<feComposite
in2="hardAlpha"
operator="arithmetic"
k2="-1"
k3="1"
id="feComposite50" />
<feColorMatrix
type="matrix"
values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"
id="feColorMatrix51" />
<feBlend
mode="normal"
in2="shape"
result="effect2_innerShadow_3_129"
id="feBlend51" />
</filter>
<linearGradient
id="paint0_linear_3_129"
x1="1.08514"
y1="50.7284"
x2="124.915"
y2="73.2716"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#F8FEFF"
id="stop51" />
<stop
offset="0.486626"
stop-color="#E1E3E7"
id="stop52" />
<stop
offset="0.782747"
stop-color="#C2C6C7"
id="stop53" />
</linearGradient>
<linearGradient
id="paint1_linear_3_129"
x1="19.5"
y1="18.5"
x2="107.5"
y2="106.5"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#E2EBEF"
id="stop54" />
<stop
offset="0.23"
stop-color="#ECF0F1"
id="stop55" />
<stop
offset="0.38"
stop-color="#D7E0E2"
id="stop56" />
<stop
offset="0.5"
stop-color="#CDD8DB"
id="stop57" />
<stop
offset="0.63"
stop-color="#D6DFE2"
id="stop58" />
<stop
offset="0.91"
stop-color="#FCFEFF"
id="stop59" />
</linearGradient>
<linearGradient
id="paint2_linear_3_129"
x1="19"
y1="18"
x2="89"
y2="88"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#26444E"
id="stop60" />
<stop
offset="0.5"
stop-color="#26444E"
stop-opacity="0"
id="stop61" />
</linearGradient>
<radialGradient
id="paint3_radial_3_129"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(62.5 61.5) rotate(45) scale(3.53553)">
<stop
offset="0.025"
stop-color="#579FA4"
id="stop62" />
<stop
offset="0.64"
stop-color="#213C3E"
id="stop63" />
</radialGradient>
<filter
id="filter1_df_3_182"
x="2"
y="2"
width="117.681"
height="97.7024"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood4" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix4" />
<feOffset
dy="4"
id="feOffset4" />
<feGaussianBlur
stdDeviation="1"
id="feGaussianBlur5" />
<feComposite
in2="hardAlpha"
operator="out"
id="feComposite5" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix5" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend5" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend6" />
<feGaussianBlur
stdDeviation="1"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur6" />
</filter>
<linearGradient
id="paint1_linear_3_182"
x1="37"
y1="10.5"
x2="67"
y2="72.5"
gradientUnits="userSpaceOnUse">
<stop
stop-color="white"
stop-opacity="0"
id="stop8" />
<stop
offset="1"
stop-color="white"
id="stop9" />
</linearGradient>
<filter
id="filter0_df_3_182"
x="2"
y="3"
width="114.604"
height="110.884"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood2" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix2" />
<feOffset
dy="4"
id="feOffset2" />
<feGaussianBlur
stdDeviation="1"
id="feGaussianBlur2" />
<feComposite
in2="hardAlpha"
operator="out"
id="feComposite2" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix3" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend3" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend4" />
<feGaussianBlur
stdDeviation="0.5"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur4" />
</filter>
<filter
id="filter1_df_3_182-3"
x="2"
y="2"
width="117.681"
height="97.7024"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood4-6" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix4-7" />
<feOffset
dy="4"
id="feOffset4-5" />
<feGaussianBlur
stdDeviation="1"
id="feGaussianBlur5-3" />
<feComposite
in2="hardAlpha"
operator="out"
id="feComposite5-5" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix5-6" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend5-2" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend6-9" />
<feGaussianBlur
stdDeviation="1"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur6-1" />
</filter>
<filter
id="filter0_df_3_182-0"
x="2"
y="3"
width="114.604"
height="110.884"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood2-9" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix2-3" />
<feOffset
dy="4"
id="feOffset2-6" />
<feGaussianBlur
stdDeviation="1"
id="feGaussianBlur2-0" />
<feComposite
in2="hardAlpha"
operator="out"
id="feComposite2-6" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0"
id="feColorMatrix3-2" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_3_182"
id="feBlend3-6" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_3_182"
result="shape"
id="feBlend4-1" />
<feGaussianBlur
stdDeviation="0.5"
result="effect2_foregroundBlur_3_182"
id="feGaussianBlur4-8" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#paint1_linear_3_182"
id="linearGradient1"
gradientUnits="userSpaceOnUse"
x1="37"
y1="10.5"
x2="67"
y2="72.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#paint1_linear_3_182"
id="linearGradient2"
gradientUnits="userSpaceOnUse"
x1="37"
y1="10.5"
x2="67"
y2="72.5" />
</defs>
<circle
cx="63.5"
cy="62.5"
r="2.5"
fill="url(#paint3_radial_3_129)"
id="clockdot" />
<g
id="clockshine">
<g
opacity="0.14"
filter="url(#filter0_df_3_182)"
id="g2"
style="filter:url(#filter0_df_3_182-0)">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 114.604,35.8755 C 98.6369,29.2336 73.1157,37.2154 52.1952,56.76 35.0872,72.7428 25.4849,92.3203 25.5839,107.884 12.4127,97.1568 4,80.8109 4,62.5 4,30.1913 30.1913,4 62.5,4 c 22.7201,0 42.415,12.9521 52.104,31.8755 z"
fill="url(#paint0_linear_3_182)"
shape-rendering="crispEdges"
id="path1-7"
style="fill:url(#linearGradient1)" />
</g>
<g
opacity="0.6"
filter="url(#filter1_df_3_182)"
id="g3-9"
style="filter:url(#filter1_df_3_182-3)">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 117.681,43.0287 C 104.615,41.2781 88.9173,42.3436 72.6911,46.6914 39.2424,55.6539 14.7141,75.572 13.0071,93.7024 7.30188,84.6718 4,73.9715 4,62.5 4,30.1913 30.1913,4 62.5,4 c 25.482,0 47.159,16.2924 55.181,39.0287 z"
fill="url(#paint1_linear_3_182)"
shape-rendering="crispEdges"
id="path2-2"
style="fill:url(#linearGradient2)" />
</g>
<rect
style="opacity:0;fill:#2c2c2c;stroke:#2c2c2c;stroke-width:0;stroke-opacity:0.984036"
id="rect5"
width="129"
height="129"
x="0"
y="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,148 @@
[Desktop Entry]
Name=Digital Clock Lite
Name[af]=Digitale horlosie Lite
Name[ar]= Lite ساعة رقمية
Name[be]=Лічбавы гадзіннік Lite
Name[be@latin]=Ličbavy hadzińnik Lite
Name[bg]=Цифров часовник Lite
Name[bn]=িি ি
Name[bn_IN]=িি ি
Name[bs]=Digitalni sat Lite
Name[ca]=Rellotge digital Lite
Name[ca@valencia]=Rellotge digital Lite
Name[cs]=Digitální hodiny Lite
Name[csb]=Cyfrowi zédżer Lite
Name[da]=Digitalt ur Lite
Name[de]=Digitale Uhr Lite
Name[el]=Ψηφιακό ρολόι Lite
Name[en_GB]=Digital Clock Lite
Name[eo]=Cifereca horloĝo Lite
Name[es]=Reloj digital Lite
Name[et]=Digikell Lite
Name[eu]=Erloju digitala Lite
Name[fi]=Digitaalinen kello Lite
Name[fr]=Horloge numérique Lite
Name[fy]=Digitale klok Lite
Name[ga]=Clog Digiteach Lite
Name[gl]=Reloxo dixital Lite
Name[gu]=િ િ
Name[he]=Lite שעון דיגיטלי
Name[hi]=िि
Name[hne]=िि
Name[hr]=Digitalni sat Lite
Name[hsb]=Digitalny časnik Lite
Name[hu]=Digitális óra Lite
Name[ia]=Horologio digital Lite
Name[id]=Jam Digital Lite
Name[is]=Stafræn klukka Lite
Name[it]=Orologio digitale Lite
Name[ja]= Lite
Name[kk]=Цифрлық сағат Lite
Name[km]=
Name[kn]= (ಿಿ) ಿ Lite
Name[ko]= Lite
Name[ku]=Demjimêra Dîjîtal Lite
Name[lt]=Skaitmeninis laikrodis Lite
Name[lv]=Ciparu pulkstenis Lite
Name[mai]=िि
Name[mk]=Дигитален часовник Lite
Name[ml]=ിി ി
Name[mr]=िि
Name[nb]=Digital klokke Lite
Name[nds]=Digitaal Klock Lite
Name[ne]=िि
Name[nl]=Digitale klok Lite
Name[nn]=Digital klokke Lite
Name[oc]=Relòtge numeric Lite
Name[or]=ି ି
Name[pa]=ਿਿ
Name[pl]=Zegar cyfrowy Lite
Name[pt]=Relógio Digital Lite
Name[pt_BR]=Relógio digital Lite
Name[ro]=Ceas digital Lite
Name[ru]=Цифровые часы Lite
Name[se]=Digitálalaš diibmu Lite
Name[si]=
Name[sk]=Digitálne hodiny Lite
Name[sl]=Digitalna ura Lite
Name[sr]=дигитални сат Lite
Name[sr@ijekavian]=дигитални сат Lite
Name[sr@ijekavianlatin]=digitalni sat Lite
Name[sr@latin]=digitalni sat Lite
Name[sv]=Digitalklocka Lite
Name[ta]= ி
Name[te]=ిి ి
Name[tg]=Соати рақамӣ Lite
Name[th]=
Name[tr]=Dijital Saat Lite
Name[ug]=Lite رەقەملىك سائەت
Name[uk]=Цифровий годинник Lite
Name[uz]=Raqamli soat Lite
Name[uz@cyrillic]=Рақамли соат Lite
Name[vi]=Đng h s Lite
Name[wa]=Ôrlodje didjitåle Lite
Name[x-test]=xxDigital Clockxx Lite
Name[zh_CN]= Lite
Name[zh_TW]= Lite
Comment=Time displayed in a digital format
Comment[ar]=الوقت بتنسيق رقميّ
Comment[bs]=Vrijeme prikazano u digitalnom obliku
Comment[ca]=Mostra l'hora en un format digital
Comment[ca@valencia]=Mostra l'hora en un format digital
Comment[cs]=Čas zobrazený v digitální podobě
Comment[da]=Tiden vist i et digitalt format
Comment[de]=Zeigt die Uhrzeit in digitaler Form an.
Comment[el]=Εμφάνιση της ώρας σε ψηφιακή μορφή
Comment[en_GB]=Time displayed in a digital format
Comment[es]=La hora mostrada en formato digital
Comment[et]=Aja esitamine digitaalsel kujul
Comment[eu]=Ordua formatu digitalean bistaratua
Comment[fi]=Aika näytettynä digitaalimuodossa
Comment[fr]=L'heure au format numérique
Comment[gl]=A hora mostrada nun formato dixital
Comment[he]=השעה מוצגת בפורמט דיגיטלי
Comment[hu]=Digitális formában kijelzett idő
Comment[id]=Waktu ditampilkan dalam format digital
Comment[is]=Klukkan sýnd á stafrænu formi
Comment[it]=Ora indicata in formato digitale
Comment[ja]=
Comment[ko]=
Comment[lt]=Laikas rodomas skaitmeniniu formatu
Comment[nb]=Klokkeslett vist i digitalt format
Comment[nds]=Tiet wiest in digitaal Formaat
Comment[nl]=Tijd weergegeven in een digitale opmaak
Comment[nn]=Klokka vist i digitalformat
Comment[pa]=ਿਿ ਿ
Comment[pl]=Wyświetla czas w formacie cyfrowym
Comment[pt]=A hora apresentada num formato digital
Comment[pt_BR]=Hora exibida em formato digital
Comment[ru]=Показ времени цифрами
Comment[sk]=Čas zobrazený v digitálnom formáte
Comment[sl]=Prikaz časa v digitalni obliki
Comment[sr]=Време дато у дигиталном формату
Comment[sr@ijekavian]=Време дато у дигиталном формату
Comment[sr@ijekavianlatin]=Vreme dato u digitalnom formatu
Comment[sr@latin]=Vreme dato u digitalnom formatu
Comment[sv]=Tid visad med digitalformat
Comment[tr]=Dijital biçimde gösterilen saat
Comment[uk]=Час, показаний у цифровому форматі
Comment[x-test]=xxTime displayed in a digital formatxx
Comment[zh_CN]=
Comment[zh_TW]=
Icon=preferences-system-time
Type=Service
X-KDE-ParentApp=
X-KDE-PluginInfo-Author=Martin Klapetek - Intika MoD
X-KDE-PluginInfo-Email=mklapetek@kde.org - Intika MoD
X-KDE-PluginInfo-License=GPL-2.0+
X-KDE-PluginInfo-Name=io.gitgud.wackyideas.digitalclocklite
X-KDE-PluginInfo-Version=5.5
X-KDE-PluginInfo-Website=plasma.kde.org
X-KDE-ServiceTypes=Plasma/Applet
X-Plasma-API=declarativeappletscript
X-KDE-PluginInfo-Category=Date and Time
X-Plasma-Provides=org.kde.plasma.time,org.kde.plasma.date
X-Plasma-MainScript=ui/main.qml

View file

@ -0,0 +1,153 @@
{
"KPackageStructure": "Plasma/Applet",
"KPlugin": {
"Authors": [
{
"Email": "mklapetek@kde.org - Intika MoD",
"Name": "Martin Klapetek - Intika MoD"
}
],
"Category": "Date and Time",
"Description": "Time displayed in a digital format",
"Description[ar]": "الوقت بتنسيق رقميّ",
"Description[bs]": "Vrijeme prikazano u digitalnom obliku",
"Description[ca@valencia]": "Mostra l'hora en un format digital",
"Description[ca]": "Mostra l'hora en un format digital",
"Description[cs]": "Čas zobrazený v digitální podobě",
"Description[da]": "Tiden vist i et digitalt format",
"Description[de]": "Zeigt die Uhrzeit in digitaler Form an.",
"Description[el]": "Εμφάνιση της ώρας σε ψηφιακή μορφή",
"Description[en_GB]": "Time displayed in a digital format",
"Description[es]": "La hora mostrada en formato digital",
"Description[et]": "Aja esitamine digitaalsel kujul",
"Description[eu]": "Ordua formatu digitalean bistaratua",
"Description[fi]": "Aika näytettynä digitaalimuodossa",
"Description[fr]": "L'heure au format numérique",
"Description[gl]": "A hora mostrada nun formato dixital",
"Description[he]": "השעה מוצגת בפורמט דיגיטלי",
"Description[hu]": "Digitális formában kijelzett idő",
"Description[id]": "Waktu ditampilkan dalam format digital",
"Description[is]": "Klukkan sýnd á stafrænu formi",
"Description[it]": "Ora indicata in formato digitale",
"Description[ja]": "デジタル形式で表示される時刻",
"Description[ko]": "디지털 시계",
"Description[lt]": "Laikas rodomas skaitmeniniu formatu",
"Description[nb]": "Klokkeslett vist i digitalt format",
"Description[nds]": "Tiet wiest in digitaal Formaat",
"Description[nl]": "Tijd weergegeven in een digitale opmaak",
"Description[nn]": "Klokka vist i digitalformat",
"Description[pa]": "ਡਿਜ਼ਿਟਲ ਫਾਰਮੈਟ ਵਿੱਚ ਸਮਾਂ ਵੇਖੋ",
"Description[pl]": "Wyświetla czas w formacie cyfrowym",
"Description[pt]": "A hora apresentada num formato digital",
"Description[pt_BR]": "Hora exibida em formato digital",
"Description[ru]": "Показ времени цифрами",
"Description[sk]": "Čas zobrazený v digitálnom formáte",
"Description[sl]": "Prikaz časa v digitalni obliki",
"Description[sr@ijekavian]": "Време дато у дигиталном формату",
"Description[sr@ijekavianlatin]": "Vreme dato u digitalnom formatu",
"Description[sr@latin]": "Vreme dato u digitalnom formatu",
"Description[sr]": "Време дато у дигиталном формату",
"Description[sv]": "Tid visad med digitalformat",
"Description[tr]": "Dijital biçimde gösterilen saat",
"Description[uk]": "Час, показаний у цифровому форматі",
"Description[x-test]": "xxTime displayed in a digital formatxx",
"Description[zh_CN]": "以数字格式显示的时间",
"Description[zh_TW]": "以數位格式顯示時間",
"Icon": "preferences-system-time",
"Id": "io.gitgud.wackyideas.digitalclocklite",
"License": "GPL-2.0+",
"Name": "Digital Clock Lite",
"Name[af]": "Digitale horlosie Lite",
"Name[ar]": "Lite ساعة رقمية",
"Name[be@latin]": "Ličbavy hadzińnik Lite",
"Name[be]": "Лічбавы гадзіннік Lite",
"Name[bg]": "Цифров часовник Lite",
"Name[bn]": "ডিজিটাল ঘড়ি",
"Name[bn_IN]": "ডিজিট্যাল ঘড়ি",
"Name[bs]": "Digitalni sat Lite",
"Name[ca@valencia]": "Rellotge digital Lite",
"Name[ca]": "Rellotge digital Lite",
"Name[cs]": "Digitální hodiny Lite",
"Name[csb]": "Cyfrowi zédżer Lite",
"Name[da]": "Digitalt ur Lite",
"Name[de]": "Digitale Uhr Lite",
"Name[el]": "Ψηφιακό ρολόι Lite",
"Name[en_GB]": "Digital Clock Lite",
"Name[eo]": "Cifereca horloĝo Lite",
"Name[es]": "Reloj digital Lite",
"Name[et]": "Digikell Lite",
"Name[eu]": "Erloju digitala Lite",
"Name[fi]": "Digitaalinen kello Lite",
"Name[fr]": "Horloge numérique Lite",
"Name[fy]": "Digitale klok Lite",
"Name[ga]": "Clog Digiteach Lite",
"Name[gl]": "Reloxo dixital Lite",
"Name[gu]": "ડિજીટલ ઘડિયાળ",
"Name[he]": "Lite שעון דיגיטלי",
"Name[hi]": "डिजिटल घड़ी",
"Name[hne]": "डिजिटल घड़ी",
"Name[hr]": "Digitalni sat Lite",
"Name[hsb]": "Digitalny časnik Lite",
"Name[hu]": "Digitális óra Lite",
"Name[ia]": "Horologio digital Lite",
"Name[id]": "Jam Digital Lite",
"Name[is]": "Stafræn klukka Lite",
"Name[it]": "Orologio digitale Lite",
"Name[ja]": "デジタル時計 Lite",
"Name[kk]": "Цифрлық сағат Lite",
"Name[km]": "នាឡិកា​ឌីជីថល",
"Name[kn]": "ಅಂಕೀಯ (ಡಿಜಿಟಲ್) ಗಡಿಯಾರ Lite",
"Name[ko]": "디지털 시계 Lite",
"Name[ku]": "Demjimêra Dîjîtal Lite",
"Name[lt]": "Skaitmeninis laikrodis Lite",
"Name[lv]": "Ciparu pulkstenis Lite",
"Name[mai]": "डिजिटल घडी",
"Name[mk]": "Дигитален часовник Lite",
"Name[ml]": "ഡിജിറ്റല്‍ ഘടികാരം",
"Name[mr]": "डिजिटल घड्याळ",
"Name[nb]": "Digital klokke Lite",
"Name[nds]": "Digitaal Klock Lite",
"Name[ne]": "डिजिटल घडी",
"Name[nl]": "Digitale klok Lite",
"Name[nn]": "Digital klokke Lite",
"Name[oc]": "Relòtge numeric Lite",
"Name[or]": "ସାଂଖିକ ଘଡ଼ି",
"Name[pa]": "ਡਿਜਿਟਲ ਘੜੀ",
"Name[pl]": "Zegar cyfrowy Lite",
"Name[pt]": "Relógio Digital Lite",
"Name[pt_BR]": "Relógio digital Lite",
"Name[ro]": "Ceas digital Lite",
"Name[ru]": "Цифровые часы Lite",
"Name[se]": "Digitálalaš diibmu Lite",
"Name[si]": "අංකිත ඔරලෝසුව",
"Name[sk]": "Digitálne hodiny Lite",
"Name[sl]": "Digitalna ura Lite",
"Name[sr@ijekavian]": "дигитални сат Lite",
"Name[sr@ijekavianlatin]": "digitalni sat Lite",
"Name[sr@latin]": "digitalni sat Lite",
"Name[sr]": "дигитални сат Lite",
"Name[sv]": "Digitalklocka Lite",
"Name[ta]": "எண்ணுரு கடிகாரம்",
"Name[te]": "డిజిటల్ గడియారం",
"Name[tg]": "Соати рақамӣ Lite",
"Name[th]": "นาฬิกาดิจิทัล",
"Name[tr]": "Dijital Saat Lite",
"Name[ug]": "Lite رەقەملىك سائەت",
"Name[uk]": "Цифровий годинник Lite",
"Name[uz@cyrillic]": "Рақамли соат Lite",
"Name[uz]": "Raqamli soat Lite",
"Name[vi]": "Đồng hồ số Lite",
"Name[wa]": "Ôrlodje didjitåle Lite",
"Name[x-test]": "xxDigital Clockxx Lite",
"Name[zh_CN]": "数字钟 Lite",
"Name[zh_TW]": "數位時鐘 Lite",
"Version": "5.5",
"Website": "plasma.kde.org"
},
"X-KDE-ParentApp": "org.kde.plasmashell",
"X-Plasma-API-Minimum-Version": "6.0",
"X-Plasma-Provides": [
"org.kde.plasma.time",
"org.kde.plasma.date"
]
}

View file

@ -0,0 +1,10 @@
import QtQuick 2.15
import org.kde.plasma.configuration
ConfigModel {
ConfigCategory {
name: i18n("General")
icon: "preferences-desktop-color"
source: "config/ConfigGeneral.qml"
}
}

View file

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name=""/>
<group name="General">
<entry name="click_action" type="string">
<default>run_command</default>
</entry>
<entry name="click_command" type="string">
<default>qdbus6 org.kde.kglobalaccel /component/kwin invokeShortcut "MinimizeAll"</default>
</entry>
<entry name="mousewheel_action" type="string">
<default>run_commands</default>
</entry>
<entry name="mousewheel_up" type="string">
<default>qdbus6 org.kde.kglobalaccel /component/kmix invokeShortcut "increase_volume"</default>
</entry>
<entry name="mousewheel_down" type="string">
<default>qdbus6 org.kde.kglobalaccel /component/kmix invokeShortcut "decrease_volume"</default>
</entry>
<entry name="size" type="int">
<default>9</default>
</entry>
<entry name="peekingEnabled" type="bool">
<default>true</default>
</entry>
<entry name="peekingThreshold" type="int">
<default>750</default>
</entry>
<entry name="edgeColor" type="string">
<default></default>
</entry>
<entry name="hoveredColor" type="string">
<default></default>
</entry>
<entry name="pressedColor" type="string">
<default></default>
</entry>
</group>
</kcfg>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Some files were not shown because too many files have changed in this diff Show more