This commit is contained in:
2026-03-31 20:13:15 +08:00
parent 48044e957d
commit 08c513b995
1155 changed files with 79920 additions and 0 deletions

View File

@ -0,0 +1,21 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 23 23">
<defs>
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text { color: #232629; }
</style>
</defs>
<path
class="ColorScheme-Text"
style="fill:currentColor"
d="m22.43,12.56s-.05-.04-.07-.07c-.04-.04-.07-.08-.12-.11,0,0,0,0,0,0,0,0,0,0,0,0l-4.97-2.6v-5.2c0-.09-.03-.17-.07-.24-.02-.03-.05-.04-.07-.07-.04-.04-.07-.08-.12-.11,0,0,0,0,0,0,0,0,0,0,0,0l-4.75-2.48c-.47-.24-1.04-.24-1.5,0l-4.75,2.48s0,0,0,0c0,0,0,0,0,0-.05.03-.08.07-.12.11-.02.02-.06.04-.07.07-.05.07-.07.15-.07.24v5.2L.76,12.38s0,0,0,0c0,0,0,0,0,0-.06.03-.09.08-.13.12-.02.02-.04.03-.06.05-.05.07-.07.15-.07.24v5.48c0,.17.1.33.26.42l5.24,2.74c.08.04.17.06.26.06s.18-.02.26-.06l4.98-2.6,4.98,2.6c.08.04.17.06.26.06s.18-.02.26-.06l5.24-2.74c.16-.09.26-.24.26-.42v-5.48c0-.09-.03-.17-.07-.24Zm-16.9,2.05l-2.7-1.41c-.34-.18-.34-.62,0-.79l2.7-1.41c.45-.24,1-.24,1.45,0l2.7,1.41c.34.18.34.62,0,.79l-2.7,1.41c-.45.24-1,.24-1.45,0Zm5.44,2.75c0,.4-.23.76-.61.96l-2.75,1.44c-.37.19-.83-.05-.83-.44v-2.86c0-.4.23-.76.61-.96l2.75-1.44c.37-.19.83.05.83.44v2.86Zm-.2-10.97l-2.7-1.41c-.34-.18-.34-.62,0-.79l2.7-1.41c.45-.24,1-.24,1.45,0l2.7,1.41c.34.18.34.62,0,.79l-2.7,1.41c-.45.24-1,.24-1.45,0Zm1.25,4.71v-2.86c0-.4.23-.76.61-.96l2.75-1.44c.37-.19.83.05.83.44v2.86c0,.4-.23.76-.61.96l-2.75,1.44c-.37.19-.83-.05-.83-.44Zm3.99,3.51l-2.7-1.41c-.34-.18-.34-.62,0-.79l2.7-1.41c.45-.24,1-.24,1.45,0l2.7,1.41c.34.18.34.62,0,.79l-2.7,1.41c-.45.24-1,.24-1.45,0Zm5.44,2.75c0,.4-.23.76-.61.96l-2.75,1.44c-.37.19-.83-.05-.83-.44v-2.86c0-.4.23-.76.61-.96l2.75-1.44c.37-.19.83.05.83.44v2.86Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,21 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 23 23">
<defs>
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text { color: #232629; }
</style>
</defs>
<path
class="ColorScheme-Text"
style="fill:currentColor"
d="m21.5,6.21c0-.06-.04-.11-.06-.18-.02-.09-.04-.19-.09-.27-.04-.06-.11-.1-.16-.15-.06-.06-.11-.13-.19-.17,0,0-.02,0-.03,0,0,0-.01-.01-.02-.02l-7.71-3.55c-1.1-.51-2.39-.51-3.49,0l-7.71,3.55s-.01.01-.02.02c0,0-.02,0-.03,0-.08.04-.12.11-.19.17-.05.05-.12.09-.16.15-.05.08-.07.17-.09.27-.02.06-.06.11-.06.18,0,0,0,0,0,.01,0,0,0,0,0,.01v9.57c0,.32.19.62.49.78l9.01,4.79c.15.08.32.12.49.12s.34-.04.49-.12l8.5-4.51c.62-.33,1.01-.94,1.01-1.6V6.24s0,0,0-.01c0,0,0,0,0-.01Zm-16.07-.32l5.2-2.4c.55-.25,1.19-.25,1.73,0l5.2,2.4c.37.17.39.66.03.85l-5.13,2.72c-.6.32-1.33.32-1.93,0l-5.13-2.72c-.36-.19-.35-.68.03-.85Zm14.1,8.5c0,.55-.32,1.06-.84,1.33l-5.44,2.88c-.34.18-.77-.05-.77-.41v-5.77c0-.55.32-1.05.83-1.33l3.24-1.72,2.2-1.16c.34-.18.77.05.77.41v5.77Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,22 @@
<!--
SPDX-FileCopyrightText: 2023 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
-->
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24">
<defs>
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text { color: #232629; }
</style>
</defs>
<path class="ColorScheme-Text" style="fill:currentColor"
d="m9.6094 13.32c-.68385 0-1.25.56615-1.25 1.25v.12891c0 .68385.56615 1.25 1.25 1.25h4.791c.68385 0 1.25-.56615 1.25-1.25v-.12891c0-.68385-.56615-1.25-1.25-1.25zm0 1h4.791c.14715 0 .25.10285.25.25v.12891c0 .14715-.10285.25-.25.25h-4.791c-.14715 0-.25-.10285-.25-.25v-.12891c0-.14715.10285-.25.25-.25z"/>
<g stroke-linecap="round" stroke-linejoin="round" class="ColorScheme-Text" style="fill:currentColor">
<path d="m4.9707 10.02a.75008.75008 0 00-.75.75v9.0996c0 1.0232.84592 1.8711 1.8691 1.8711h11.91c1.0232 0 1.8691-.84787 1.8691-1.8711v-9.0996a.75008.75008 0 00-.75-.75zm.75 1.5h12.648v8.3496c0 .21677-.15237.37109-.36914.37109h-11.91c-.21677 0-.36914-.15432-.36914-.37109z"/>
<path d="m7.5098 7.1602a.75008.75008 0 00-.56055.25195l-2.5391 2.8594a.75008.75008 0 00.56055 1.248h14.148a.75008.75008 0 00.5625-1.248l-2.541-2.8594a.75008.75008 0 00-.56055-.25195zm.33594 1.5h8.3965l1.207 1.3594h-10.811z"/>
<path d="m15.746 3.6992-7.4453.041016c-.57783 0-1.1067.42379-1.209 1.0117a.75008.75008 0 00-.00781.046875l-.20703 1.9082-2.3945-1.375c-.37855-.23296-.83629-.23296-1.2148 0a.75008.75008 0 00-.00781.00391l-2.7324 1.7246c-.00054767.000337.00054683.00162 0 .00195-.71708.44295-.71521 1.5381.005859 1.9707a.75008.75008 0 00.003906.00195l4.0313 2.3906a.75.75 0 001.0273-.26367.75.75 0 00-.26367-1.0273l-3.5391-2.0996 2.0898-1.3184 3.2441 1.8633a.75008.75008 0 001.1191-.57031l.30078-2.7715 6.9668-.037109.31055 2.8105a.75008.75008 0 001.127.56445l3.1641-1.8613 2.0918 1.3145-3.4746 2.0996a.75.75 0 00-.25391 1.0293.75.75 0 001.0293.25391l3.9336-2.377c.72984-.4325.72984-1.5675 0-2l-2.7031-1.6992a.75008.75008 0 00-.0059-.00391c-.35475-.21833-.84467-.24519-1.2382.0078162l-2.3047 1.3555-.21484-1.9277a.75008.75008 0 00-.0059-.046875c-.10095-.5807-.61862-1.0458-1.25-1.0195z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,14 @@
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24">
<defs>
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text { color: #232629; }
</style>
</defs>
<path
class="ColorScheme-Text"
style="fill:currentColor"
d="m 19.854756,20.481011 c -1.262396,-0.531251 -2.820748,-1.029352 -4.628787,-1.322602 -0.496751,-0.08075 -0.849454,-0.542301 -0.763897,-1.025102 0.05151,-0.28815 0.0777,-0.5899 0.0777,-0.905251 0,-1.996653 -1.097395,-3.618455 -2.445348,-3.618455 -1.357556,0 -2.4549513,1.621802 -2.4549513,3.618455 0,0.30005 0.025317,0.594151 0.074207,0.875501 0.082937,0.485351 -0.2697652,0.948602 -0.7691364,1.025102 -1.8831212,0.28815 -3.5008395,0.811751 -4.8121254,1.361702 -0.7988193,0.1122 -1.4439859,-0.777751 -0.9725516,-1.490052 0.1152394,-0.169151 0.231352,-0.346801 0.3369882,-0.525301 0.2793686,-0.430951 0.5587371,-0.862751 0.8276293,-1.312402 1.2327135,-1.977953 2.464554,-4.125056 3.6588544,-6.431109 0.028809,-0.0561 0.05762,-0.122401 0.086429,-0.178501 C 8.3203287,10.075296 8.560411,9.5967448 8.7917631,9.1190441 8.9070025,8.8937938 9.0231151,8.6591935 9.1287513,8.4339431 9.3120869,8.5461433 9.4945495,8.6770435 9.706695,8.8087937 10.669644,9.3901945 11.574972,9.718295 12.229743,9.8865952 11.748705,9.5304447 11.218778,9.1088441 10.679247,8.5835434 10.274162,8.1899928 9.9179674,7.7964422 9.6097889,7.4122417 10.062017,6.4372903 10.495912,5.4810389 10.880916,4.5528376 c 0.06722,-0.1496002 0.134447,-0.3000505 0.192939,-0.4403007 0.336988,-0.8151511 1.502479,-0.8151511 1.84907,-0.00935 0.163257,0.3842006 0.327385,0.7777511 0.501118,1.1721517 0.144049,0.3468005 0.308178,0.693601 0.471434,1.0497515 0.105636,0.2431004 0.221748,0.4964007 0.336989,0.7497011 0.231352,0.5066007 0.471434,1.0123514 0.721992,1.5283022 0.231352,0.4972507 0.481038,0.9936514 0.7412,1.4994026 0,0.0187 0.0096,0.02805 0.01921,0.04675 0.616356,1.228251 1.25192,2.399553 1.897086,3.534305 0.461831,0.833851 0.934139,1.640502 1.415176,2.419103 0.164128,0.290701 0.336989,0.572051 0.520325,0.853402 0.124842,0.1972 0.240954,0.39355 0.365797,0.5814 h -0.01048 c -0.336988,-0.17765 -0.702787,-0.3468 -1.097395,-0.49725 -0.683579,-0.262651 -1.319143,-0.421601 -1.868276,-0.515951 0.750802,0.365501 1.617718,0.844051 2.523047,1.481552 0.558736,0.402901 1.05898,0.796451 1.482399,1.190852 0.250558,0.674901 -0.356196,1.405902 -1.087792,1.284352 z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1 @@
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23"><path d=""/></svg>

After

Width:  |  Height:  |  Size: 92 B

View File

@ -0,0 +1,10 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m11.5,1.63C5.99,1.63,1.5,6.11,1.5,11.63s4.49,10,10,10,10-4.49,10-10S17.01,1.63,11.5,1.63Zm-7.26,10c0-4,3.26-7.26,7.26-7.26,1.56,0,3,.5,4.19,1.34L5.56,15.78c-.83-1.18-1.32-2.61-1.32-4.16Zm7.26,7.26c-1.46,0-2.83-.44-3.97-1.19l10.06-10c.74,1.13,1.17,2.48,1.17,3.93,0,4-3.26,7.26-7.26,7.26Z"/>
</svg>

After

Width:  |  Height:  |  Size: 542 B

View File

@ -0,0 +1,10 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m22.43,12.56s-.05-.04-.07-.07c-.04-.04-.07-.08-.12-.11,0,0,0,0,0,0,0,0,0,0,0,0l-4.97-2.6v-5.2c0-.09-.03-.17-.07-.24-.02-.03-.05-.04-.07-.07-.04-.04-.07-.08-.12-.11,0,0,0,0,0,0,0,0,0,0,0,0l-4.75-2.48c-.47-.24-1.04-.24-1.5,0l-4.75,2.48s0,0,0,0c0,0,0,0,0,0-.05.03-.08.07-.12.11-.02.02-.06.04-.07.07-.05.07-.07.15-.07.24v5.2L.76,12.38s0,0,0,0c0,0,0,0,0,0-.06.03-.09.08-.13.12-.02.02-.04.03-.06.05-.05.07-.07.15-.07.24v5.48c0,.17.1.33.26.42l5.24,2.74c.08.04.17.06.26.06s.18-.02.26-.06l4.98-2.6,4.98,2.6c.08.04.17.06.26.06s.18-.02.26-.06l5.24-2.74c.16-.09.26-.24.26-.42v-5.48c0-.09-.03-.17-.07-.24Zm-16.9,2.05l-2.7-1.41c-.34-.18-.34-.62,0-.79l2.7-1.41c.45-.24,1-.24,1.45,0l2.7,1.41c.34.18.34.62,0,.79l-2.7,1.41c-.45.24-1,.24-1.45,0Zm5.44,2.75c0,.4-.23.76-.61.96l-2.75,1.44c-.37.19-.83-.05-.83-.44v-2.86c0-.4.23-.76.61-.96l2.75-1.44c.37-.19.83.05.83.44v2.86Zm-.2-10.97l-2.7-1.41c-.34-.18-.34-.62,0-.79l2.7-1.41c.45-.24,1-.24,1.45,0l2.7,1.41c.34.18.34.62,0,.79l-2.7,1.41c-.45.24-1,.24-1.45,0Zm1.25,4.71v-2.86c0-.4.23-.76.61-.96l2.75-1.44c.37-.19.83.05.83.44v2.86c0,.4-.23.76-.61.96l-2.75,1.44c-.37.19-.83-.05-.83-.44Zm3.99,3.51l-2.7-1.41c-.34-.18-.34-.62,0-.79l2.7-1.41c.45-.24,1-.24,1.45,0l2.7,1.41c.34.18.34.62,0,.79l-2.7,1.41c-.45.24-1,.24-1.45,0Zm5.44,2.75c0,.4-.23.76-.61.96l-2.75,1.44c-.37.19-.83-.05-.83-.44v-2.86c0-.4.23-.76.61-.96l2.75-1.44c.37-.19.83.05.83.44v2.86Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,10 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m18.18,3.3h-3.48c-.43-1.1-1.53-1.88-2.81-1.88s-2.37.78-2.81,1.88h-3.36c-1.53,0-2.77,1.2-2.77,2.68v12.75c0,1.48,1.24,2.68,2.77,2.68h12.46c1.53,0,2.77-1.2,2.77-2.68V5.98c0-1.48-1.24-2.68-2.77-2.68Zm-6.29-.35c.59,0,1.07.47,1.07,1.04s-.48,1.04-1.07,1.04-1.07-.47-1.07-1.04.48-1.04,1.07-1.04Zm-.27,14.89h-4.95c-.54,0-.98-.43-.98-.95s.44-.95.98-.95h4.95c.54,0,.98.43.98.95s-.44.95-.98.95Zm3.22-4.36H6.68c-.54,0-.98-.43-.98-.95s.44-.95.98-.95h8.17c.54,0,.98.43.98.95s-.44.95-.98.95Zm2.56-4.36H6.68c-.54,0-.98-.43-.98-.95s.44-.95.98-.95h10.73c.54,0,.98.43.98.95s-.44.95-.98.95Z"/>
</svg>

After

Width:  |  Height:  |  Size: 825 B

View File

@ -0,0 +1,10 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m21.5,6.21c0-.06-.04-.11-.06-.18-.02-.09-.04-.19-.09-.27-.04-.06-.11-.1-.16-.15-.06-.06-.11-.13-.19-.17,0,0-.02,0-.03,0,0,0-.01-.01-.02-.02l-7.71-3.55c-1.1-.51-2.39-.51-3.49,0l-7.71,3.55s-.01.01-.02.02c0,0-.02,0-.03,0-.08.04-.12.11-.19.17-.05.05-.12.09-.16.15-.05.08-.07.17-.09.27-.02.06-.06.11-.06.18,0,0,0,0,0,.01,0,0,0,0,0,.01v9.57c0,.32.19.62.49.78l9.01,4.79c.15.08.32.12.49.12s.34-.04.49-.12l8.5-4.51c.62-.33,1.01-.94,1.01-1.6V6.24s0,0,0-.01c0,0,0,0,0-.01Zm-16.07-.32l5.2-2.4c.55-.25,1.19-.25,1.73,0l5.2,2.4c.37.17.39.66.03.85l-5.13,2.72c-.6.32-1.33.32-1.93,0l-5.13-2.72c-.36-.19-.35-.68.03-.85Zm14.1,8.5c0,.55-.32,1.06-.84,1.33l-5.44,2.88c-.34.18-.77-.05-.77-.41v-5.77c0-.55.32-1.05.83-1.33l3.24-1.72,2.2-1.16c.34-.18.77.05.77.41v5.77Z"/>
</svg>

After

Width:  |  Height:  |  Size: 997 B

View File

@ -0,0 +1,11 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<polyline fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.13px" points="15.35 15.15 11.68 12.23 11.68 7.15"/>
<path d="m22.5,11.61c0-.33-.02-.65-.05-.97,0-.01,0-.02,0-.03-.03-.31-.08-.61-.14-.92,0-.03,0-.05-.01-.08-.06-.27-.13-.54-.21-.8-.02-.06-.03-.11-.05-.17-.08-.24-.17-.48-.26-.72-.03-.07-.05-.13-.08-.2-.02-.04-.03-.08-.05-.12-.1-.23-.22-.46-.34-.68,0-.02-.02-.03-.02-.05-1.06-1.97-2.72-3.5-4.78-4.4-.05-.02-.09-.04-.14-.06-.07-.03-.14-.07-.22-.1-.19-.07-.37-.13-.56-.19-.04-.01-.08-.03-.13-.04-3.14-.98-6.44-.33-8.92,1.57-.12.09-.23.19-.34.29-.11.09-.22.17-.32.27-1.69,1.53-2.84,3.65-3.17,6.08h-1.34c-.78,0-1.17.96-.62,1.51l2.85,2.85c.33.33.87.33,1.21,0l2.83-2.86c.55-.56.16-1.51-.62-1.5h-1.54c.12-.64.32-1.25.6-1.82,0-.02.02-.03.03-.04.41-.83.96-1.55,1.61-2.15.15-.14.31-.27.47-.4,0,0,0,0,0,0,1.21-.92,2.73-1.47,4.37-1.47.74,0,1.46.11,2.13.32.01,0,.03,0,.04.01.21.07.41.14.61.22.03.01.05.02.07.03,1.49.65,2.71,1.78,3.48,3.2,0,0,0,0,0,.01.11.2.2.4.29.61.02.04.03.09.05.13.07.18.14.35.2.54.01.04.02.08.03.11.06.19.11.39.15.59,0,.02,0,.04,0,.06.04.22.08.44.1.67,0,0,0,.02,0,.03.02.23.03.46.04.7,0,.03,0,.05,0,.08,0,.21-.01.42-.03.62,0,.07-.02.14-.03.21-.02.16-.04.31-.07.47-.02.11-.05.23-.08.34-.03.11-.05.22-.08.33-.04.14-.09.28-.14.41-.03.08-.06.17-.09.25-.06.15-.12.29-.19.43-.04.08-.07.16-.12.24-.06.12-.13.24-.2.35-.05.09-.11.18-.17.27-.06.1-.14.19-.2.29-.07.1-.14.19-.21.29-.07.09-.15.18-.23.26-.08.08-.15.17-.23.25-.1.11-.21.2-.32.3-.06.05-.11.11-.17.16-.16.14-.33.27-.5.39,0,0-.02.01-.03.02-1.13.78-2.46,1.23-3.84,1.29-.03,0-.05,0-.08,0-.19,0-.38,0-.58-.01-.05,0-.11,0-.16,0-.2-.02-.39-.04-.59-.07-.04,0-.07-.01-.11-.02-.21-.04-.42-.08-.63-.14-.02,0-.04-.01-.06-.02-.22-.06-.43-.13-.65-.22-.02,0-.03-.01-.05-.02-.96-.38-1.81-.94-2.52-1.68-.53-.54-1.39-.55-1.93-.02-.54.53-.55,1.4-.02,1.94.87.89,1.88,1.59,3.01,2.1v.02c.13.06.28.11.42.17.03.01.06.03.09.04.03.01.06.02.09.03.24.09.48.17.72.24.07.02.13.04.2.06.24.06.48.12.72.17.08.01.16.02.23.04.23.04.47.08.71.1.06,0,.11,0,.17,0,.25.02.5.04.75.04.16,0,.31-.02.47-.02.11,0,.21,0,.32-.02.2-.02.39-.04.58-.07.07,0,.14-.02.21-.03.93-.15,1.81-.43,2.63-.82.05-.02.1-.05.14-.07.19-.09.37-.19.55-.29.06-.03.11-.07.17-.1.25-.15.49-.31.73-.48.14-.1.29-.21.42-.32.08-.07.16-.13.24-.2.16-.14.31-.28.46-.42.06-.05.11-.11.17-.17.19-.2.38-.4.55-.61,0-.01.02-.02.03-.03.2-.24.38-.49.56-.75.01-.02.02-.04.03-.05.15-.22.29-.46.42-.69.04-.08.08-.15.12-.23.09-.18.18-.37.27-.56.04-.1.09-.2.13-.3.02-.05.04-.1.06-.15.04-.1.06-.2.1-.3.06-.17.12-.33.17-.5.05-.17.09-.34.13-.51.03-.14.07-.27.09-.41.04-.23.08-.45.1-.68.01-.09.02-.17.03-.26.03-.29.04-.59.04-.88,0-.02,0-.05,0-.07,0,0,0-.01,0-.02Z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,10 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m11.5,1.5C5.98,1.5,1.5,5.98,1.5,11.5s4.48,10,10,10,10-4.48,10-10S17.02,1.5,11.5,1.5Zm6.45,6.42l-6.94,8.96c-.34.44-.86.73-1.42.77-.06,0-.11,0-.17,0-.5,0-.99-.19-1.36-.53l-2.84-2.61c-.58-.53-.62-1.43-.09-2,.53-.58,1.43-.61,2-.09l2.19,2.01,6.39-8.25c.48-.62,1.37-.73,1.99-.25.62.48.73,1.37.25,1.99Z"/>
</svg>

After

Width:  |  Height:  |  Size: 551 B

View File

@ -0,0 +1,13 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m14.49,15.49c-.46,0-.92-.2-1.24-.6-.58-.72-.5-1.8.18-2.41l3.92-3.5-3.93-3.55c-.68-.62-.76-1.7-.17-2.41.59-.71,1.62-.8,2.3-.18l5.38,4.85c.36.33.57.8.57,1.3,0,.5-.21.97-.57,1.3l-5.38,4.8c-.31.27-.68.41-1.06.41Z"/>
<ellipse cx="7.09" cy="4.35" rx="1.51" ry="1.58"/>
<ellipse cx="3.68" cy="11.77" rx="2.18" ry="2.28"/>
<ellipse cx="8.48" cy="19.22" rx="3.04" ry="3.19"/>
</svg>

After

Width:  |  Height:  |  Size: 631 B

View File

@ -0,0 +1,22 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<defs>
<style>
.cls-1 { fill: none; stroke: #000; stroke-linecap: round; stroke-linejoin: round; stroke-width: 2.13px; }
</style>
</defs>
<ellipse cx="2.48" cy="5.61" rx="1.53" ry="1.5"/>
<line class="cls-1" x1="8" y1="5.61" x2="20.94" y2="5.61"/>
<ellipse cx="2.48" cy="9.61" rx="1.53" ry="1.5"/>
<line class="cls-1" x1="8" y1="9.61" x2="20.94" y2="9.61"/>
<ellipse cx="2.48" cy="13.61" rx="1.53" ry="1.5"/>
<line class="cls-1" x1="8" y1="13.61" x2="20.94" y2="13.61"/>
<ellipse cx="2.48" cy="17.61" rx="1.53" ry="1.5"/>
<line class="cls-1" x1="8" y1="17.61" x2="20.94" y2="17.61"/>
</svg>

After

Width:  |  Height:  |  Size: 891 B

View File

@ -0,0 +1,12 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m1.5,2.42v3.68c0,.45.32.82.71.82h18.58c.39,0,.71-.36.71-.82v-3.68c0-.45-.32-.82-.71-.82H2.21c-.39,0-.71.36-.71.82Zm2.14,3.07c-.63,0-1.14-.64-1.14-1.42s.51-1.42,1.14-1.42,1.14.64,1.14,1.42-.51,1.42-1.14,1.42Zm16.11-.43H7.53c-.39,0-.71-.36-.71-.82v-.34c0-.45.32-.82.71-.82h12.21c.39,0,.71.36.71.82v.34c0,.45-.32.82-.71.82Z"/>
<path d="m1.5,9.77v3.68c0,.45.32.82.71.82h18.58c.39,0,.71-.36.71-.82v-3.68c0-.45-.32-.82-.71-.82H2.21c-.39,0-.71.36-.71.82Zm2.14,3.07c-.63,0-1.14-.64-1.14-1.42s.51-1.42,1.14-1.42,1.14.64,1.14,1.42-.51,1.42-1.14,1.42Zm16.11-.43H7.53c-.39,0-.71-.36-.71-.82v-.34c0-.45.32-.82.71-.82h12.21c.39,0,.71.36.71.82v.34c0,.45-.32.82-.71.82Z"/>
<path d="m1.5,17.11v3.68c0,.45.32.82.71.82h18.58c.39,0,.71-.36.71-.82v-3.68c0-.45-.32-.82-.71-.82H2.21c-.39,0-.71.36-.71.82Zm2.14,3.07c-.63,0-1.14-.64-1.14-1.42s.51-1.42,1.14-1.42,1.14.64,1.14,1.42-.51,1.42-1.14,1.42Zm16.11-.43H7.53c-.39,0-.71-.36-.71-.82v-.34c0-.45.32-.82.71-.82h12.21c.39,0,.71.36.71.82v.34c0,.45-.32.82-.71.82Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,11 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m20.02,13.39c-.59,0-.93.29-1.07.68-.95,2.82-3.56,4.52-6.64,4.52-1.67,0-3.26-.58-4.52-1.64-.19-.16-.19-.44-.01-.61l1.5-1.46c.53-.52.16-1.42-.58-1.42l-5.62.1c-.55.01-1,.46-1,1.01v5.37c.18.8,1.1.88,1.54.45l1.39-1.36c.16-.15.4-.15.56,0,1.86,1.66,4.23,2.58,6.74,2.58,5.25,0,8.46-3.36,9.71-7.7.08-.26-.13-.53-.41-.53h-1.6Z"/>
<path d="m4.07,9.82c.59,0,.93-.29,1.07-.68.95-2.82,3.56-4.52,6.64-4.52,1.68,0,3.26.58,4.53,1.64.19.15.19.44.01.61l-1.5,1.46c-.53.52-.16,1.42.58,1.42l5.62-.1c.55-.01.99-.46.99-1.01V3.28c-.18-.8-1.1-.88-1.54-.45l-1.39,1.36c-.16.15-.4.15-.56,0-1.86-1.67-4.23-2.58-6.75-2.58-5.25,0-8.46,3.37-9.71,7.71-.08.26.13.53.41.53h1.6Z"/>
</svg>

After

Width:  |  Height:  |  Size: 901 B

View File

@ -0,0 +1,12 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m9.72,11.51h13.28v-3.68c0-1.31-1.04-2.37-2.33-2.37h-4.1v-2.09c0-1.09-.88-1.98-1.95-1.98h-6.72c-1.08,0-1.95.89-1.95,1.98v2.09h-3.6c-1.29,0-2.33,1.06-2.33,2.37v3.68h9.72Zm-1.66-7.97h6.37v1.91h-6.37v-1.91Z"/>
<path d="m9.72,12.93h3.71c.16,0,.29.13.29.29v.67c0,.16-.13.29-.29.29h-3.71c-.16,0-.29-.13-.29-.29v-.67c0-.16.13-.29.29-.29Z"/>
<path d="m15.12,12.93c.02.1.03.19.03.29v.67c0,.94-.77,1.71-1.71,1.71h-3.71c-.94,0-1.71-.77-1.71-1.71v-.67c0-.1.01-.2.03-.29H0v6.08c0,1.31,1.04,2.37,2.33,2.37h18.33c1.29,0,2.33-1.06,2.33-2.37v-6.08h-7.88Z"/>
</svg>

After

Width:  |  Height:  |  Size: 800 B

View File

@ -0,0 +1,10 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m11.5,1.51C5.98,1.51,1.5,5.99,1.5,11.51s4.48,10,10,10,10-4.48,10-10S17.02,1.51,11.5,1.51Zm-1.48,13.45c0,.88-.62,1.59-1.4,1.59s-1.4-.71-1.4-1.59v-6.91c0-.88.62-1.59,1.4-1.59s1.4.71,1.4,1.59v6.91Zm5.75,0c0,.88-.62,1.59-1.4,1.59s-1.4-.71-1.4-1.59v-6.91c0-.88.62-1.59,1.4-1.59s1.4.71,1.4,1.59v6.91Z"/>
</svg>

After

Width:  |  Height:  |  Size: 550 B

View File

@ -0,0 +1,10 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m20.88,17.92l-3.29-3.28c.85-1.32,1.35-2.88,1.35-4.56,0-4.73-3.91-8.57-8.72-8.57S1.5,5.35,1.5,10.08s3.91,8.57,8.72,8.57c1.55,0,3-.4,4.26-1.1.01.01.02.03.03.04l3.31,3.3c.41.4.95.63,1.53.63.55,0,1.07-.2,1.47-.57.43-.39.67-.92.68-1.5.01-.57-.21-1.11-.62-1.52ZM3.98,10.08c0-3.36,2.8-6.09,6.24-6.09s6.24,2.73,6.24,6.09-2.8,6.09-6.24,6.09-6.24-2.73-6.24-6.09Z"/>
</svg>

After

Width:  |  Height:  |  Size: 608 B

View File

@ -0,0 +1,12 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m9.15,17.22h-2.11V2.27c0-.42-.38-.77-.86-.77h-1.15c-.47,0-.86.34-.86.77v14.96h-2.11c-.49,0-.74.52-.4.84l3.55,3.29c.22.2.58.2.8,0l3.55-3.29c.34-.31.09-.84-.4-.84Z"/>
<path d="m19.62,9.26l-.42-1.08h-3.54l-.42,1.1c-.16.43-.3.72-.42.87s-.3.23-.56.23c-.22,0-.42-.08-.59-.24s-.26-.34-.26-.54c0-.12.02-.24.06-.36s.1-.3.2-.52l2.23-5.58c.06-.16.14-.35.23-.58s.18-.41.28-.56.23-.27.4-.36.37-.14.61-.14.45.05.61.14.3.21.4.35.19.3.26.47.16.39.26.67l2.27,5.54c.18.42.27.73.27.92s-.08.38-.25.55-.37.25-.61.25c-.14,0-.26-.02-.36-.07s-.18-.12-.25-.2-.14-.21-.22-.39-.14-.33-.2-.46Zm-3.49-2.38h2.6l-1.31-3.54-1.29,3.54Z"/>
<path d="m14.27,19.5l4.47-5.28h-3.84c-.27,0-.47-.06-.61-.18s-.2-.27-.2-.46.07-.36.2-.48.34-.18.61-.18h4.95c.64,0,.96.29.96.88,0,.28-.05.51-.16.67s-.32.44-.65.81l-4.18,4.91h4.61c.27,0,.48.06.61.17s.2.27.2.47-.07.37-.2.49-.34.18-.61.18h-5.65c-.38,0-.67-.08-.87-.25s-.29-.4-.29-.68c0-.1.02-.19.05-.27s.07-.16.13-.23.13-.16.22-.28.18-.21.25-.29Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,10 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m11.5,1.51C5.98,1.51,1.5,5.99,1.5,11.51s4.48,10,10,10,10-4.48,10-10S17.02,1.51,11.5,1.51Zm5.17,10.81l-5.87,3.76c-1.03.66-2.37-.08-2.37-1.3v-6.54c0-1.22,1.35-1.95,2.37-1.3l5.87,3.76c.59.38.59,1.25,0,1.63Z"/>
</svg>

After

Width:  |  Height:  |  Size: 459 B

View File

@ -0,0 +1,10 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m11.76,1.5C6.23,1.5,1.76,5.98,1.76,11.5s4.48,10,10,10,10-4.48,10-10S17.28,1.5,11.76,1.5Zm3.85,12.29c0,.86-.7,1.56-1.56,1.56h-4.58c-.86,0-1.56-.7-1.56-1.56v-4.58c0-.86.7-1.56,1.56-1.56h4.58c.86,0,1.56.7,1.56,1.56v4.58Z"/>
</svg>

After

Width:  |  Height:  |  Size: 473 B

View File

@ -0,0 +1,10 @@
<!--
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
https://github.com/exequtic/apdatifier
-->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
<path d="m20.33,1.42H2.89C1.63,1.42.61,2.47.61,3.77v15.31c0,1.29,1.02,2.34,2.28,2.34h17.44c1.26,0,2.28-1.05,2.28-2.34V3.77c0-1.29-1.02-2.34-2.28-2.34Zm-9.99,10.67l-3.1,3.29c-.21.22-.48.33-.76.33-.26,0-.53-.1-.73-.3-.42-.42-.43-1.1-.02-1.53l2.38-2.53-2.35-2.45c-.41-.43-.4-1.11.01-1.53.41-.42,1.08-.41,1.49.01l3.07,3.2c.4.42.4,1.09,0,1.51Zm6.5,3.62h-4.07c-.58,0-1.05-.48-1.05-1.08s.47-1.08,1.05-1.08h4.07c.58,0,1.05.48,1.05,1.08s-.47,1.08-1.05,1.08Z"/>
</svg>

After

Width:  |  Height:  |  Size: 695 B

View File

@ -0,0 +1,62 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import org.kde.kirigami as Kirigami
Rectangle {
property var iconName: ""
property var iconColor: ""
property bool pauseBadge: iconName === pausedIcon
function setAnchor(anchor) {
if (counterRow) {
var topLeft = { top: parent.top, bottom: undefined, left: parent.left, right: undefined }
var topRight = { top: parent.top, bottom: undefined, left: undefined, right: parent.right }
var positions = pauseBadge ? topLeft : topRight
} else {
var normal = {
top: (cfg.counterTop && !cfg.counterBottom) ? parent.top : undefined,
bottom: (cfg.counterBottom && !cfg.counterTop) ? parent.bottom : undefined,
left: (cfg.counterLeft && !cfg.counterRight) ? parent.left : undefined,
right: (cfg.counterRight && !cfg.counterLeft) ? parent.right : undefined
}
var reverse = {
top: (cfg.counterBottom && !cfg.counterTop) ? parent.top : undefined,
bottom: (cfg.counterTop && !cfg.counterBottom) ? parent.bottom : undefined,
left: (cfg.counterRight && !cfg.counterLeft) ? parent.left : undefined,
right: (cfg.counterLeft && !cfg.counterRight) ? parent.right : undefined
}
var positions = pauseBadge ? reverse : normal
}
return positions[anchor]
}
width: (counterOverlay ? trayIconSize : parent.width) / 3
height: width
radius: width / 2
color: cfg.counterColor ? cfg.counterColor : Kirigami.Theme.backgroundColor
anchors {
top: setAnchor("top")
bottom: setAnchor("bottom")
left: setAnchor("left")
right: setAnchor("right")
topMargin: counterOverlay ? 0 : 5
bottomMargin: counterOverlay ? 0 : 0
leftMargin: counterOverlay ? 0 : -1
rightMargin: counterOverlay ? 0 : -1
}
Kirigami.Icon {
anchors.fill: parent
source: cfg.ownIconsUI ? Qt.resolvedUrl("../assets/icons/" + iconName + ".svg") : iconName
color: iconColor
isMask: cfg.ownIconsUI
}
}

View File

@ -0,0 +1,49 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import org.kde.kirigami as Kirigami
import "../../tools/tools.js" as JS
RowLayout {
property alias labelText: label.text
ComboBox {
id: comboBox
implicitWidth: 250
textRole: "name"
model: [
{"name": i18n("None"), "value": ""},
{"name": i18n("Check updates"), "value": "checkUpdates"},
{"name": i18n("Upgrade system"), "value": "upgradeSystem"},
{"name": i18n("Switch interval"), "value": "switchInterval"},
{"name": i18n("Management"), "value": "management"}
]
onCurrentIndexChanged: {
var action = model[currentIndex]["value"]
switch (type) {
case "middle": cfg_middleAction = action; break;
case "right": cfg_rightAction = action; break;
case "scrollUp": cfg_scrollUpAction = action; break;
case "scrollDown": cfg_scrollDownAction = action; break;
}
}
Component.onCompleted: {
currentIndex = JS.setIndex(plasmoid.configuration[type + "Action"], model)
}
}
Label {
id: label
text: ""
}
property string type: ""
}

View File

@ -0,0 +1,69 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import org.kde.notification
import "../../tools/tools.js" as JS
Item {
Component {
id: notifyComponent
Notification {
componentName: "apdatifier"
flags: cfg.notifyPersistent ? Notification.Persistent : Notification.CloseOnTimeout
}
}
Component {
id: upgradeAction
NotificationAction {
label: i18n("Upgrade system")
onActivated: JS.upgradeSystem()
}
}
Component {
id: openArticleAction
NotificationAction {
property string link
label: i18n("Read article")
onActivated: Qt.openUrlExternally(link)
}
}
function send(event, title, body, link) {
const params = {
updates: {
icon: "apdatifier-packages",
urgency: "DefaultUrgency"
},
news: {
icon: "news-subscribe",
urgency: "HighUrgency"
},
error: {
icon: "error",
urgency: "CriticalUrgency"
}
}
const { icon, urgency } = params[event]
const action = (event === "updates" && cfg.notifyUpdatesAction) ? upgradeAction.createObject(root)
: (event === "news" && cfg.notifyNewsAction) ? openArticleAction.createObject(root, { link: link })
: []
if (cfg.notifySound) event += "Sound"
notifyComponent.createObject(root, {
eventId: event,
iconName: icon,
title: title,
text: body,
actions: action,
urgency: urgency
})?.sendEvent()
}
}

View File

@ -0,0 +1,79 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import org.kde.plasma.extras
import org.kde.plasma.components
import org.kde.kirigami as Kirigami
Item {
width: parent.width
height: implicitHeight
anchors.centerIn: parent
Loader {
width: parent.width - (Kirigami.Units.largeSpacing * 4)
anchors.centerIn: parent
active: sts.updated
sourceComponent: Kirigami.PlaceholderMessage {
width: parent.width - (Kirigami.Units.largeSpacing * 4)
icon.name: "checkmark"
text: i18n("System updated")
}
}
Loader {
width: parent.width - (Kirigami.Units.largeSpacing * 4)
anchors.centerIn: parent
active: !sts.busy && sts.err
sourceComponent: Kirigami.PlaceholderMessage {
icon.name: "error"
text: sts.statusMsg
explanation: sts.errMsg
}
}
Loader {
width: parent.width - (Kirigami.Units.largeSpacing * 4)
anchors.centerIn: parent
active: sts.busy
sourceComponent: ColumnLayout {
spacing: Kirigami.Units.largeSpacing * 4
BusyIndicator {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 128
Layout.preferredHeight: 128
opacity: 0.6
running: true
}
RowLayout {
spacing: Kirigami.Units.smallSpacing
visible: !cfg.showStatusText
ToolButton {
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
hoverEnabled: false
highlighted: false
enabled: false
Kirigami.Icon {
height: parent.height
width: parent.height
anchors.centerIn: parent
source: cfg.ownIconsUI ? svg(statusIcon) : statusIcon
color: Kirigami.Theme.colorSet
scale: cfg.ownIconsUI ? 0.7 : 0.9
isMask: cfg.ownIconsUI
smooth: true
}
}
DescriptiveLabel {
text: sts.statusMsg
font.bold: true
}
}
}
}
}

View File

@ -0,0 +1,45 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import org.kde.plasma.plasma5support as Plasma5Support
Plasma5Support.DataSource {
id: executable
engine: "executable"
connectedSources: []
onNewData: (sourceName, data) => {
var cmd = sourceName
var out = data["stdout"]
var err = data["stderr"]
var code = data["exit code"]
exited(cmd, out, err, code)
listeners[cmd](cmd, out, err, code)
}
signal exited(string cmd, string out, string err, int code)
property var listeners: ({})
function exec(cmd, callback) {
listeners[cmd] = execCallback.bind(executable, callback)
connectSource(cmd)
}
function execCallback(callback, cmd, out, err, code) {
cleanup()
if (callback) callback(cmd, out, err, code)
}
function cleanup() {
for (var cmd in listeners) {
delete listeners[cmd]
disconnectSource(cmd)
}
this.destroy()
}
}

View File

@ -0,0 +1,730 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Dialogs
import QtQuick.Controls
import org.kde.ksvg
import org.kde.kcmutils
import org.kde.iconthemes
import org.kde.kquickcontrolsaddons
import org.kde.kirigami as Kirigami
import org.kde.plasma.core as PlasmaCore
import "../../tools/tools.js" as JS
SimpleKCM {
property alias cfg_relevantIcon: relevantIcon.value
property string cfg_selectedIcon: plasmoid.configuration.selectedIcon
property alias cfg_indicatorStop: indicatorStop.checked
property alias cfg_counterEnabled: counterEnabled.checked
property alias cfg_counterOnLeft: counterOnLeft.checked
property string cfg_counterColor: plasmoid.configuration.counterColor
property alias cfg_counterSize: counterSize.value
property alias cfg_counterRadius: counterRadius.value
property alias cfg_counterOpacity: counterOpacity.value
property alias cfg_counterShadow: counterShadow.checked
property string cfg_counterFontFamily: plasmoid.configuration.counterFontFamily
property alias cfg_counterFontBold: counterFontBold.checked
property alias cfg_counterFontSize: counterFontSize.value
property alias cfg_counterSpacing: counterSpacing.value
property alias cfg_counterMargins: counterMargins.value
property alias cfg_counterOffsetX: counterOffsetX.value
property alias cfg_counterOffsetY: counterOffsetY.value
property alias cfg_counterCenter: counterCenter.checked
property bool cfg_counterTop: plasmoid.configuration.counterTop
property bool cfg_counterBottom: plasmoid.configuration.counterBottom
property bool cfg_counterRight: plasmoid.configuration.counterRight
property bool cfg_counterLeft: plasmoid.configuration.counterLeft
property alias cfg_ownIconsUI: ownIconsUI.checked
property int cfg_defaultTab: plasmoid.configuration.defaultTab
property alias cfg_switchDefaultTab: switchDefaultTab.checked
property alias cfg_spacing: spacing.value
property alias cfg_sorting: sorting.checked
property alias cfg_showStatusText: showStatusText.checked
property alias cfg_showToolBar: showToolBar.checked
property alias cfg_searchButton: searchButton.checked
property alias cfg_intervalButton: intervalButton.checked
property alias cfg_sortButton: sortButton.checked
property alias cfg_managementButton: managementButton.checked
property alias cfg_upgradeButton: upgradeButton.checked
property alias cfg_checkButton: checkButton.checked
property alias cfg_tabBarVisible: tabBarVisible.checked
property alias cfg_tabBarTexts: tabBarTexts.checked
property bool inTray: (plasmoid.containmentDisplayHints & PlasmaCore.Types.ContainmentDrawsPlasmoidHeading)
property bool horizontal: plasmoid.location === 3 || plasmoid.location === 4
property bool counterOverlay: inTray || !horizontal
property bool counterRow: !inTray && horizontal
property int currentTab
signal tabChanged(currentTab: int)
onCurrentTabChanged: tabChanged(currentTab)
header: Kirigami.NavigationTabBar {
actions: [
Kirigami.Action {
icon.name: "view-list-icons"
text: i18n("Panel Icon View")
checked: currentTab === 0
onTriggered: currentTab = 0
},
Kirigami.Action {
icon.name: "view-split-left-right"
text: i18n("List View")
checked: currentTab === 1
onTriggered: currentTab = 1
}
]
}
Kirigami.FormLayout {
id: iconViewTab
visible: currentTab === 0
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: i18n("Shown when")
enabled: counterOverlay
SpinBox {
id: relevantIcon
from: 0
to: 999
stepSize: 1
value: relevantIcon.value
}
Label {
text: i18np("update is pending ", "updates are pending ", relevantIcon.value)
}
}
Button {
id: iconButton
implicitWidth: iconFrame.width + Kirigami.Units.smallSpacing
implicitHeight: implicitWidth
hoverEnabled: true
FrameSvgItem {
id: iconFrame
anchors.centerIn: parent
width: Kirigami.Units.iconSizes.large + fixedMargins.left + fixedMargins.right
height: width
imagePath: "widgets/background"
Kirigami.Icon {
anchors.centerIn: parent
width: Kirigami.Units.iconSizes.large
height: width
source: JS.setIcon(cfg_selectedIcon)
}
}
IconDialog {
id: iconDialog
onIconNameChanged: cfg_selectedIcon = iconName || JS.defaultIcon
}
onClicked: menu.opened ? menu.close() : menu.open()
Menu {
id: menu
y: +parent.height
MenuItem {
text: i18n("Default") + " 1"
icon.name: "apdatifier-plasmoid"
enabled: cfg_selectedIcon !== JS.defaultIcon
onClicked: cfg_selectedIcon = JS.defaultIcon
}
MenuItem {
text: i18n("Default") + " 2"
icon.name: "apdatifier-packages"
enabled: cfg_selectedIcon !== icon.name
onClicked: cfg_selectedIcon = icon.name
}
MenuItem {
text: i18n("Default") + " 3"
icon.name: "apdatifier-package"
enabled: cfg_selectedIcon !== icon.name
onClicked: cfg_selectedIcon = icon.name
}
MenuItem {
text: i18n("Default") + " 4"
icon.name: "apdatifier-flatpak"
enabled: cfg_selectedIcon !== icon.name
onClicked: cfg_selectedIcon = icon.name
}
MenuItem {
text: i18n("Select...")
icon.name: "document-open-folder"
onClicked: iconDialog.open()
}
}
HoverHandler {
cursorShape: Qt.PointingHandCursor
}
ToolTip {
text: cfg_selectedIcon === JS.defaultIcon ? i18n("Default icon") : cfg_selectedIcon
delay: Kirigami.Units.toolTipDelay
visible: iconButton.hovered
}
}
Item {
Kirigami.FormData.isSection: true
}
CheckBox {
Kirigami.FormData.label: i18n("Stopped interval") + ":"
id: indicatorStop
text: i18n("Enable")
}
Item {
Kirigami.FormData.isSection: true
}
CheckBox {
Kirigami.FormData.label: i18n("Counter") + ":"
id: counterEnabled
text: i18n("Enable")
}
CheckBox {
Kirigami.FormData.label: "On left" + ":"
id: counterOnLeft
text: i18n("Enable")
visible: counterRow
enabled: counterEnabled.checked
}
Button {
Kirigami.FormData.label: i18n("Color") + ":"
id: counterColor
Layout.leftMargin: Kirigami.Units.gridUnit
implicitWidth: Kirigami.Units.gridUnit
implicitHeight: implicitWidth
visible: counterOverlay
enabled: counterEnabled.checked
background: Rectangle {
radius: counterRadius.value
border.width: 1
border.color: "black"
color: cfg_counterColor ? cfg_counterColor : Kirigami.Theme.backgroundColor
}
onPressed: menuColor.opened ? menuColor.close() : menuColor.open()
Menu {
id: menuColor
y: +parent.height
MenuItem {
text: i18n("Default color")
icon.name: "edit-clear"
enabled: cfg_counterColor && cfg_counterColor !== Kirigami.Theme.backgroundColor
onClicked: cfg_counterColor = ""
}
MenuItem {
text: i18n("Select...")
icon.name: "document-open-folder"
onClicked: colorDialog.open()
}
}
ColorDialog {
id: colorDialog
visible: false
title: i18n("Select counter background color")
selectedColor: cfg_counterColor
onAccepted: {
cfg_counterColor = selectedColor
}
}
HoverHandler {
cursorShape: Qt.PointingHandCursor
}
ToolTip {
text: cfg_counterColor ? cfg_counterColor : i18n("Default background color from current theme")
delay: Kirigami.Units.toolTipDelay
visible: counterColor.hovered
}
}
RowLayout {
Kirigami.FormData.label: i18n("Size") + ":"
visible: counterOverlay
enabled: counterEnabled.checked
Slider {
id: counterSize
from: -5
to: 10
stepSize: 1
value: counterSize.value
onValueChanged: plasmoid.configuration.counterSize = counterSize.value
}
Label {
text: counterSize.value
}
}
RowLayout {
Kirigami.FormData.label: i18n("Radius") + ":"
visible: counterOverlay
enabled: counterEnabled.checked
Slider {
id: counterRadius
from: 0
to: 100
stepSize: 1
value: counterRadius.value
onValueChanged: plasmoid.configuration.counterRadius = counterRadius.value
}
Label {
text: counterRadius.value
}
}
RowLayout {
Kirigami.FormData.label: i18n("Opacity") + ":"
visible: counterOverlay
enabled: counterEnabled.checked
Slider {
id: counterOpacity
from: 0
to: 10
stepSize: 1
value: counterOpacity.value
onValueChanged: plasmoid.configuration.counterOpacity = counterOpacity.value
}
Label {
text: counterOpacity.value / 10
}
}
CheckBox {
Kirigami.FormData.label: i18n("Shadow") + ":"
visible: counterOverlay
enabled: counterEnabled.checked
id: counterShadow
text: i18n("Enable")
}
ComboBox {
Kirigami.FormData.label: i18n("Font") + ":"
enabled: counterEnabled.checked
implicitWidth: 250
editable: true
textRole: "name"
model: {
let fonts = Qt.fontFamilies()
let arr = []
arr.push({"name": i18n("Default system font"), "value": ""})
for (let i = 0; i < fonts.length; i++) {
arr.push({"name": fonts[i], "value": fonts[i]})
}
return arr
}
onCurrentIndexChanged: cfg_counterFontFamily = model[currentIndex]["value"]
Component.onCompleted: currentIndex = JS.setIndex(plasmoid.configuration.counterFontFamily, model)
}
CheckBox {
Kirigami.FormData.label: i18n("Font bold") + ":"
enabled: counterEnabled.checked
id: counterFontBold
text: i18n("Enable")
}
Slider {
Kirigami.FormData.label: i18n("Font size") + ":"
visible: counterRow
enabled: counterEnabled.checked
id: counterFontSize
from: 4
to: 8
stepSize: 1
value: counterFontSize.value
onValueChanged: plasmoid.configuration.counterFontSize = counterFontSize.value
}
SpinBox {
Kirigami.FormData.label: i18n("Left spacing") + ":"
visible: counterRow
enabled: counterEnabled.checked
id: counterSpacing
from: 0
to: 99
stepSize: 1
value: counterSpacing.value
onValueChanged: plasmoid.configuration.counterSpacing = counterSpacing.value
}
SpinBox {
Kirigami.FormData.label: i18n("Side margins") + ":"
visible: counterRow
id: counterMargins
from: 0
to: 99
stepSize: 1
value: counterMargins.value
onValueChanged: plasmoid.configuration.counterMargins = counterMargins.value
}
RowLayout {
Kirigami.FormData.label: i18n("Offset") + ":"
visible: counterOverlay
enabled: counterEnabled.checked
Label { text: "X:" }
SpinBox {
id: counterOffsetX
from: -10
to: 10
stepSize: 1
value: counterOffsetX.value
onValueChanged: plasmoid.configuration.counterOffsetX = counterOffsetX.value
}
Label { text: "Y:" }
SpinBox {
id: counterOffsetY
from: -10
to: 10
stepSize: 1
value: counterOffsetY.value
onValueChanged: plasmoid.configuration.counterOffsetY = counterOffsetY.value
}
}
Item {
Kirigami.FormData.isSection: true
}
CheckBox {
Kirigami.FormData.label: i18n("Position") + ":"
visible: counterOverlay
enabled: counterEnabled.checked
id: counterCenter
text: i18n("Center")
}
GridLayout {
Layout.fillWidth: true
visible: counterOverlay
enabled: counterEnabled.checked
columns: 4
rowSpacing: 0
columnSpacing: 0
ButtonGroup {
id: position
}
Label {
Layout.fillHeight: true
Layout.alignment: Qt.AlignRight
Layout.rightMargin: Kirigami.Units.smallSpacing * 2.5
text: i18n("Top-Left")
MouseArea {
anchors.fill: parent
onClicked: {
topleft.checked = true
}
}
}
RadioButton {
id: topleft
ButtonGroup.group: position
checked: cfg_counterTop && cfg_counterLeft
onCheckedChanged: {
if (checked) {
cfg_counterTop = true
cfg_counterBottom = false
cfg_counterRight = false
cfg_counterLeft = true
}
}
}
RadioButton {
id: topright
ButtonGroup.group: position
checked: cfg_counterTop && cfg_counterRight
onCheckedChanged: {
if (checked) {
cfg_counterTop = true
cfg_counterBottom = false
cfg_counterRight = true
cfg_counterLeft = false
}
}
}
Label {
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft
text: i18n("Top-Right")
MouseArea {
anchors.fill: parent
onClicked: {
topright.checked = true
}
}
}
Label {
Layout.fillHeight: true
Layout.alignment: Qt.AlignRight
Layout.rightMargin: Kirigami.Units.smallSpacing * 2.5
text: i18n("Bottom-Left")
MouseArea {
anchors.fill: parent
onClicked: {
bottomleft.checked = true
}
}
}
RadioButton {
id: bottomleft
ButtonGroup.group: position
checked: cfg_counterBottom && cfg_counterLeft
onCheckedChanged: {
if (checked) {
cfg_counterTop = false
cfg_counterBottom = true
cfg_counterRight = false
cfg_counterLeft = true
}
}
}
RadioButton {
id: bottomright
ButtonGroup.group: position
checked: cfg_counterBottom && cfg_counterRight
onCheckedChanged: {
if (checked) {
cfg_counterTop = false
cfg_counterBottom = true
cfg_counterRight = true
cfg_counterLeft = false
}
}
}
Label {
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft
text: i18n("Bottom-Right")
MouseArea {
anchors.fill: parent
onClicked: {
bottomright.checked = true
}
}
}
}
Item {
Kirigami.FormData.isSection: true
}
}
Kirigami.FormLayout {
id: listViewTab
visible: currentTab === 1
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: "UI:"
CheckBox {
id: ownIconsUI
text: i18n("Use built-in icons")
}
Kirigami.ContextualHelpButton {
toolTipText: i18n("Override custom icon theme and use default Apdatifier icons instead.")
}
}
Item {
Kirigami.FormData.isSection: true
}
ButtonGroup {
id: viewGroup
}
RadioButton {
Kirigami.FormData.label: i18n("Default tab") + ":"
id: compactView
ButtonGroup.group: viewGroup
text: i18n("Compact")
Component.onCompleted: checked = !plasmoid.configuration.defaultTab
}
RadioButton {
ButtonGroup.group: viewGroup
text: i18n("Extended")
onCheckedChanged: cfg_defaultTab = checked
Component.onCompleted: checked = plasmoid.configuration.defaultTab
}
CheckBox {
Kirigami.FormData.label: i18n("Behavior") + ":"
id: switchDefaultTab
text: i18n("Always switch to default tab")
}
RowLayout {
Kirigami.FormData.label: i18n("Item spacing (Compact)") + ":"
Slider {
id: spacing
from: 0
to: 12
stepSize: 1
value: spacing.value
onValueChanged: plasmoid.configuration.spacing = spacing.value
}
Label {
text: spacing.value
}
}
Item {
Kirigami.FormData.isSection: true
}
ButtonGroup {
id: sortGroup
}
RadioButton {
id: sorting
Kirigami.FormData.label: i18n("Sorting") + ":"
text: i18n("By repository")
checked: true
Component.onCompleted: checked = plasmoid.configuration.sorting
ButtonGroup.group: sortGroup
}
RadioButton {
text: i18n("By name")
Component.onCompleted: checked = !plasmoid.configuration.sorting
ButtonGroup.group: sortGroup
}
Item {
Kirigami.FormData.isSection: true
}
CheckBox {
id: showStatusText
Kirigami.FormData.label: i18n("Header") + ":"
text: i18n("Show status")
}
CheckBox {
id: showToolBar
text: i18n("Show tool bar")
}
RowLayout {
enabled: showToolBar.checked
CheckBox {
id: searchButton
icon.name: "search"
}
CheckBox {
id: intervalButton
icon.name: "media-playback-paused"
}
CheckBox {
id: sortButton
icon.name: "sort-name"
}
}
RowLayout {
enabled: showToolBar.checked
CheckBox {
id: managementButton
icon.name: "tools"
}
CheckBox {
id: upgradeButton
icon.name: "akonadiconsole"
}
CheckBox {
id: checkButton
icon.name: "view-refresh"
}
}
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: i18n("Footer") + ":"
CheckBox {
id: tabBarVisible
text: i18n("Show tab bar")
}
}
CheckBox {
id: tabBarTexts
text: i18n("Show tab texts")
enabled: tabBarVisible.checked
}
Item {
Kirigami.FormData.isSection: true
}
}
}

View File

@ -0,0 +1,514 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import org.kde.kcmutils
import org.kde.kirigami as Kirigami
import "../components" as QQC
import "../../tools/tools.js" as JS
SimpleKCM {
property alias cfg_interval: interval.checked
property alias cfg_time: time.value
property alias cfg_checkOnStartup: checkOnStartup.checked
property alias cfg_arch: arch.checked
property alias cfg_aur: aur.checked
property alias cfg_flatpak: flatpak.checked
property alias cfg_widgets: widgets.checked
property alias cfg_newsArch: newsArch.checked
property alias cfg_newsKDE: newsKDE.checked
property alias cfg_newsTWIK: newsTWIK.checked
property alias cfg_newsTWIKA: newsTWIKA.checked
property alias cfg_newsKeep: newsKeep.value
property string cfg_middleAction: plasmoid.configuration.middleAction
property string cfg_rightAction: plasmoid.configuration.rightAction
property string cfg_scrollUpAction: plasmoid.configuration.scrollUpAction
property string cfg_scrollDownAction: plasmoid.configuration.scrollDownAction
property alias cfg_notifyUpdates: notifyUpdates.checked
property alias cfg_notifyUpdatesAction: notifyUpdatesAction.checked
property alias cfg_notifyEveryBump: notifyEveryBump.checked
property alias cfg_notifyNews: notifyNews.checked
property alias cfg_notifyNewsAction: notifyNewsAction.checked
property alias cfg_notifyErrors: notifyErrors.checked
property alias cfg_notifySound: notifySound.checked
property alias cfg_notifyPersistent: notifyPersistent.checked
property var cfg: plasmoid.configuration
property var pkg: plasmoid.configuration.packages
property var terminals: plasmoid.configuration.terminals
property var packageLink: "https://archlinux.org/packages/extra/x86_64/pacman-contrib"
property int installButton
property var dialogTitles: {
"0": i18n("Install Development version"),
"1": i18n("Install Stable version"),
"2": i18n("Uninstall widget")
}
property var dialogSubtitles: {
"0": i18n("Note: version with the latest commits may be unstable."),
"1": i18n("Note: if you haven't installed the Devel version before, there's no need to install the Stable version."),
"2": i18n("Removal of the widget and all related files, including the directory with its configuration.")
}
property int currentTab
signal tabChanged(currentTab: int)
onCurrentTabChanged: tabChanged(currentTab)
Component.onCompleted: {
JS.checkDependencies()
}
header: Kirigami.NavigationTabBar {
actions: [
Kirigami.Action {
icon.name: "search"
text: i18n("Search")
checked: currentTab === 0
onTriggered: currentTab = 0
},
Kirigami.Action {
icon.name: "notification-active"
text: i18n("Notifications")
checked: currentTab === 1
onTriggered: currentTab = 1
},
Kirigami.Action {
icon.name: "followmouse-symbolic"
text: i18n("Mouse actions")
checked: currentTab === 2
onTriggered: currentTab = 2
},
Kirigami.Action {
icon.name: "documentinfo"
text: i18n("Misc")
checked: currentTab === 3
onTriggered: currentTab = 3
}
]
}
ColumnLayout {
Kirigami.InlineMessage {
id: configMsg
Layout.fillWidth: true
icon.source: "document-save"
text: "<b>" + i18n("Configuration is automatically saved in a config file and loaded at every startup, ensuring you never lose your settings. The config file is stored in ") + "~/.config/apdatifier" + "</b>"
type: Kirigami.MessageType.Positive
visible: plasmoid.configuration.configMsg
actions: [
Kirigami.Action {
text: "OK"
icon.name: "checkmark"
onTriggered: plasmoid.configuration.configMsg = false
}
]
}
Kirigami.InlineMessage {
Layout.fillWidth: true
icon.source: "apdatifier-package"
text: "<b>" + "<a href=\"" + packageLink + "\">checkupdates</a>" + i18n(" not installed! Highly recommended to install it for getting the latest updates without the need to download fresh package databases.") + "</b>"
type: Kirigami.MessageType.Error
onLinkActivated: Qt.openUrlExternally(packageLink)
visible: !pkg.checkupdates
}
Kirigami.FormLayout {
id: searchTab
visible: currentTab === 0
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: i18n("Interval") + ":"
CheckBox {
id: interval
}
SpinBox {
id: time
from: 15
to: 1440
stepSize: 5
value: time
enabled: interval.checked
}
Label {
text: i18n("minutes")
}
Kirigami.ContextualHelpButton {
toolTipText: i18n("The current timer is reset when either of these settings is changed.")
}
}
RowLayout {
CheckBox {
id: checkOnStartup
text: i18n("Check on start up")
enabled: interval.checked
}
Kirigami.ContextualHelpButton {
toolTipText: i18n("If the option is <b>enabled</b>, update checking will begin immediately upon widget startup.<br><br>If the option is <b>disabled</b>, update checking will be initiated after a specified time interval has passed since the widget was started. <b>Recommended.</b>")
}
}
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: i18n("Updates") + ":"
CheckBox {
id: arch
text: i18n("Arch Official Repositories")
enabled: pkg.pacman
onCheckedChanged: if (!checked) aur.checked = false
}
}
RowLayout {
spacing: Kirigami.Units.gridUnit
visible: pkg.pacman
CheckBox {
id: aur
text: i18n("Arch User Repository") + " (AUR)"
enabled: arch.checked && (pkg.paru || pkg.yay)
}
Kirigami.UrlButton {
url: "https://github.com/exequtic/apdatifier#supported-pacman-wrappers"
text: instTip.text
font.pointSize: instTip.font.pointSize
color: instTip.color
visible: !pkg.paru && !pkg.yay
}
}
RowLayout {
spacing: Kirigami.Units.gridUnit
CheckBox {
id: flatpak
text: i18n("Flatpak applications")
enabled: pkg.flatpak
}
Kirigami.UrlButton {
id: instTip
url: "https://flathub.org/setup"
text: i18n("Not installed")
font.pointSize: Kirigami.Theme.smallFont.pointSize
color: Kirigami.Theme.neutralTextColor
visible: !pkg.flatpak
}
}
RowLayout {
CheckBox {
id: widgets
text: i18n("Plasma Widgets")
enabled: pkg.jq
}
Kirigami.ContextualHelpButton {
toolTipText: i18n("Required installed") + " jq." + i18n("<br><br>For widget developers:<br>Don't forget to update the metadata.json and specify the name of the applet and its version <b>exactly</b> as they appear on the KDE Store.")
}
}
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: i18n("News") + ":"
CheckBox {
id: newsArch
text: i18n("Arch Linux News")
enabled: pkg.jq
}
}
CheckBox {
id: newsKDE
text: "KDE Announcements"
enabled: pkg.jq
}
CheckBox {
id: newsTWIK
text: "This Week in KDE"
enabled: pkg.jq
}
CheckBox {
id: newsTWIKA
text: "This Week in KDE Apps"
enabled: pkg.jq
}
RowLayout {
Label {
text: i18n("Keep")
}
SpinBox {
id: newsKeep
from: 1
to: 10
stepSize: 1
value: newsKeep
enabled: newsArch.checked || newsKDE.checked || newsTWIK.checked || newsTWIKA.checked
}
Label {
text: i18np("news item from the feed", "news items from the feed", newsKeep.value)
}
}
}
Kirigami.FormLayout {
id: notificationsTab
visible: currentTab === 1
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
spacing: Kirigami.Units.largeSpacing * 2
CheckBox {
Kirigami.FormData.label: i18n("Notifications") + ":"
id: notifyUpdates
text: i18n("For new updates")
}
CheckBox {
id: notifyUpdatesAction
text: i18n("Action button")
enabled: notifyUpdates.checked
}
}
RowLayout {
CheckBox {
id: notifyEveryBump
text: i18n("For every version bump")
enabled: notifyUpdates.checked
}
Kirigami.ContextualHelpButton {
toolTipText: i18n("If the option is <b>enabled</b>, notifications will be sent when a new version of the package is bumped, even if the package is already on the list. <b>More notifications.</b> <br><br>If the option is <b>disabled</b>, notifications will only be sent for packages that are not yet on the list. <b>Less notifications.</b>")
}
}
RowLayout {
spacing: Kirigami.Units.largeSpacing * 2
CheckBox {
id: notifyNews
text: i18n("For news")
}
CheckBox {
id: notifyNewsAction
text: i18n("Action button")
enabled: notifyNews.checked
}
}
CheckBox {
id: notifyErrors
text: i18n("For errors")
}
CheckBox {
id: notifySound
text: i18n("With sound")
enabled: notifyUpdates.checked || notifyNews.checked || notifyErrors.checked
}
CheckBox {
id: notifyPersistent
text: i18n("Persistent")
enabled: notifyUpdates.checked || notifyNews.checked || notifyErrors.checked
}
Item {
Kirigami.FormData.isSection: true
}
Kirigami.Separator {
Layout.fillWidth: true
}
RowLayout {
id: notifyTip
Label {
horizontalAlignment: Text.AlignHCenter
Layout.maximumWidth: 250
font.pointSize: instTip.font.pointSize
text: i18n("To further configure, click the button below -> Application Settings -> Apdatifier")
wrapMode: Text.WordWrap
}
}
Item {
Kirigami.FormData.isSection: true
}
Button {
anchors.horizontalCenter: notifyTip.horizontalCenter
enabled: notifyUpdates.checked || notifyNews.checked || notifyErrors.checked
icon.name: "settings-configure"
text: i18n("Configure...")
onClicked: KCMLauncher.openSystemSettings("kcm_notifications")
}
Item {
Kirigami.FormData.isSection: true
}
}
Kirigami.FormLayout {
id: mouseActionsTab
visible: currentTab === 2
Item {
Kirigami.FormData.isSection: true
}
QQC.ComboBox {
Kirigami.FormData.label: i18n("Middle click") + ":"
type: "middle"
}
QQC.ComboBox {
Kirigami.FormData.label: i18n("Right click") + ":"
type: "right"
Kirigami.ContextualHelpButton {
toolTipText: i18n("Do not enable this option if the widget is not used in the system tray; otherwise, you will not be able to open the settings by right-clicking.")
}
}
QQC.ComboBox {
Kirigami.FormData.label: i18n("Scroll up") + ":"
type: "scrollUp"
}
QQC.ComboBox {
Kirigami.FormData.label: i18n("Scroll down") + ":"
type: "scrollDown"
}
Item {
Kirigami.FormData.isSection: true
}
}
Kirigami.FormLayout {
id: miscTab
visible: currentTab === 3
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Layout.preferredWidth: miscTab.width - Kirigami.Units.largeSpacing * 10
Button {
Layout.fillWidth: true
Layout.maximumWidth: 500
icon.name: "backup"
text: i18n("Restore hidden tooltips")
onClicked: {
plasmoid.configuration.configMsg = true
plasmoid.configuration.rulesMsg = true
plasmoid.configuration.newsMsg = true
plasmoid.configuration.version = "v0"
}
}
}
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Layout.preferredWidth: miscTab.width - Kirigami.Units.largeSpacing * 10
Button {
Layout.fillWidth: true
Layout.maximumWidth: 500
icon.name: "folder-git-symbolic"
text: i18n("Install Development version")
onClicked: {
installButton = 0
installDialog.open()
}
}
}
RowLayout {
Layout.preferredWidth: miscTab.width - Kirigami.Units.largeSpacing * 10
Button {
Layout.fillWidth: true
Layout.maximumWidth: 500
icon.name: "run-build"
text: i18n("Install Stable version")
onClicked: {
installButton = 1
installDialog.open()
}
}
}
RowLayout {
Layout.preferredWidth: miscTab.width - Kirigami.Units.largeSpacing * 10
Button {
Layout.fillWidth: true
Layout.maximumWidth: 500
icon.name: "delete"
text: i18n("Uninstall widget")
onClicked: {
installButton = 2
installDialog.open()
}
}
}
Kirigami.PromptDialog {
id: installDialog
title: dialogTitles[installButton]
subtitle: dialogSubtitles[installButton]
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
onAccepted: {
if (installButton === 0) {
JS.execute(JS.runInTerminal("utils", "installDev"))
} else if (installButton === 1) {
JS.execute(JS.runInTerminal("utils", "installStable"))
} else {
JS.execute(JS.runInTerminal("utils", "uninstall"))
}
}
}
}
}
}

View File

@ -0,0 +1,212 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import org.kde.iconthemes
import org.kde.kirigami as Kirigami
import "../../tools/tools.js" as JS
ColumnLayout {
ListModel {
id: rulesModel
Component.onCompleted: {
JS.execute(JS.readFile(JS.rulesFile), (cmd, out, err, code) => {
if (JS.Error(code, err)) return
if (out && JS.validJSON(out, JS.rulesFile)) {
JSON.parse(out).forEach(el =>
rulesModel.append({
type: el.type,
value: el.value,
icon: el.icon,
excluded: el.excluded,
important: ('important' in el) ? el.important : false
})
)
}
})
}
}
ListModel {
id: typesModel
Component.onCompleted: {
let types = [
{name: i18n("Unimportant"), type: "all", tip: "---"},
{name: i18n("Repository"), type: "repo", tip: i18n("Exact repository match")},
{name: i18n("Group"), type: "group", tip: i18n("Substring group match")},
{name: i18n("Substring"), type: "match", tip: i18n("Substring name match")},
{name: i18n("Name"), type: "name", tip: i18n("Exact name match")}
]
for (var i = 0; i < types.length; ++i) {
typesModel.append({name: types[i].name, type: types[i].type, tip: types[i].tip})
}
}
}
Kirigami.InlineMessage {
id: rulesMsg
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.smallSpacing * 2
Layout.rightMargin: Kirigami.Units.smallSpacing * 2
icon.source: "showinfo"
text: i18n("Here you can override the default package icons and exclude them from the list. Each rule overwrites the previous one, so the list of rules should be in this order: ")+i18n("Unimportant")+", "+i18n("Repository")+", "+i18n("Group")+", "+i18n("Substring")+", "+i18n("Name")
visible: plasmoid.configuration.rulesMsg
actions: [
Kirigami.Action {
text: "OK"
icon.name: "checkmark"
onTriggered: plasmoid.configuration.rulesMsg = false
}
]
}
Component {
id: rule
ItemDelegate {
width: rulesList.width - Kirigami.Units.largeSpacing * 2
contentItem: RowLayout {
ComboBox {
implicitWidth: 200
id: type
model: typesModel
textRole: "name"
currentIndex: -1
onCurrentIndexChanged: {
if (currentIndex === 0) valueField.text = ""
rulesList.model.set(index, {"type": model.get(currentIndex).type})
}
Component.onCompleted: {
var currentType = rulesList.model.get(index).type
for (var i = 0; i < model.count; ++i) {
if (model.get(i).type === currentType) {
currentIndex = i
break
}
}
}
}
TextField {
id: valueField
Layout.fillWidth: true
text: model.value
placeholderText: type.model.get(type.currentIndex).tip
enabled: type.currentIndex !== 0
onTextChanged: {
var allow = /^[a-z0-9_\-+.]*$/
var filtered = valueField.text.replace(/[^a-z0-9_\-+.]/g, "")
if (valueField.text !== filtered) {
valueField.text = filtered
return
}
if (model.value !== valueField.text) {
model.value = valueField.text
}
}
}
ToolButton {
ToolTip { text: model.icon }
icon.name: model.icon
onClicked: iconDialog.open()
IconDialog {
id: iconDialog
onIconNameChanged: model.icon = iconName
}
}
ToolButton {
ToolTip { text: i18n("Mark as important") }
icon.name: model.important ? "flag-red" : "flag"
onClicked: model.important = !model.important
}
ToolButton {
ToolTip { text: model.excluded ? i18n("Show in the list") : i18n("Exclude from the list") }
icon.name: model.excluded ? "view-visible" : "hint"
onClicked: model.excluded = !model.excluded
}
ToolButton {
icon.name: 'arrow-up'
enabled: index > 0
onClicked: rulesList.model.move(index, index - 1, 1)
}
ToolButton {
icon.name: 'arrow-down'
enabled: index > -1 && index < rulesList.model.count - 1
onClicked: rulesList.model.move(index, index + 1, 1)
}
ToolButton {
ToolTip { text: i18n("Remove") }
icon.name: 'delete'
onClicked: rulesList.model.remove(index)
}
}
}
}
ListView {
Layout.fillHeight: true
Layout.fillWidth: true
id: rulesList
model: rulesModel
delegate: rule
clip: true
boundsBehavior: Flickable.StopAtBounds
add: Transition { NumberAnimation { properties: "x"; from: 100; duration: 300 } }
moveDisplaced: Transition { NumberAnimation { properties: "x,y"; duration: 300 } }
move: Transition { NumberAnimation { properties: "x,y"; duration: 300 } }
removeDisplaced: Transition { NumberAnimation { properties: "x,y"; duration: 300 } }
remove: Transition { ParallelAnimation {
NumberAnimation { property: "opacity"; to: 0; duration: 300 }
NumberAnimation { properties: "x"; to: 100; duration: 300 } } }
ScrollBar.vertical: ScrollBar { active: true }
}
RowLayout {
Layout.alignment: Qt.AlignHCenter
Button {
text: i18n("Add rule")
icon.name: "list-add"
onClicked: {
rulesModel.append({
type: "name",
value: "",
icon: plasmoid.configuration.ownIconsUI ? "apdatifier-package" : "server-database",
excluded: false,
important: false
})
}
}
Button {
text: i18n("Apply")
icon.name: "dialog-ok-apply"
onClicked: {
var array = []
for (var i = rulesModel.count - 1; i >= 0; --i) {
if (rulesModel.get(i).type !== "all" && rulesModel.get(i).value.trim() === "") rulesModel.remove(i, 1);
}
for (var i = 0; i < rulesModel.count; i++) {
array.push(rulesModel.get(i))
}
var rules = JS.toFileFormat(array)
plasmoid.configuration.rules = rules
JS.execute(JS.writeFile(rules, '>', JS.rulesFile))
}
}
}
}

View File

@ -0,0 +1,94 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import org.kde.kirigami as Kirigami
Kirigami.Page {
id: supportPage
leftPadding: Kirigami.Units.gridUnit
rightPadding: Kirigami.Units.gridUnit
header: Item {
height: layout.implicitHeight + (Kirigami.Units.gridUnit * 2)
ColumnLayout {
id: layout
width: parent.width - (Kirigami.Units.gridUnit * 2)
anchors.centerIn: parent
Label {
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
text: i18n("Thanks for using my widget! If you appreciate my work, you can support me by starring the GitHub repository or buying me a coffee ;)")
wrapMode: Text.WordWrap
}
}
}
RowLayout {
anchors.centerIn: parent
Layout.fillWidth: true
Layout.fillHeight: true
Kirigami.UrlButton {
id: buymeacoffee
url: "https://buymeacoffee.com/evgk"
visible: false
}
Kirigami.UrlButton {
id: github
url: "https://github.com/exequtic/apdatifier"
visible: false
}
Image {
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
source: "../assets/art/apdatifier-donate.png"
sourceSize.width: supportPage.width / 2
sourceSize.height: supportPage.height
HoverHandler {
id: handlerCoffee
cursorShape: Qt.PointingHandCursor
}
TapHandler {
onTapped: Qt.openUrlExternally(buymeacoffee.url)
}
ToolTip {
visible: handlerCoffee.hovered
text: i18n("Visit %1", buymeacoffee.url)
}
}
Image {
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
source: "../assets/art/apdatifier-githubstar.png"
sourceSize.width: supportPage.width / 2
sourceSize.height: supportPage.height
HoverHandler {
id: handlerGithub
cursorShape: Qt.PointingHandCursor
}
TapHandler {
onTapped: Qt.openUrlExternally(github.url)
}
ToolTip {
visible: handlerGithub.hovered
text: i18n("Visit %1", github.url)
}
}
}
}

View File

@ -0,0 +1,712 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Dialogs
import org.kde.kcmutils
import org.kde.kirigami as Kirigami
import "../../tools/tools.js" as JS
SimpleKCM {
property string cfg_terminal: plasmoid.configuration.terminal
property alias cfg_tmuxSession: tmuxSession.checked
property alias cfg_idleInhibit: idleInhibit.checked
property alias cfg_termFont: termFont.checked
property string cfg_wrapper: plasmoid.configuration.wrapper
property alias cfg_archFlags: archFlags.text
property alias cfg_sudoBin: sudoBin.text
property alias cfg_rebootSystem: rebootSystem.checked
property string cfg_mirrors: plasmoid.configuration.mirrors
property alias cfg_mirrorsAge: mirrorsAge.value
property alias cfg_mirrorCount: mirrorCount.value
property var countryList: []
property string cfg_dynamicUrl: plasmoid.configuration.dynamicUrl
property alias cfg_flatpakRemoveUnused: flatpakRemoveUnused.checked
property string cfg_flatpakFlags: plasmoid.configuration.flatpakFlags
property alias cfg_widgetConfirmation: widgetConfirmation.checked
property alias cfg_restartShell: restartShell.checked
property alias cfg_restartCommand: restartCommand.text
property alias cfg_trayEnabledByDefault: trayEnabledByDefault.checked
property var pkg: plasmoid.configuration.packages
property var terminals: plasmoid.configuration.terminals
property alias cfg_preExec: preExec.text
property alias cfg_postExec: postExec.text
property int currentTab
signal tabChanged(currentTab: int)
onCurrentTabChanged: tabChanged(currentTab)
header: Kirigami.NavigationTabBar {
actions: [
Kirigami.Action {
icon.name: "akonadiconsole"
text: i18n("General")
checked: currentTab === 0
onTriggered: currentTab = 0
},
Kirigami.Action {
icon.name: "apdatifier-package"
text: "Arch"
checked: currentTab === 1
onTriggered: currentTab = 1
},
Kirigami.Action {
icon.name: "apdatifier-flatpak"
text: "Flatpak"
checked: currentTab === 2
onTriggered: currentTab = 2
},
Kirigami.Action {
icon.name: "start-here-kde-plasma-symbolic"
text: i18n("Widgets")
checked: currentTab === 3
onTriggered: currentTab = 3
}
]
}
Kirigami.FormLayout {
id: terminalTab
visible: currentTab === 0
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: i18n("Terminal") + ":"
ComboBox {
model: terminals
textRole: "name"
enabled: terminals
onCurrentIndexChanged: cfg_terminal = model[currentIndex]["value"]
Component.onCompleted: {
if (terminals) {
currentIndex = JS.setIndex(plasmoid.configuration.terminal, terminals)
if (!plasmoid.configuration.terminal) {
plasmoid.configuration.terminal = model[0]["value"]
}
}
}
}
Kirigami.UrlButton {
url: "https://github.com/exequtic/apdatifier#supported-terminals"
text: i18n("Not installed")
font.pointSize: Kirigami.Theme.smallFont.pointSize
color: Kirigami.Theme.neutralTextColor
visible: !terminals
}
}
RowLayout {
CheckBox {
id: termFont
text: i18n("Use NerdFont icons")
}
Kirigami.ContextualHelpButton {
toolTipText: i18n("If your terminal utilizes any <b>Nerd Font</b>, icons from that font will be used.")
}
}
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
CheckBox {
id: tmuxSession
text: i18n("tmux session")
enabled: pkg.tmux
}
}
RowLayout {
CheckBox {
id: idleInhibit
text: "Idle Inhibit"
}
Kirigami.ContextualHelpButton {
toolTipText: "Disables automatic sleep and screen lock while upgrading."
}
}
Kirigami.Separator {
Kirigami.FormData.label: i18n("Pre/post upgrade scripts")
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: i18n("Pre-exec") + ":"
TextField {
id: preExec
placeholderText: i18n("Command or script path")
placeholderTextColor: "grey"
}
Button {
icon.name: "document-open"
onClicked: fileDialogPreExec.open()
}
FileDialog {
id: fileDialogPreExec
fileMode: FileDialog.OpenFile
onAccepted: preExec.text = selectedFile.toString().substring(7)
}
Kirigami.ContextualHelpButton {
toolTipText: i18n("Running your command or script BEFORE the upgrade.<br>For example, you can specify your command to update the mirrorlist if you have unofficial repositories.")
}
}
RowLayout {
Kirigami.FormData.label: i18n("Post-exec") + ":"
TextField {
id: postExec
placeholderText: i18n("Command or script path")
placeholderTextColor: "grey"
}
Button {
icon.name: "document-open"
onClicked: fileDialogPostExec.open()
}
FileDialog {
id: fileDialogPostExec
fileMode: FileDialog.OpenFile
onAccepted: postExec.text = selectedFile.toString().substring(7)
}
Kirigami.ContextualHelpButton {
toolTipText: i18n("Running your command or script AFTER the upgrade.<br>For example, you can specify your command to upgrade something else.")
}
}
}
Kirigami.FormLayout {
id: archTab
visible: currentTab === 1
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
enabled: plasmoid.configuration.aur
Kirigami.FormData.label: i18n("Wrapper") + ":"
spacing: Kirigami.Units.largeSpacing * 2
ButtonGroup {
id: wrappersGroup
}
RadioButton {
ButtonGroup.group: wrappersGroup
text: "paru"
enabled: pkg.paru
onCheckedChanged: cfg_wrapper = checked ? "paru" : "yay"
Component.onCompleted: checked = plasmoid.configuration.wrapper === text
}
RadioButton {
ButtonGroup.group: wrappersGroup
text: "yay"
enabled: pkg.yay
Component.onCompleted: checked = plasmoid.configuration.wrapper === text
}
}
RowLayout {
visible: !plasmoid.configuration.aur
Label {
horizontalAlignment: Text.AlignHCenter
font.pointSize: Kirigami.Theme.smallFont.pointSize
font.bold: true
color: Kirigami.Theme.negativeTextColor
text: i18n("AUR disabled in search settings")
}
}
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: i18n("Upgrade options") + ":"
Label {
text: plasmoid.configuration.aur ? cfg_wrapper+" "+"-Syu" : cfg_sudoBin+" "+"pacman -Syu"
}
TextField {
id: archFlags
onTextChanged: {
var allow = /^[a-z\- ]*$/
if (!allow.test(archFlags.text))
archFlags.text = archFlags.text.replace(/[^a-z\- ]/g, "")
}
}
}
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: "sudobin:"
spacing: 0
enabled: pkg.pacman
TextField {
id: sudoBin
}
}
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: i18n("Reboot system") + ":"
CheckBox {
id: rebootSystem
text: i18n("Suggest after upgrading")
}
Kirigami.ContextualHelpButton {
toolTipText: "This option suggests restarting the system after upgrading critical packages.<br><br><b>Note that not all critical packages require a full system restart; some may only need a session restart or no action at all, such as when an updated package is not currently running (e.g., an alternative kernel) or not in use (e.g., an alternative driver).</b>"
}
}
Kirigami.Separator {
Kirigami.FormData.label: i18n("Pacman Mirrorlist Generator")
Kirigami.FormData.isSection: true
}
RowLayout {
height: 30
Label {
horizontalAlignment: Text.AlignHCenter
font.pointSize: Kirigami.Theme.smallFont.pointSize
font.bold: true
color: Kirigami.Theme.negativeTextColor
text: i18n("Only for official repositories")
}
Kirigami.ContextualHelpButton {
toolTipText: i18n("Required installed") + " pacman-contrib." + i18n("<br><br>Also see https://archlinux.org/mirrorlist (click button to open link)")
onClicked: Qt.openUrlExternally("https://archlinux.org/mirrorlist")
}
}
Item {
Layout.preferredHeight: Kirigami.Units.smallSpacing * 2
}
ButtonGroup {
id: generator
}
RowLayout{
Kirigami.FormData.label: i18n("Generator") + ":"
RadioButton {
ButtonGroup.group: generator
id: mirrors
text: i18n("Disabled")
enabled: pkg.pacman && pkg.checkupdates
checked: {
plasmoid.configuration.mirrors === "false"
}
onCheckedChanged: {
if (checked) cfg_mirrors = "false"
}
Component.onCompleted: {
if (!checked && !enabled) {
checked = true
plasmoid.configuration.mirrors = "false"
}
}
}
}
RadioButton {
ButtonGroup.group: generator
text: i18n("Always ask")
enabled: mirrors.enabled
checked: plasmoid.configuration.mirrors === "alwaysAsk"
onCheckedChanged: {
if (checked) cfg_mirrors = "alwaysAsk"
}
}
RowLayout{
enabled: mirrors.enabled
RadioButton {
ButtonGroup.group: generator
text: i18n("Ask if older than")
checked: plasmoid.configuration.mirrors === "age"
onCheckedChanged: {
if (checked) cfg_mirrors = "age"
}
}
SpinBox {
id: mirrorsAge
from: 1
to: 999
stepSize: 1
value: mirrorsAge
}
Label {
text: i18np("day", "days", mirrorsAge.value)
}
}
RadioButton {
ButtonGroup.group: generator
text: i18n("No ask, force refresh")
enabled: mirrors.enabled
checked: plasmoid.configuration.mirrors === "force"
onCheckedChanged: {
if (checked) cfg_mirrors = "force"
}
}
Item {
Layout.preferredHeight: Kirigami.Units.smallSpacing * 2
}
RowLayout {
Kirigami.FormData.label: i18n("Protocol") + ":"
CheckBox {
id: http
text: "http"
onClicked: updateUrl()
enabled: mirrors.enabled
}
CheckBox {
id: https
text: "https"
onClicked: updateUrl()
enabled: mirrors.enabled
}
}
RowLayout {
Kirigami.FormData.label: i18n("IP version") + ":"
CheckBox {
id: ipv4
text: "IPv4"
onClicked: updateUrl()
enabled: mirrors.enabled
}
CheckBox {
id: ipv6
text: "IPv6"
onClicked: updateUrl()
enabled: mirrors.enabled
}
}
CheckBox {
Kirigami.FormData.label: i18n("Mirror status") + ":"
id: mirrorstatus
text: i18n("Enable")
onClicked: updateUrl()
enabled: mirrors.enabled
}
RowLayout {
Kirigami.FormData.label: i18n("Number output") + ":"
SpinBox {
id: mirrorCount
from: 0
to: 10
stepSize: 1
value: mirrorCount
enabled: mirrors.enabled
}
Kirigami.ContextualHelpButton {
toolTipText: i18n("Number of servers to write to mirrorlist file. 0 for all.")
}
}
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: i18n("Country") + ":"
Label {
textFormat: Text.RichText
text: {
var matchResult = cfg_dynamicUrl.match(/country=([A-Z]+)/g)
if (matchResult !== null) {
var countries = matchResult.map(str => str.split("=")[1]).join(", ")
return countries
} else {
return '<a style="color: ' + Kirigami.Theme.negativeTextColor + '">' + i18n("Select at least one!") + '</a>'
}
}
}
Kirigami.ContextualHelpButton {
toolTipText: i18n("You must select at least one country, otherwise all will be chosen by default. <br><br><b>The more countries you select, the longer it will take to generate the mirrors!</b> <br><br>It is optimal to choose <b>1-2</b> countries closest to you.")
}
}
ColumnLayout {
Layout.maximumWidth: archTab.width / 2.5
Layout.maximumHeight: 200
enabled: mirrors.enabled
ScrollView {
Layout.preferredWidth: archTab.width / 2.5
Layout.preferredHeight: 200
GridLayout {
columns: 1
Repeater {
model: countryListModel
delegate: CheckBox {
text: model.text
checked: model.checked
onClicked: {
model.checked = checked
checked ? countryList.push(model.code) : countryList.splice(countryList.indexOf(model.code), 1)
updateUrl()
}
}
}
}
}
}
Item {
Kirigami.FormData.isSection: true
}
}
Kirigami.FormLayout {
id: flatpakTab
visible: currentTab === 2
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: i18n("Uninstall unused") + ":"
CheckBox {
id: flatpakRemoveUnused
text: i18n("Enable")
}
}
Item {
Kirigami.FormData.isSection: true
}
ButtonGroup {
id: flatpakFlags
}
RowLayout{
Kirigami.FormData.label: i18n("Upgrade options") + ":"
RadioButton {
ButtonGroup.group: flatpakFlags
text: i18n("Normal")
checked: plasmoid.configuration.flatpakFlags === ""
onCheckedChanged: {
if (checked) cfg_flatpakFlags = ""
}
}
}
RadioButton {
ButtonGroup.group: flatpakFlags
text: i18n("Normal, skip questions")
checked: plasmoid.configuration.flatpakFlags === "--assumeyes"
onCheckedChanged: {
if (checked) cfg_flatpakFlags = "--assumeyes"
}
}
RadioButton {
ButtonGroup.group: flatpakFlags
text: i18n("Non interactive, skip questions")
checked: plasmoid.configuration.flatpakFlags === "--noninteractive"
onCheckedChanged: {
if (checked) cfg_flatpakFlags = "--noninteractive"
}
}
RadioButton {
ButtonGroup.group: flatpakFlags
text: i18n("Verbose")
checked: plasmoid.configuration.flatpakFlags === "--verbose"
onCheckedChanged: {
if (checked) cfg_flatpakFlags = "--verbose"
}
}
}
Kirigami.FormLayout {
id: widgetsTab
visible: currentTab === 3
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: i18n("Upgrade confirmation") + ":"
CheckBox {
id: widgetConfirmation
text: i18n("Enable")
}
}
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: i18n("Restart plasmashell") + ":"
CheckBox {
id: restartShell
text: i18n("Suggest after upgrading")
}
Kirigami.ContextualHelpButton {
toolTipText: i18n("After upgrading widget, the old version will still remain in memory until you restart plasmashell. To avoid doing this manually, enable this option.")
}
}
RowLayout {
Kirigami.FormData.label: i18n("Command") + ":"
TextField {
id: restartCommand
enabled: restartShell.checked
}
}
Item {
Kirigami.FormData.isSection: true
}
RowLayout {
Kirigami.FormData.label: i18n("Apdatifier tray icon") + ":"
CheckBox {
id: trayEnabledByDefault
text: i18n("Enabled by default")
}
}
}
Component.onCompleted: {
if (tmuxSession.checked && !pkg.tmux) tmuxSession.checked = plasmoid.configuration.tmuxSession = false
if(cfg_dynamicUrl) {
var urlParams = plasmoid.configuration.dynamicUrl.split("?")[1].split("&")
for (var i = 0; i < urlParams.length; i++) {
var param = urlParams[i]
if (param.includes("use_mirror_status=on")) mirrorstatus.checked = true
if (/protocol=http\b/.test(param)) http.checked = true
if (param.includes("protocol=https")) https.checked = true
if (param.includes("ip_version=4")) ipv4.checked = true
if (param.includes("ip_version=6")) ipv6.checked = true
if (param.includes("country=")) {
var country = decodeURIComponent(param.split("=")[1])
countryList.push(country)
for (var j = 0; j < countryListModel.count; ++j) {
if (countryListModel.get(j).code === country) {
countryListModel.get(j).checked = true
}
}
}
}
}
}
function updateUrl() {
var params = ""
if (http.checked) params += "&protocol=http"
if (https.checked) params += "&protocol=https"
if (ipv4.checked) params += "&ip_version=4"
if (ipv6.checked) params += "&ip_version=6"
if (mirrorstatus.checked) params += "&use_mirror_status=on"
for (var i = 0; i < countryList.length; i++) {
params += "&country=" + countryList[i]
}
var baseUrl = "https://archlinux.org/mirrorlist/?"
cfg_dynamicUrl = baseUrl + params.substring(1)
}
ListModel {
id: countryListModel
function createCountryList() {
let countries =
"Australia:AU, Austria:AT, Azerbaijan:AZ, Bangladesh:BD, Belarus:BY, Belgium:BE, " +
"Bosnia and Herzegovina:BA, Brazil:BR, Bulgaria:BG, Cambodia:KH, Canada:CA, Chile:CL, " +
"China:CN, Colombia:CO, Croatia:HR, Czech Republic:CZ, Denmark:DK, Ecuador:EC, " +
"Estonia:EE, Finland:FI, France:FR, Georgia:GE, Germany:DE, Greece:GR, Hong Kong:HK, " +
"Hungary:HU, Iceland:IS, India:IN, Indonesia:ID, Iran:IR, Israel:IL, Italy:IT, Japan:JP, " +
"Kazakhstan:KZ, Kenya:KE, Latvia:LV, Lithuania:LT, Luxembourg:LU, Mauritius:MU, Mexico:MX, " +
"Moldova:MD, Monaco:MC, Netherlands:NL, New Caledonia:NC, New Zealand:NZ, North Macedonia:MK, " +
"Norway:NO, Paraguay:PY, Poland:PL, Portugal:PT, Romania:RO, Russia:RU, Réunion:RE, " +
"Serbia:RS, Singapore:SG, Slovakia:SK, Slovenia:SI, South Africa:ZA, South Korea:KR, Spain:ES, " +
"Sweden:SE, Switzerland:CH, Taiwan:TW, Thailand:TH, Turkey:TR, Ukraine:UA, United Kingdom:GB, " +
"United States:US, Uzbekistan:UZ, Vietnam:VN"
countries.split(", ").map(item => {
let [country, code] = item.split(":")
countryListModel.append({text: country, code: code, checked: false})
})
}
Component.onCompleted: createCountryList()
}
}

View File

@ -0,0 +1,138 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import QtQuick.Layouts
import org.kde.plasma.plasmoid
import org.kde.kirigami as Kirigami
import org.kde.plasma.core as PlasmaCore
import "components"
import "representation" as Rep
import "../tools/tools.js" as JS
PlasmoidItem {
id: root
compactRepresentation: Rep.Panel {}
fullRepresentation: Rep.Expanded {
Layout.minimumWidth: Kirigami.Units.gridUnit * 24
Layout.minimumHeight: Kirigami.Units.gridUnit * 16
anchors.fill: parent
focus: true
}
switchWidth: Kirigami.Units.gridUnit * 24
switchHeight: Kirigami.Units.gridUnit * 16
Plasmoid.busy: plasmoid.location === PlasmaCore.Types.Floating ? false : States.busy
Plasmoid.status: cfg.relevantIcon > 0 ? (sts.count >= cfg.relevantIcon || sts.busy || sts.err) ? PlasmaCore.Types.ActiveStatus : PlasmaCore.Types.PassiveStatus : PlasmaCore.Types.ActiveStatus
Plasmoid.backgroundHints: PlasmaCore.Types.DefaultBackground | PlasmaCore.Types.ConfigurableBackground
Plasmoid.icon: plasmoid.configuration.selectedIcon
toolTipMainText: !interval && sts.idle ? i18n("Auto check disabled") : ""
toolTipSubText: sts.busy ? sts.statusMsg : sts.err ? sts.errMsg : sts.checktime
property var check
property var cache: []
property int time: plasmoid.configuration.time
property bool interval: plasmoid.configuration.interval
property bool sorting: plasmoid.configuration.sorting
property string rules: plasmoid.configuration.rules || ""
property var pkg: plasmoid.configuration.packages || ""
property var cfg: plasmoid.configuration
property var configuration: JSON.stringify(cfg)
QtObject {
id: sts
property int count: 0
property bool busy: false
property bool upgrading: false
property bool err: !!errMsg
property bool idle: !busy && !err
property bool updated: idle && !count
property bool pending: idle && count
property bool paused: idle && cfg.indicatorStop && !cfg.interval
property string errMsg: ""
property string statusMsg: ""
property string statusIco: ""
property string checktime: ""
}
ListModel {
id: listModel
}
ListModel {
id: newsModel
}
ListModel {
id: activeNewsModel
}
Notification {
id: notify
}
Plasmoid.contextualActions: [
PlasmaCore.Action {
text: i18n("Check updates")
icon.name: "view-refresh"
enabled: !sts.upgrading
onTriggered: JS.checkUpdates()
},
PlasmaCore.Action {
text: i18n("Upgrade system")
icon.name: "akonadiconsole"
enabled: (cfg.terminal && cfg.tmuxSession && sts.count) || (cfg.terminal && sts.pending)
onTriggered: JS.upgradeSystem()
},
PlasmaCore.Action {
text: i18n("Management")
icon.name: "tools"
enabled: cfg.terminal && pkg.pacman
onTriggered: JS.management()
}
]
Timer {
id: searchTimer
interval: time * 1000 * 60
repeat: true
onTriggered: JS.checkUpdates()
}
Timer {
id: upgradeTimer
interval: 1000
repeat: true
onTriggered: JS.upgradingState()
}
Timer {
id: saveTimer
interval: 1000
onTriggered: JS.saveConfig()
}
Timer {
id: initTimer
running: true
interval: 50
}
function refresh() {
if (initTimer.running) return
JS.refreshListModel()
}
onTimeChanged: searchTimer.restart()
onIntervalChanged: interval ? searchTimer.start() : searchTimer.stop()
onSortingChanged: refresh()
onRulesChanged: refresh()
onConfigurationChanged: saveTimer.start()
Component.onCompleted: JS.init()
}

View File

@ -0,0 +1,374 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import QtQuick.Layouts
import org.kde.kitemmodels
import org.kde.plasma.extras
import org.kde.plasma.plasmoid
import org.kde.plasma.components
import org.kde.kirigami as Kirigami
import org.kde.plasma.core as PlasmaCore
import "../scrollview" as View
import "../../tools/tools.js" as JS
Representation {
property string currVersion: "v2.9.4"
property bool searchFieldOpen: false
property bool expanded: root.expanded
onExpandedChanged: {
if (plasmoid.configuration.switchDefaultTab && !expanded)
swipeView.currentIndex = plasmoid.configuration.defaultTab
}
property string statusIcon: {
var icons = {
"0": cfg.ownIconsUI ? "status_error" : "error",
"1": cfg.ownIconsUI ? "status_pending" : "accept_time_event",
"2": cfg.ownIconsUI ? "status_blank" : ""
}
return icons[sts.statusIco] !== undefined ? icons[sts.statusIco] : sts.statusIco
}
function svg(icon) {
return Qt.resolvedUrl("../assets/icons/" + icon + ".svg")
}
property var backgroundHidden: (Plasmoid.formFactor === PlasmaCore.Types.Planar) && (Plasmoid.userBackgroundHints === PlasmaCore.Types.ShadowBackground)
onBackgroundHiddenChanged: topHeader.background.visible = bottomHeader.background.visible = !backgroundHidden
header: PlasmoidHeading {
id: topHeader
visible: cfg.showStatusText || cfg.showToolBar
contentItem: RowLayout {
id: toolBar
Layout.fillWidth: true
Layout.minimumHeight: Kirigami.Units.iconSizes.medium
Layout.maximumHeight: Kirigami.Units.iconSizes.medium
RowLayout {
id: status
Layout.alignment: cfg.showToolBar ? Qt.AlignLeft : Qt.AlignHCenter
spacing: Kirigami.Units.smallSpacing / 2
visible: cfg.showStatusText
Item {
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
Kirigami.Icon {
height: parent.height
width: parent.height
anchors.centerIn: parent
source: cfg.ownIconsUI ? svg(statusIcon) : statusIcon
color: Kirigami.Theme.colorSet
scale: cfg.ownIconsUI ? 0.7 : 0.9
isMask: cfg.ownIconsUI
smooth: true
}
}
Label {
Layout.maximumWidth: toolBar.width - toolBarButtons.width - Kirigami.Units.iconSizes.smallMedium
Layout.alignment: Qt.AlignLeft
text: sts.statusMsg
elide: Text.ElideRight
font.bold: true
}
}
RowLayout {
id: toolBarButtons
Layout.alignment: Qt.AlignRight
spacing: Kirigami.Units.smallSpacing
visible: cfg.showToolBar
ToolButton {
id: searchButton
ToolTip {text: i18n("Filter by package name")}
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
hoverEnabled: enabled
highlighted: enabled
visible: cfg.searchButton && sts.pending
enabled: visible && swipeView.currentIndex != 2
onClicked: {
if (searchFieldOpen) searchField.text = ""
searchFieldOpen = !searchField.visible
searchField.focus = searchFieldOpen
}
Kirigami.Icon {
height: parent.height
width: parent.height
anchors.centerIn: parent
source: cfg.ownIconsUI ? svg("toolbar_search") : "search"
color: Kirigami.Theme.colorSet
scale: cfg.ownIconsUI ? 0.7 : 0.9
isMask: cfg.ownIconsUI
smooth: true
}
}
ToolButton {
ToolTip {text: cfg.interval ? i18n("Disable auto search updates") : i18n("Enable auto search updates")}
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
hoverEnabled: enabled
highlighted: enabled
enabled: sts.idle
visible: enabled && cfg.intervalButton
onClicked: JS.switchInterval()
Kirigami.Icon {
height: parent.height
width: parent.height
anchors.centerIn: parent
source: cfg.ownIconsUI
? (cfg.interval ? svg("toolbar_pause") : svg("toolbar_start"))
: (cfg.interval ? "media-playback-paused" : "media-playback-playing")
color: !cfg.interval && !cfg.indicatorStop ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.colorSet
scale: cfg.ownIconsUI ? 0.7 : 0.9
isMask: cfg.ownIconsUI
smooth: true
}
}
ToolButton {
ToolTip {text: cfg.sorting ? i18n("Sort packages by name") : i18n("Sort packages by repository")}
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
hoverEnabled: enabled
highlighted: enabled
visible: cfg.sortButton && sts.pending
enabled: visible && swipeView.currentIndex != 2
onClicked: cfg.sorting = !cfg.sorting
Kirigami.Icon {
height: parent.height
width: parent.height
anchors.centerIn: parent
source: cfg.ownIconsUI ? svg("toolbar_sort") : "sort-name"
color: Kirigami.Theme.colorSet
scale: cfg.ownIconsUI ? 0.7 : 0.9
isMask: cfg.ownIconsUI
smooth: true
}
}
ToolButton {
ToolTip { id: managementTip; text: i18n("Management")}
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
hoverEnabled: enabled
highlighted: enabled
enabled: sts.idle && pkg.pacman !== "" && cfg.terminal
visible: enabled && cfg.managementButton
onClicked: { managementTip.hide(); JS.management() }
Kirigami.Icon {
height: parent.height
width: parent.height
anchors.centerIn: parent
source: cfg.ownIconsUI ? svg("toolbar_management") : "tools"
color: Kirigami.Theme.colorSet
scale: cfg.ownIconsUI ? 0.7 : 0.9
isMask: cfg.ownIconsUI
smooth: true
}
}
ToolButton {
ToolTip { id: upgradeTip; text: i18n("Upgrade system")}
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
hoverEnabled: enabled
highlighted: enabled
enabled: sts.pending && cfg.terminal
visible: enabled && cfg.upgradeButton
onClicked: { upgradeTip.hide(); JS.upgradeSystem() }
Kirigami.Icon {
height: parent.height
width: parent.height
anchors.centerIn: parent
source: cfg.ownIconsUI ? svg("toolbar_upgrade") : "akonadiconsole"
color: Kirigami.Theme.colorSet
scale: cfg.ownIconsUI ? 0.7 : 0.9
isMask: cfg.ownIconsUI
smooth: true
}
}
ToolButton {
ToolTip {text: sts.busy ? i18n("Stop checking") : i18n("Check updates")}
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
hoverEnabled: enabled
highlighted: enabled
visible: cfg.checkButton && !sts.upgrading
onClicked: JS.checkUpdates()
Kirigami.Icon {
height: parent.height
width: parent.height
anchors.centerIn: parent
source: cfg.ownIconsUI ? (sts.busy ? svg("toolbar_stop") : svg("toolbar_check"))
: (sts.busy ? "media-playback-stopped" : "view-refresh")
color: Kirigami.Theme.colorSet
scale: cfg.ownIconsUI ? 0.7 : 0.9
isMask: cfg.ownIconsUI
smooth: true
}
}
}
}
}
footer: PlasmoidHeading {
id: bottomHeader
spacing: 0
topPadding: 0
height: Kirigami.Units.iconSizes.medium
visible: cfg.tabBarVisible
contentItem: TabBar {
id: tabBar
Layout.fillWidth: true
Layout.fillHeight: true
position: TabBar.Footer
currentIndex: swipeView.currentIndex
onCurrentIndexChanged: {
swipeView.currentIndex = currentIndex
if (swipeView.currentIndex === 2) {
searchFieldOpen = false
searchField.text = ""
}
}
TabButton {
id: compactViewTab
ToolTip { text: cfg.tabBarTexts ? "" : i18n("Compact view") }
contentItem: RowLayout {
Kirigami.Theme.inherit: true
Item { Layout.fillWidth: true }
Kirigami.Icon {
Layout.preferredHeight: Kirigami.Units.iconSizes.small
Layout.preferredWidth: Kirigami.Units.iconSizes.small
source: cfg.ownIconsUI ? svg("tab_compact") : "view-split-left-right"
color: Kirigami.Theme.colorSet
isMask: cfg.ownIconsUI
smooth: true
}
Label { text: i18n("Compact"); visible: cfg.tabBarTexts }
Item { Layout.fillWidth: true }
}
}
TabButton {
id: extendViewTab
ToolTip { text: cfg.tabBarTexts ? "" : i18n("Extended view") }
contentItem: RowLayout {
Kirigami.Theme.inherit: true
Item { Layout.fillWidth: true }
Kirigami.Icon {
Layout.preferredHeight: Kirigami.Units.iconSizes.small
Layout.preferredWidth: Kirigami.Units.iconSizes.small
source: cfg.ownIconsUI ? svg("tab_extended") : "view-split-top-bottom"
color: Kirigami.Theme.colorSet
isMask: cfg.ownIconsUI
smooth: true
}
Label { text: i18n("Extended"); visible: cfg.tabBarTexts }
Item { Layout.fillWidth: true }
}
}
TabButton {
id: newsViewTab
ToolTip { text: cfg.tabBarTexts ? "" : i18n("News") }
contentItem: RowLayout {
Kirigami.Theme.inherit: true
Item { Layout.fillWidth: true }
Kirigami.Icon {
id: newsIcon
Layout.preferredHeight: Kirigami.Units.iconSizes.small
Layout.preferredWidth: Kirigami.Units.iconSizes.small
source: cfg.ownIconsUI ? svg("status_news") : "news-subscribe"
color: activeNewsModel.count > 0 ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.colorSet
isMask: cfg.ownIconsUI
smooth: true
}
Label { text: i18n("News"); visible: cfg.tabBarTexts }
Item { Layout.fillWidth: true }
}
}
}
}
ColumnLayout {
anchors.fill: parent
spacing: 0
TextField {
Layout.fillWidth: true
Layout.topMargin: Kirigami.Units.smallSpacing * 2
Layout.bottomMargin: Kirigami.Units.smallSpacing * 2
Layout.leftMargin: Kirigami.Units.smallSpacing * 2
Layout.rightMargin: Kirigami.Units.smallSpacing * 2
id: searchField
clearButtonShown: true
visible: searchFieldOpen && sts.pending
placeholderText: i18n("Filter by package name")
onTextChanged: modelList.setFilterFixedString(text)
}
Kirigami.InlineMessage {
Layout.fillWidth: true
Layout.topMargin: Kirigami.Units.smallSpacing * 2
Layout.bottomMargin: Kirigami.Units.smallSpacing * 2
text: "<b>" + i18n("Check out release notes")+" "+currVersion+"</b>"
type: Kirigami.MessageType.Positive
visible: !searchFieldOpen &&
plasmoid.configuration.version.localeCompare(currVersion, undefined, { numeric: true, sensitivity: 'base' }) < 0
actions: [
Kirigami.Action {
tooltip: i18n("Select...")
icon.name: "application-menu"
expandible: true
Kirigami.Action {
text: "GitHub"
icon.name: "internet-web-browser-symbolic"
onTriggered: Qt.openUrlExternally("https://github.com/exequtic/apdatifier/releases")
}
Kirigami.Action {
text: i18n("Dismiss")
icon.name: "dialog-close"
onTriggered: plasmoid.configuration.version = currVersion
}
}
]
}
SwipeView {
id: swipeView
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
currentIndex: plasmoid.configuration.defaultTab
View.Compact {}
View.Extended {}
View.News {}
}
}
KSortFilterProxyModel {
id: modelList
sourceModel: listModel
filterRoleName: "name"
filterRowCallback: (sourceRow, sourceParent) => {
return sourceModel.data(sourceModel.index(sourceRow, 0, sourceParent), filterRole).includes(searchField.text)
}
}
}

View File

@ -0,0 +1,204 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import org.kde.plasma.plasmoid
import org.kde.kirigami as Kirigami
import org.kde.plasma.core as PlasmaCore
import Qt5Compat.GraphicalEffects
import "../components" as QQC
import "../../tools/tools.js" as JS
MouseArea {
id: mouseArea
property bool wasExpanded: false
property bool inTray: (plasmoid.containmentDisplayHints & PlasmaCore.Types.ContainmentDrawsPlasmoidHeading)
property bool horizontal: plasmoid.location === 3 || plasmoid.location === 4
property int trayIconSize: horizontal ? trayIcon.width : trayIcon.height
property bool counterOverlay: inTray || !horizontal
property bool counterRow: !inTray && horizontal
function darkColor(color) {
return Kirigami.ColorUtils.brightnessForColor(color) === Kirigami.ColorUtils.Dark
}
property var isDarkText: darkColor(Kirigami.Theme.textColor)
property var lightText: isDarkText ? Kirigami.Theme.backgroundColor : Kirigami.Theme.textColor
property var darkText: isDarkText ? Kirigami.Theme.textColor : Kirigami.Theme.backgroundColor
property var errorIcon: cfg.ownIconsUI ? "status_error" : "error"
property var updatedIcon: cfg.ownIconsUI ? "status_updated" : "checkmark"
property var pausedIcon: cfg.ownIconsUI ? "toolbar_pause" : "media-playback-paused"
Layout.preferredWidth: counterOverlay ? trayIcon.width : panelRow.width
hoverEnabled: true
acceptedButtons: cfg.rightAction ? Qt.AllButtons : Qt.LeftButton | Qt.MiddleButton
onEntered: sts.checktime = JS.getLastCheckTime()
onPressed: mouse => {
wasExpanded = expanded
if (!cfg.rightAction && mouse.button == Qt.RightButton) mouse.accepted = false
}
onClicked: mouse => {
if (mouse.button == Qt.LeftButton) expanded = !wasExpanded
if (mouse.button == Qt.MiddleButton && cfg.middleAction) JS[cfg.middleAction]()
if (mouse.button == Qt.RightButton && cfg.rightAction) JS[cfg.rightAction]()
}
WheelHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
onWheel: (event) => {
if (srollTimer.running) return
srollTimer.start()
var action = event.angleDelta.y > 0 ? cfg.scrollUpAction : cfg.scrollDownAction
if (!action) return
JS[action]()
}
}
Timer {
id: srollTimer
interval: 500
}
RowLayout {
id: panelRow
layoutDirection: cfg.counterOnLeft ? Qt.RightToLeft : Qt.LeftToRight
visible: counterRow
spacing: 0
anchors.centerIn: mouseArea
Item {
Layout.preferredWidth: Kirigami.Units.smallSpacing + cfg.counterMargins
}
Item {
Layout.preferredHeight: mouseArea.height
Layout.preferredWidth: mouseArea.height
Kirigami.Icon {
id: panelIcon
width: parent.width
height: parent.height
source: JS.setIcon(plasmoid.icon)
active: mouseArea.containsMouse
QQC.Badge {
iconName: errorIcon
iconColor: Kirigami.Theme.negativeTextColor
visible: sts.err
}
QQC.Badge {
iconName: updatedIcon
iconColor: Kirigami.Theme.positiveTextColor
visible: sts.updated
}
QQC.Badge {
iconName: pausedIcon
iconColor: Kirigami.Theme.neutralTextColor
visible: sts.paused
}
}
}
Item {
Layout.preferredWidth: cfg.counterSpacing
visible: counterText.visible
}
Label {
id: counterText
visible: cfg.counterEnabled && sts.pending
font.family: plasmoid.configuration.counterFontFamily || Kirigami.Theme.defaultFont
font.pixelSize: mouseArea.height * (cfg.counterFontSize / 10)
font.bold: cfg.counterFontBold
fontSizeMode: Text.FixedSize
smooth: true
text: sts.count
}
Item {
Layout.preferredWidth: Kirigami.Units.smallSpacing + cfg.counterMargins
}
}
Kirigami.Icon {
id: trayIcon
anchors.fill: parent
source: JS.setIcon(plasmoid.icon)
active: mouseArea.containsMouse
visible: counterOverlay
}
Rectangle {
id: frame
anchors.centerIn: trayIcon
width: trayIconSize + cfg.counterOffsetX
height: trayIconSize + cfg.counterOffsetY
opacity: 0
visible: counterOverlay
}
Rectangle {
id: counterFrame
width: cfg.counterCenter ? frame.width : counter.width + 2
height: cfg.counterCenter ? frame.height : counter.height
radius: cfg.counterRadius
opacity: cfg.counterOpacity / 10
color: cfg.counterColor ? cfg.counterColor : Kirigami.Theme.backgroundColor
visible: counterOverlay && cfg.counterEnabled && sts.pending
layer.enabled: cfg.counterShadow
layer.effect: DropShadow {
horizontalOffset: 0
verticalOffset: 0
radius: 2
samples: radius * 2
color: Qt.rgba(0, 0, 0, 0.5)
}
anchors {
centerIn: cfg.counterCenter ? parent : undefined
top: (!cfg.counterCenter && cfg.counterTop && !cfg.counterBottom) ? frame.top : undefined
bottom: (!cfg.counterCenter && cfg.counterBottom && !cfg.counterTop) ? frame.bottom : undefined
left: (!cfg.counterCenter && cfg.counterLeft && !cfg.counterRight) ? frame.left : undefined
right: (!cfg.counterCenter && cfg.counterRight && !cfg.counterLeft) ? frame.right : undefined
}
}
Label {
id: counter
anchors.centerIn: counterFrame
text: sts.count
font.family: plasmoid.configuration.counterFontFamily || Kirigami.Theme.defaultFont
font.pixelSize: Math.max(trayIcon.height / 4, Kirigami.Theme.smallFont.pixelSize + cfg.counterSize)
font.bold: cfg.counterFontBold
color: cfg.counterColor ? darkColor(counterFrame.color) ? lightText : darkText : Kirigami.Theme.textColor
smooth: true
visible: counterFrame.visible
}
QQC.Badge {
iconName: errorIcon
iconColor: Kirigami.Theme.negativeTextColor
visible: counterOverlay && sts.err
}
QQC.Badge {
iconName: updatedIcon
iconColor: Kirigami.Theme.positiveTextColor
visible: counterOverlay && sts.updated
}
QQC.Badge {
iconName: pausedIcon
iconColor: Kirigami.Theme.neutralTextColor
visible: counterOverlay && sts.paused
}
}

View File

@ -0,0 +1,73 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import org.kde.plasma.components
import org.kde.kirigami as Kirigami
import "../../tools/tools.js" as JS
import "../components"
ScrollView {
id: view
ScrollBar.vertical.policy: (sts.count === 0 || sts.busy || sts.err) ? ScrollBar.AlwaysOff : ScrollBar.AsNeeded
ListView {
model: modelList
delegate: GridLayout {
visible: sts.pending
property var heightItem: Math.round(Kirigami.Theme.defaultFont.pointSize * 1.5)
property var column: view.width / 2
height: heightItem + cfg.spacing
Rectangle {
id: icon
property bool isHovering: false
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
height: heightItem
width: height
color: "transparent"
Kirigami.Icon {
anchors.centerIn: parent
height: heightItem
width: height
source: !icon.isHovering ? model.IC : "edit-download"
}
Loader {
width: parent.width - (Kirigami.Units.largeSpacing * 4)
anchors.fill: parent
active: model.ID || model.CN
sourceComponent: MouseArea {
id: hoverIcon
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: icon.isHovering = true
onExited: icon.isHovering = false
onClicked: JS.upgradePackage(model.NM, model.ID, model.CN)
}
}
}
Label {
Layout.minimumWidth: column
Layout.maximumWidth: column
text: model.IM ? "<font color='" + Kirigami.Theme.negativeTextColor + "'><b>" + model.NM + "</b></font>" : model.NM
elide: Text.ElideRight
}
Label {
Layout.minimumWidth: column
Layout.maximumWidth: column
text: model.RE + " → " + model.VN
elide: Text.ElideRight
}
}
Placeholder {
anchors.fill: parent
}
}
}

View File

@ -0,0 +1,136 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import org.kde.ksvg
import org.kde.plasma.extras
import org.kde.plasma.components
import org.kde.kirigami as Kirigami
import "../../tools/tools.js" as JS
import "../components"
ScrollView {
ScrollBar.vertical.policy: (sts.count === 0 || sts.busy || sts.err) ? ScrollBar.AlwaysOff : ScrollBar.AsNeeded
contentItem: ListView {
model: modelList
boundsBehavior: Flickable.StopAtBounds
highlight: Highlight { visible: sts.idle }
highlightMoveDuration: Kirigami.Units.shortDuration
highlightResizeDuration: Kirigami.Units.shortDuration
height: parent.height
delegate: ExpandableListItem {
visible: sts.pending
property var pkg: []
allowStyledText: true
title: model.IM ? "<font color='" + Kirigami.Theme.negativeTextColor + "'><b>" + model.NM + "</b></font>" : model.NM
subtitle: model.RE + " " + model.VO + " → " + model.VN
icon: model.IC
function getContextualActions() {
var actions = []
if (model.ID || model.CN) {
actions.push(updateButton)
}
return actions
}
Action {
id: updateButton
icon.name: "edit-download"
text: i18n("Upgrade package")
enabled: cfg.terminal
onTriggered: JS.upgradePackage(model.NM, model.ID, model.CN)
}
contextualActions: getContextualActions()
customExpandedViewContent: Component {
ColumnLayout {
spacing: 0
SvgItem {
Layout.fillWidth: true
imagePath: "widgets/line"
elementId: "horizontal-line"
visible: contextualActions.length === 0
}
Item {
Layout.preferredHeight: Kirigami.Units.smallSpacing * 2
}
MouseArea {
Layout.fillWidth: true
Layout.preferredHeight: details.implicitHeight
// acceptedButtons: Qt.RightButton
activeFocusOnTab: repeater.count > 0
GridLayout {
id: details
width: parent.width
columns: 2
rowSpacing: Kirigami.Units.smallSpacing / 4
columnSpacing: 40
Repeater {
id: repeater
model: pkg.length
Label {
property bool header: !(index % 2)
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
horizontalAlignment: Text.AlignLeft
font: Kirigami.Theme.smallFont
opacity: header ? 0.6 : 1
text: header ? "<b>" + pkg[index] + ":</b>" : pkg[index].indexOf("://") !== -1 ? "<a href=\"" + pkg[index] + "\">" + pkg[index] + "</a>" : pkg[index]
textFormat: header ? Text.StyledText : pkg[index].indexOf("://") !== -1 ? Text.StyledText : Text.PlainText
wrapMode: header ? Text.NoWrap : Text.WordWrap
onLinkActivated: Qt.openUrlExternally(link)
}
}
}
}
Item {
Layout.preferredHeight: Kirigami.Units.smallSpacing * 2
}
Component.onCompleted: {
const details = []
model.TP && details.push(i18n("Package type"), model.TP)
model.DE && details.push(i18n("Description"), model.DE)
model.AU && details.push(i18n("Author"), model.AU)
model.LN && details.push("URL", model.LN)
model.ID && details.push(i18n("App ID"), model.ID)
model.BR && details.push(i18n("Branch"), model.BR)
model.CM && details.push(i18n("Commit"), model.CM)
model.RT && details.push(i18n("Runtime"), model.RT)
model.GR && details.push(i18n("Groups"), model.GR)
model.PR && details.push(i18n("Provides"), model.PR)
model.DP && details.push(i18n("Depends on"), model.DP)
model.RQ && details.push(i18n("Required by"), model.RQ)
model.CF && details.push(i18n("Conflicts with"), model.CF)
model.RP && details.push(i18n("Replaces"), model.RP)
model.IS && details.push(i18n("Installed size"), model.IS)
model.DS && details.push(i18n("Download size"), model.DS)
model.DT && details.push(i18n("Install date"), model.DT)
model.RN && details.push(i18n("Install reason"), model.RN)
pkg = details
}
}
}
}
Placeholder {
anchors.fill: parent
}
}
}

View File

@ -0,0 +1,126 @@
/*
SPDX-FileCopyrightText: 2024 Evgeny Kazantsev <exequtic@gmail.com>
SPDX-License-Identifier: MIT
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as Controls
import org.kde.plasma.components
import org.kde.kirigami as Kirigami
import "../../tools/tools.js" as JS
ScrollView {
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ListView {
model: activeNewsModel
spacing: Kirigami.Units.largeSpacing * 2
topMargin: spacing
rightMargin: spacing
leftMargin: spacing
bottomMargin: spacing
// add: Transition { NumberAnimation { properties: "x"; from: 100; duration: Kirigami.Units.longDuration } } NEWS SPACING PATCH
removeDisplaced: Transition { NumberAnimation { properties: "x,y"; duration: Kirigami.Units.longDuration } }
remove: Transition { ParallelAnimation {
NumberAnimation { property: "opacity"; to: 0; duration: Kirigami.Units.longDuration }
NumberAnimation { properties: "x"; to: 100; duration: Kirigami.Units.longDuration }}}
delegate: Kirigami.AbstractCard {
contentItem: Item {
implicitWidth: delegateLayout.implicitWidth
implicitHeight: delegateLayout.implicitHeight
GridLayout {
id: delegateLayout
anchors {
left: parent.left
top: parent.top
right: parent.right
}
rowSpacing: Kirigami.Units.largeSpacing
columnSpacing: Kirigami.Units.largeSpacing
columns: width > Kirigami.Units.gridUnit * 20 ? 4 : 2
Kirigami.Icon {
Layout.fillHeight: true
Layout.maximumHeight: Kirigami.Units.iconSizes.huge
Layout.preferredWidth: height
source: model.title.includes("Arch") ? "apdatifier-plasmoid" :
model.title.includes("Plasma") ? "note-symbolic" :
model.title.includes("Apps") ? "applications-all-symbolic" :
model.title.includes("Community") ? "start-here-kde-plasma-symbolic"
: "news-subscribe"
}
RowLayout {
ColumnLayout {
Controls.Label {
Layout.fillWidth: true
wrapMode: Text.WordWrap
text: model.title
font.bold: true
}
Controls.Label {
Layout.fillWidth: true
wrapMode: Text.WordWrap
text: model.date
opacity: 0.6
}
Kirigami.Separator {
Layout.fillWidth: true
}
Controls.Label {
Layout.fillWidth: true
wrapMode: Text.WordWrap
text: model.article
}
}
ColumnLayout {
Controls.Button {
ToolTip { id: tip; text: i18n("Read article") }
icon.name: "internet-web-browser-symbolic"
onClicked: {
tip.hide()
Qt.openUrlExternally(model.link)
}
}
Controls.Button {
ToolTip { text: i18n("Remove") }
icon.name: "delete"
onClicked: JS.removeNewsItem(index)
}
}
}
}
}
}
Loader {
width: parent.width
active: sts.busy && (sts.statusIco === "status_news" || sts.statusIco === "news-subscribe")
sourceComponent: ProgressBar {
from: 0
to: 100
indeterminate: true
}
}
Loader {
anchors.centerIn: parent
active: activeNewsModel.count === 0
sourceComponent: Kirigami.PlaceholderMessage {
icon.name: "news-subscribe"
text: i18n("No unread news")
helpfulAction: Kirigami.Action {
enabled: newsModel.count > 0
icon.name: "backup"
text: i18n("Restore list")
onTriggered: JS.restoreNewsList()
}
}
}
}
}