Compare commits

..

181 Commits

Author SHA1 Message Date
161ff64293 Release 4.0.0 2024-03-25 14:04:30 +02:00
115bef3dbe correct subscription processing 2024-03-24 00:42:03 +02:00
b6ade7310a extend temperature sensors 2024-03-23 15:30:35 +02:00
0555185044 add time source 2024-03-23 15:11:49 +02:00
23e197789f make it build together 2024-03-23 13:57:28 +02:00
67640cccdc do not derive from qwidget in aggregates 2024-03-22 16:57:47 +02:00
33a41bb6c0 do not derive from qwidget 2024-03-21 16:51:29 +02:00
42c11a6b60 port dataengin 2024-03-20 18:45:17 +02:00
423597dbd9 port widget to dbus 2024-03-15 15:51:23 +02:00
0fcfb7d7e4 port library 2024-03-08 16:22:00 +02:00
5fd3a4a21a update to plasma 6 support 2024-03-07 12:09:46 +02:00
eecb128865 Release 3.5.1 2023-05-18 13:02:44 +03:00
0565d3533f correct desktop indices for main widget 2023-05-18 12:53:51 +03:00
88f70c0ea6 Release 3.5.0 2023-05-18 02:57:31 +03:00
338828da88 add release pipeline 2023-05-18 01:41:48 +03:00
09a3c32d0c fix some found warning 2023-05-17 21:37:00 +03:00
e9beea2d7a create workflow run 2023-05-17 18:23:58 +03:00
1e69aa93f5 add support of hidden flag 2023-05-17 14:11:58 +03:00
73f1617cbf Merge pull request #156 from arcan1s/feature/wayland-support
wayland support
2023-05-17 03:48:20 +03:00
dea9d488df wayland support 2023-05-17 03:42:40 +03:00
84de9755b5 fix (some) KF deprecation warnings 2023-03-30 03:31:57 +03:00
ff40ac96d8 update dependencies list 2021-07-07 22:09:44 +03:00
de9d90df4a Release 3.4.3
compilation fixes for old ubuntu and provide patch for old qt versions
2021-01-08 15:48:20 +03:00
883659272d add patch for qt < 5.14 2021-01-08 11:17:11 +03:00
0c443e9278 do not use nodiscard for slots (#147) 2021-01-08 10:52:57 +03:00
6ec30b71d1 Release 3.4.2
changelog updated
2021-01-07 06:55:03 +03:00
4ed19a38d9 release 3.4.1
update translators list
2020-11-07 17:10:04 +03:00
e592de9555 release 3.4.0 2020-11-07 17:05:13 +03:00
1e0316c4de fix warnings 2020-11-07 16:45:36 +03:00
91abbdcd96 clang-tidy warning fixes 2020-11-03 04:23:01 +03:00
e81d765098 update to new process api 2020-11-01 14:33:17 +03:00
8eaf444a25 fix dockerfile again 2020-11-01 01:16:10 +03:00
183e7d8a20 correct image spelling 2020-11-01 00:43:00 +03:00
a4a1ae064f newest qt fixes 2020-11-01 00:38:59 +03:00
3e81cd16bb update for docker 2020-10-31 22:02:42 +03:00
55319521b2 replace all nbsp in previews (#142) 2020-04-18 16:52:02 +03:00
e525cb4742 do not replace space to nbsp in some cases (#143) 2020-04-18 03:06:06 +03:00
0f19bce80d close process in destructor 2019-12-15 11:31:49 +03:00
e0df575aa9 hanle new sources 2019-12-15 11:23:18 +03:00
276248a748 system source, some code improvements 2019-12-14 23:54:15 +03:00
c05a87a540 add notes about dependencies 2019-12-07 11:47:45 +03:00
9f46a17b98 Add italian translation (#136) 2018-10-26 03:33:46 +03:00
c2a18f8845 add git build instruction 2018-09-17 16:43:01 +03:00
308b721c87 some docker changes (3) 2017-12-17 21:39:03 +03:00
c4c37406a5 some docker changes (2) 2017-12-17 21:32:21 +03:00
ffb66586d3 some docker changes 2017-12-17 21:27:00 +03:00
935fa04757 some travis debug 2017-12-17 21:20:55 +03:00
fee70b7385 fix typo 2017-12-17 21:13:12 +03:00
ed21e3fb18 lang: generic 2017-12-17 19:29:28 +03:00
5807d4d75e use language? 2017-12-17 18:08:17 +03:00
5bd95fe41a simplify docker 2017-12-17 18:01:56 +03:00
13edbc5eb1 docker iteration v10 2017-12-17 17:53:37 +03:00
3b41239672 fix hddevices test 2017-12-17 16:57:58 +03:00
b30bd35add remove hdddevices test 2017-12-17 16:44:43 +03:00
4bba061d66 fix lambda related code 2017-12-17 06:24:41 +03:00
ce30d90a23 fix hddtemp tests 2017-12-17 05:07:50 +03:00
423eabd857 fix battery tests 2017-12-17 04:29:23 +03:00
e5a9e99438 Replace yahoo finance to stooq (#131)
Old code is dropped to separated provider
2017-12-15 02:01:34 +03:00
eb911551eb Merge pull request #132 from ibnuda/indonesian-translation
Finished ID translation.
2017-12-03 06:31:55 +03:00
5886dcc50b Finished ID translation. 2017-12-02 01:21:36 +07:00
2d7d4c55a2 use MSD for battery calculations, fix segfault 2017-08-25 06:11:18 +03:00
ea5d73d8fd add more battery retalted keys 2017-08-24 01:20:27 +03:00
081f7a3c88 release 3.3.3 2017-08-03 01:47:10 +03:00
707fa727c5 split awkeysaggregator class 2017-07-28 04:57:07 +03:00
5d0c05e856 make tests great again (iteration #2) 2017-07-27 17:20:59 +03:00
4625afa0b9 add docker files, improve dbus interface 2017-07-27 16:47:20 +03:00
5c56f813d2 make tests great again!
Also dbus adaptor has been renamed, because it does not allow to
register one service for several applications (like plasmashell and
    plasmawindowed)
2017-07-26 20:23:26 +03:00
5e08434835 fix issue with invalid (up|down)total($|kb) calculation (see #127)
also renamed *total* tags to *tot* for consistency with other tags:

  * uptotal.* -> uptot.*
  * downtotal.* -> downtot.*
  * pstotal -> pstot
2017-07-24 15:07:36 +03:00
d2e6f2fe38 some refactoring
* massive changes inside includes, drop unused definitions
* rewrite some initialization methods to avoid additional
freeing/allocation
* drop some explicit destructors calls
2017-07-14 03:34:05 +03:00
e90e1da096 Small fixes
* update translations, add target to update translations
* add custom keys support to config helper
2017-07-13 19:15:10 +03:00
9d0a1bd70c rewrite formtatter* and customkeys* to share their code 2017-07-12 03:28:03 +03:00
7ce3e8b1cf add custom keys configuration 2017-07-10 01:43:21 +03:00
7a00dce7c5 initial implementation of custom keys 2017-07-07 00:52:16 +03:00
1a7530a847 commit metadata files too 2017-06-02 17:46:37 +03:00
1702045550 update changelog 2017-06-02 17:38:27 +03:00
fe88c72498 release 3.3.2 2017-06-02 17:35:35 +03:00
737759d03f Bug fixing
* fix bug with invalid applet and configuration load with newest qt
* fix bug with invalid DP configuration
* fix bug with invalid HTML tags operations
2017-06-02 17:34:27 +03:00
934e30819c rename deadbeef defaults 2017-05-21 23:07:12 +03:00
a4d3a09f26 add patch for mpris 2017-05-17 17:47:34 +03:00
acc4df92bc fix invalid mpris parser
In some cases it causes the error like:

Error message "Интерфейс «(null)» для пути /org/mpris/MediaPlayer2 объекта не найден"

(for example deadbeef was affected). Suggested patch should fix this
issue and seems to be working with at least deadbeef and qmmp mpris
engines.
2017-05-17 17:43:18 +03:00
0a723aef82 release 3.3.1
* bump api versions
* update changelog
2017-05-15 20:15:05 +03:00
271b8d55cf release 3.3.0 2017-05-15 17:06:03 +03:00
1afc33abef qml UI fixes 2017-05-15 17:05:22 +03:00
6b8244f3c4 fix comparison 2017-05-10 15:26:25 +03:00
ff2032cca1 update patches
Since now Qt5.4 version support is officially dropped. It means that
widgets now require

ubuntu>=16.04
debian>8
opensuse>=42.1
2017-05-10 15:01:01 +03:00
05aafc43e7 translation update 2017-05-05 18:20:50 +03:00
d0c96ce829 massive refactoring 2017-05-05 17:55:52 +03:00
6e62ceaac7 massive changes inside
* use pass by ref instead of by value if possible
* use reference in interation over collections
* fix no tag inserting
2017-05-04 15:00:50 +03:00
6e99e262d4 add configuration for cron 2017-05-03 00:27:09 +03:00
1b4d1d6944 implement qcronscheduler, tests update 2017-04-28 01:47:42 +03:00
8be4cc6e82 Add tests and UI fields for #118 2017-04-20 00:21:34 +03:00
99c750fd0b fix build again 2017-04-20 03:31:00 +03:00
fca8019972 fix ci build (3) 2017-03-08 16:56:20 +03:00
8d3dd0ed96 one more fix for travis, drop build directory from search 2017-03-08 06:55:00 +03:00
4974948151 add new deps to travis -_- 2017-03-08 06:44:02 +03:00
9e50ade6a5 add cppchec and clangformat to travis build 2017-03-08 06:33:55 +03:00
801eea9a8b add flag to cmake build 2017-03-08 06:22:58 +03:00
1841fb5ed2 extquotes test improvement 2017-02-15 00:43:21 +03:00
9c8dbdcb41 fix kwin definition again 2017-02-14 05:11:00 +03:00
53afc07457 tests cleanup 2017-02-14 04:47:24 +03:00
1caecb427b fix test library building 2017-02-14 04:35:24 +03:00
ea10d526d5 fix test library building 2017-02-14 04:32:17 +03:00
b818586a23 another iteration with fix travis tests 2017-02-14 04:26:59 +03:00
a30e6ba21b fix stupid errors (2) 2017-02-14 04:01:33 +03:00
fe38d9133b fix stupid errors 2017-02-14 03:53:33 +03:00
38c5589c10 one more iteration to try to fix tests on travis 2017-02-14 03:48:11 +03:00
ce09ab753b add temporary || true to tests to get output 2017-02-13 21:12:36 +03:00
10f556e41b Try to fix test for automatic run with travis
* Additionally calculate valid pressure
2017-02-13 21:04:03 +03:00
d097e154ff try to use virtual fb x-server to run tests 2017-02-12 20:58:14 +03:00
8979ddf52b add submodule init 2017-02-12 20:26:09 +03:00
d3dd9b3390 add python to makedeps array 2017-02-12 20:22:31 +03:00
5615fd3ff9 more correct using of arch script (2) 2017-02-12 20:19:51 +03:00
cbb8415a95 more correct using of arch script 2017-02-12 20:16:03 +03:00
8dcdae9611 another iteration with travis ci 2017-02-12 20:11:11 +03:00
bfdaadfc8b add socket activation for extensions (#118)
Option `X-AW-Socket` is used. Any message received by this socket will
trigger extension update. If the option is set, `X-AW-Interval` will be
ignored
2017-02-06 12:16:16 +03:00
9543122816 cosmetic changes caused by site moving 2017-02-02 23:12:19 +03:00
6a24fc3f63 more pretty about text
Use generic text generation for all plasmoids
2016-11-06 22:12:03 +03:00
73d1b0a69f bump formatter api version 2016-11-05 00:01:50 +03:00
06f4882a2d add network request source 2016-11-04 01:12:25 +03:00
7565ea2e82 add test case for jsonformatter
Change array indexes from "[num]" to ".num." in path
2016-11-03 00:23:10 +03:00
004a97800c add json formatter 2016-11-02 23:23:30 +03:00
8dfb6b609f better tooltip class 2016-11-01 00:02:13 +03:00
f893b34e19 run clangformat 2016-10-31 08:12:15 +03:00
a189e1af38 use default widget configuration to configure telemetry 2016-10-30 09:04:08 +03:00
0332c59daf add copyright string 2016-10-29 12:21:13 +03:00
26b375254a add telemetry configuration 2016-10-28 23:21:37 +03:00
89cb4b74fd add background color to textarea 2016-10-27 00:00:18 +03:00
ea1d5fca86 drop C-like fabs function 2016-10-26 01:02:17 +03:00
c3c46ff1b1 improve tag completion
allow to select item from tooltip by mouse and insert it to text edtior
2016-10-25 10:23:05 +03:00
87406f70c4 add initial support of tag suggestion 2016-10-24 08:12:14 +03:00
d520f55afc add test for dbus connection 2016-10-23 01:32:07 +03:00
77a94aa0c1 add methods to dbus interface 2016-10-22 00:43:16 +03:00
c103986f37 add dbus session prototype 2016-10-21 08:10:29 +03:00
7568ae2a3b move textarea to own class as well 2016-10-20 09:23:18 +03:00
2ea5824fd7 add test case for new method 2016-10-19 00:01:09 +03:00
47439ef151 update desktop panel configuration to new one 2016-10-18 00:12:25 +03:00
63d19f038c move info label to own class, move dialog to own class as well 2016-10-17 23:12:03 +03:00
9d5864aa62 move extensions to own bar 2016-10-16 12:23:23 +03:00
d74cd645fd qml improvements
* move functions to plugin part
* move model to general.qml
2016-10-15 00:01:10 +03:00
80767c9dbf update qmldir to new ui element 2016-10-14 01:10:10 +03:00
57ad8a0a2b add tag selector row 2016-10-13 00:12:46 +03:00
eea636c6f1 add html bar 2016-10-12 10:23:20 +03:00
65141ff528 add comment lines to qmldir.in file 2016-10-11 00:00:07 +03:00
f882756fad update desktoppanel qml part 2016-10-10 20:43:07 +03:00
335fbb137e move general singleton to shared part, update part of desktop-panel ui 2016-10-09 21:23:27 +03:00
fcb698e7fc use shared About tab 2016-10-08 00:54:29 +03:00
f1b5208bb2 use shared qml files 2016-10-07 22:13:41 +03:00
c9f5be6a60 use model list defined in general.qml for font configuration 2016-10-03 23:54:07 +03:00
f7094ca187 add font dialog, some color dialog improvements 2016-10-02 01:43:12 +03:00
a326ebdabf replace buttons in dataengine page 2016-10-01 12:42:05 +03:00
3ee1d4c30e Add import and export dialogs 2016-09-30 10:22:10 +03:00
31c129163b Create dialogs for button and color button 2016-09-29 10:24:03 +03:00
80c994bce0 massive qml controls replacement (#114) 2016-09-28 13:50:57 +03:00
8aa6d0c626 change opensuse url 2016-09-27 12:17:13 +03:00
33623fe75e use own control for checkbox 2016-09-25 12:41:22 +03:00
ecf4be8d9c Add support of text styling for desktop panel 2016-09-24 15:24:24 +03:00
7f6a2d8100 Add ability to change text style inside general widget (see #112) 2016-09-23 01:12:34 +03:00
086870e9c2 drop custom keys engine
With current implementation it has no sense to add this support. It
requies some architectures changes inside.
2016-09-22 02:34:20 +03:00
1c52cf72be initial import of custom keys support (#101)
It will use the configuration file `$AWHOME/custom.ini`, group `[Custom]`. One
custom key per string, key is custom key, value is any of available
standard data.

Formatters will be defined by using standard way.
2016-09-21 01:02:21 +03:00
8e598bbd13 allow editable selectors 2016-09-20 02:42:10 +03:00
877f58784b small refactoring
* change `writeFormatters` method to more intuitive
`removeUnusedFormatters`
* use class property as filename
2016-09-19 23:49:11 +03:00
ee6cf60aa4 change constants from #define to const var val
Update contributing.md accordingly
2016-09-18 00:59:23 +03:00
6449465be2 add test for telemetryhandler class 2016-09-17 23:19:06 +03:00
3403d1de50 add local history suggestion to configuration window 2016-09-16 16:03:11 +03:00
f9ddf690c7 drop semicolon from qml files, update CONTRIBUTING guide accordingly 2016-09-15 07:26:00 +03:00
87652eb774 add ability to upload telemetry to a server 2016-09-14 11:32:40 +03:00
a9924a1432 fix conditional error 2016-09-08 19:36:26 +03:00
c5cb5cb359 initial import of telemetry handler 2016-09-07 10:23:05 +03:00
65c8f552de run clangformat 2016-09-05 17:04:16 +03:00
486267256c Add patch for bug reporting 2016-09-01 15:56:56 +03:00
94e87ee570 Add legacy message 2016-08-31 20:49:31 +03:00
b17aeb88e3 drop some legacy code 2016-08-29 15:02:34 +03:00
7d8036b0e1 update russian translation 2016-08-28 16:34:13 +03:00
4d1c05d737 translation update 2016-08-27 02:54:59 +03:00
95ede170d9 use more obvious way to sort keys
Some bugs in past were related to invalid keys sorting. Automatic keys
sorting should prevent such bugs in the future
2016-08-26 23:01:16 +03:00
80d926290c finally implement bug reporting (#104) 2016-08-25 13:33:08 +03:00
5b9984d950 add frontend for bug reporting (#104) 2016-08-23 12:30:11 +03:00
e5b1102abf some changes inside bug reportin backend 2016-08-22 19:10:37 +03:00
f3f9239984 more correct error checking 2016-08-21 19:24:16 +03:00
18c993c0d5 add github issue reporing backend (#104) 2016-08-20 12:14:22 +03:00
a9e3e3f087 Possible one more performance increasing
Lets try to use own QueuedConnection type instead of default
AutoConnection. To implement it we need to disconnect all default slots
and reconnect them with specified connection type
2016-08-18 20:16:05 +03:00
338 changed files with 18542 additions and 13350 deletions

41
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,41 @@
name: build & tests
on:
push:
branches: [ development, master ]
pull_request:
branches: [ development, master ]
env:
BUILD_TYPE: Release
jobs:
run-tests:
runs-on: ubuntu-latest
container:
image: archlinux:latest
volumes:
- ${{ github.workspace }}:/repo
options: -w /repo
steps:
- uses: actions/checkout@v3
- name: create build environment
run: pacman -Sy --noconfirm base-devel cmake extra-cmake-modules python util-linux-libs xorg-server-xvfb
- name: install dependencies
run: pacman -S --noconfirm plasma-workspace ksysguard
- name: configure cmake
run: cmake -B build -DKDE_INSTALL_USE_QT_SYS_PATHS=ON -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_FUTURE=ON -DBUILD_TESTING=ON sources
- name: build
working-directory: /repo/build
run: make
- name: test
working-directory: /repo/build
run: xvfb-run -a make test

51
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,51 @@
name: release
on:
push:
tags:
- '*'
jobs:
make-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: create changelog
id: changelog
uses: jaywcjlove/changelog-generator@main
with:
token: ${{ secrets.GITHUB_TOKEN }}
filter: 'Release \d+\.\d+\.\d+'
- name: create archive
run: bash create_archive.sh
env:
VERSION: ${{ steps.version.outputs.VERSION }}
# - name: build debian package
# run: |
# sudo apt update && \
# sudo apt install -yq cmake extra-cmake-modules g++ git gettext make && \
# sudo apt install -yq libkf5i18n-dev libkf5notifications-dev libkf5service-dev \
# libkf5windowsystem-dev libkf5plasma-dev qtbase5-dev qtdeclarative5-dev \
# plasma-workspace-dev && \
# cmake -B build-deb -DKDE_INSTALL_USE_QT_SYS_PATHS=ON -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Optimization -DBUILD_FUTURE=ON -DBUILD_DEB_PACKAGE=ON sources && \
# cd build-deb && \
# make package && \
# cd ..
- name: release
uses: softprops/action-gh-release@v1
with:
body: |
${{ steps.changelog.outputs.compareurl }}
${{ steps.changelog.outputs.changelog }}
files: |
awesome-widgets-*-src.tar.xz
# build-deb/plasma-widget-awesome-widgets-*.deb
fail_on_unmatched_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

1
.gitignore vendored
View File

@ -47,3 +47,4 @@ pkg
# clion settings # clion settings
.idea .idea
cmake-build*

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "sources/3rdparty/fontdialog"]
path = sources/3rdparty/fontdialog
url = https://github.com/arcan1s/qtadds-fontdialog.git

View File

@ -1,20 +0,0 @@
sudo: required
dist: trusty
language: cpp
os:
- linux
before_script:
- sudo apt-add-repository -y ppa:kubuntu-ppa/backports
- sudo sed -i 's/trusty/wily/g' /etc/apt/sources.list
- sudo sed -i 's/trusty/wily/g' /etc/apt/sources.list.d/kubuntu-ppa-backports-trusty.list
- sudo apt-get -qq update
- sudo apt-get -y -qq -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew install libkf5i18n-dev libkf5notifications-dev libkf5service-dev libkf5windowsystem-dev plasma-framework-dev qtbase5-dev qtdeclarative5-dev extra-cmake-modules cmake g++
- rm -rf build
- mkdir build
script:
- cd build
- cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DKDE_INSTALL_USE_QT_SYS_PATHS=ON ../sources
- make

View File

@ -11,3 +11,5 @@ Ernesto Avilés Vzqz (Spanish)
Виктор Слободян (Ukrainian) Виктор Слободян (Ukrainian)
Steve Lemuel (Chinese) Steve Lemuel (Chinese)
Mariusz Kocoń (Polish) Mariusz Kocoń (Polish)
Ibnu Daru Aji (Indonesian)
Antonio Vivace (Italian)

View File

@ -1,3 +1,48 @@
Ver.4.0.0:
* migration to plasma 6
Ver.3.5.0:
+ wayland support
* update code to latest standards
- drop support of windows preview
Ver.3.4.2:
+ Italian translation (#136, thanks to @avivace)
+ stooq quotes support (default) (#131)
+ Indonesian translation (#132, thanks to @ibnuda)
+ new keys - $batleftN, $batnowN, $batrateN, $battotalN, $brightness, $volume
* fix compiler warnings
* update to new qt api
- fix non printable spaces (#142, #143)
Ver.3.3.3:
+ add custom keys support (#101)
* DBus interface improvements
* rename tags (up|down|ps)total.* to (up|down|ps)tot.*
- fix issue with invalid (up|down)total($|kb) calculation (#127)
- fix issue with wrong applet identation (#125)
Ver.3.3.2:
- fix bug with invalid DP colour configuration
- fix bug with invalid HTML tags operation
* update to newest Qt and plasma
Ver.3.3.1:
+ add ability to direct issue report (#104)
+ add key completion (#105)
+ add ability to load historical configuration (#106)
+ add ability to upload configuration to remote server (#106)
+ add stylish (#112)
+ add DBus intergration (#115)
+ add cron-like extenstion triggers (`X-AW-Socket` option) (#117)
+ add ability to trigger extensions by calling socket (`X-AW-Schedule` option) (#118)
+ add source for network requests
+ add Json formatter
- drop patches provided support for Qt 5.4
* use custom signal slot connection for dataengine (`BUILD_FUTURE` flag required)
* update UI
* refactoring
Ver.3.2.1: Ver.3.2.1:
+ add X-AW-Translate option to DateTime formatter + add X-AW-Translate option to DateTime formatter
+ add formatters to configuration export and import + add formatters to configuration export and import

View File

@ -37,31 +37,17 @@ for more details. To avoid manual labor there is automatic cmake target named
* `Q_PROPERTY` macro is allowed and recommended for QObject based classes. * `Q_PROPERTY` macro is allowed and recommended for QObject based classes.
* Qt macros (e.g. `signals`, `slots`, `Q_OBJECT`, etc) are allowed. In other hand * Qt macros (e.g. `signals`, `slots`, `Q_OBJECT`, etc) are allowed. In other hand
`Q_FOREACH` (`foreach`) is not allowed use `for (auto foo : bar)` instead. `Q_FOREACH` (`foreach`) is not allowed use `for (auto &foo : bar)` instead.
* Current project standard is **C++11**. * Current project standard is **C++17**.
* Do not use C-like code: * Do not use C-like code:
* C-like style iteration if possible. Use `for (auto foo : bar)` and * C-like style iteration if possible. Use `for (auto &foo : bar)` and
`std::for_each` instead if possible. It is also recommended to use iterators. `std::for_each` instead if possible. It is also recommended to use iterators.
* C-like casts, use `const_cast`, `static_cast`, `dymanic_Cast` instead. Using * C-like casts, use `const_cast`, `static_cast`, `dymanic_Cast` instead. Using
of `reinterpret_cast` is not recommended. It is highly recommended to use of `reinterpret_cast` is not recommended. It is highly recommended to use
`dynamic_cast` with the exception catching. It is also possible to use `dynamic_cast` with the exception catching. It is also possible to use
`qvariant_cast` if required. Exception is class constructors, e.g.: `qvariant_cast` if required.
```
char c = 'c';
std::string s = "string";
qDebug() << QString("some string") << QChar(c) << QString(s);
```
* C-like `NULL`, use `nullptr` instead. * C-like `NULL`, use `nullptr` instead.
* It is highly recommended to avoid implicit casts. Exception `nullptr` casts to * C-like constant definition, use `const vartype foo = bar` definition instead.
boolean, e.g.:
```
if (nullptr)
qDebug() << "nullptr is true, wtf";
```
* Abstract classes (which have at least one pure virtual method) are allowed. * Abstract classes (which have at least one pure virtual method) are allowed.
* Templates are allowed and recommended. Templates usually should be described * Templates are allowed and recommended. Templates usually should be described
inside header not source code file. inside header not source code file.
@ -91,6 +77,8 @@ for more details. To avoid manual labor there is automatic cmake target named
* 'true ? foo : bar' construction is allowed and recommended for one-line assignment. * 'true ? foo : bar' construction is allowed and recommended for one-line assignment.
* Any global pointer should be assign to `nullptr` after deletion and before * Any global pointer should be assign to `nullptr` after deletion and before
initialization. Exception: if object is deleted into class destructor. initialization. Exception: if object is deleted into class destructor.
* Do not use semicolon in qml files unless it is required.
* Any method argument including class constructors should start with `_`.
Comments Comments
-------- --------
@ -176,8 +164,7 @@ Testing
1. `-DCMAKE_BUILD_TYPE=Debug`. 1. `-DCMAKE_BUILD_TYPE=Debug`.
2. `-DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON`. 2. `-DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON`.
3. `-DCMAKE_BUILD_TYPE=Release`. 3. `-DCMAKE_BUILD_TYPE=Release`.
* It is recommended to create addition test if possible. * Additional test functions should be declated and used only inside `BUILD_TESTING`
* Addition test functions should be declated and used only inside `BUILD_TESTING`
definition. definition.
Tools Tools
@ -208,9 +195,9 @@ Tools
* Recommended class constructor for QObject based classes: * Recommended class constructor for QObject based classes:
``` ```
FooClass::FooClass(QObject *parent, const QVariant var) FooClass::FooClass(QObject *_parent, const QVariant _var)
: QObject(parent) : QObject(_parent)
, m_var(var) , m_var(_var)
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
// some code below if any // some code below if any

View File

@ -1,7 +1,7 @@
awesome-widgets (ex-pytextmonitor) awesome-widgets (ex-pytextmonitor)
================================== ==================================
[![Build Status](https://travis-ci.org/arcan1s/awesome-widgets.svg?branch=development)](https://travis-ci.org/arcan1s/awesome-widgets) [![build & tests](https://github.com/arcan1s/awesome-widgets/actions/workflows/build.yml/badge.svg)](https://github.com/arcan1s/awesome-widgets/actions/workflows/build.yml)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/8254/badge.svg)](https://scan.coverity.com/projects/awesome-widgets) [![Coverity Scan Build Status](https://scan.coverity.com/projects/8254/badge.svg)](https://scan.coverity.com/projects/awesome-widgets)
Information Information
@ -31,6 +31,7 @@ Dependencies
------------ ------------
* plasma-framework * plasma-framework
* ksysguard (since plasma 5.22)
Optional dependencies Optional dependencies
--------------------- ---------------------
@ -39,6 +40,7 @@ Optional dependencies
* hddtemp * hddtemp
* smartmontools * smartmontools
* music player (mpd or MPRIS supported) * music player (mpd or MPRIS supported)
* wireless_tools
Make dependencies Make dependencies
----------------- -----------------
@ -46,6 +48,8 @@ Make dependencies
* cmake * cmake
* extra-cmake-modules * extra-cmake-modules
In addition some distros might require to install some -dev packages, e.g. the list of required packages for deb-based distros can be found [here](https://github.com/arcan1s/awesome-widgets/blob/development/.docker/Dockerfile-ubuntu-amd64#L7).
Installation Installation
------------ ------------
@ -53,7 +57,7 @@ Installation
* install * install
mkdir build && cd build mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr ../ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr ../sources
make && sudo make install make && sudo make install
**NOTE** on Plasma 5 it very likely requires `-DKDE_INSTALL_USE_QT_SYS_PATHS=ON` flag **NOTE** on Plasma 5 it very likely requires `-DKDE_INSTALL_USE_QT_SYS_PATHS=ON` flag

View File

@ -1,32 +1,20 @@
#!/bin/bash #!/bin/bash
SRCDIR="sources" SRCDIR="sources"
MAJOR=$(grep -m1 PROJECT_VERSION_MAJOR sources/CMakeLists.txt | awk '{print $2}' | sed 's/^.\(.*\)..$/\1/') VERSION="$(git describe --tags --abbrev=0)"
MINOR=$(grep -m1 PROJECT_VERSION_MINOR sources/CMakeLists.txt | awk '{print $2}' | sed 's/^.\(.*\)..$/\1/')
PATCH=$(grep -m1 PROJECT_VERSION_PATCH sources/CMakeLists.txt | awk '{print $2}' | sed 's/^.\(.*\)..$/\1/')
VERSION="${MAJOR}.${MINOR}.${PATCH}"
# update submodules
git submodule update --init --recursive
# build widget # build widget
ARCHIVE="awesome-widgets" ARCHIVE="awesome-widgets"
FILES="AUTHORS CHANGELOG COPYING packages patches" FILES="AUTHORS CHANGELOG COPYING packages patches sources"
IGNORELIST="build usr .kdev4 *.kdev4 .idea packages/*src.tar.xz" IGNORELIST="build usr .kdev4 *.kdev4 .idea packages/*src.tar.xz"
# create archive # create archive
[[ -e ${ARCHIVE}-${VERSION}-src.tar.xz ]] && rm -f "${ARCHIVE}-${VERSION}-src.tar.xz" [[ -e ${ARCHIVE}-${VERSION}-src.tar.xz ]] && rm -f "${ARCHIVE}-${VERSION}-src.tar.xz"
[[ -d ${ARCHIVE} ]] && rm -rf "${ARCHIVE}" [[ -d ${ARCHIVE} ]] && rm -rf "${ARCHIVE}"
cp -r "${SRCDIR}" "${ARCHIVE}" cp -r "${SRCDIR}" "${ARCHIVE}"
for FILE in ${FILES[*]}; do cp -r "$FILE" "${ARCHIVE}"; done for FILE in ${FILES[*]}; do cp -r "$FILE" "${ARCHIVE}"; done
for FILE in ${IGNORELIST[*]}; do rm -rf "${ARCHIVE}/${FILE}"; done for FILE in ${IGNORELIST[*]}; do rm -rf "${ARCHIVE}/${FILE}"; done
tar cJf "${ARCHIVE}-${VERSION}-src.tar.xz" "${ARCHIVE}"
ln -sf "../${ARCHIVE}-${VERSION}-src.tar.xz" packages
rm -rf "${ARCHIVE}"
# update md5sum tar cJf "${ARCHIVE}-${VERSION}-src.tar.xz" "${ARCHIVE}"
MD5SUMS=$(md5sum ${ARCHIVE}-${VERSION}-src.tar.xz | awk '{print $1}')
sed -i "/md5sums=('[0-9A-Fa-f]*/s/[^'][^)]*/md5sums=('${MD5SUMS}'/" packages/PKGBUILD rm -rf "${ARCHIVE}"
sed -i "s/pkgver=[0-9.]*/pkgver=${VERSION}/" packages/PKGBUILD
# clear
find . -type f -name '*src.tar.xz' -not -name "*${VERSION}-src.tar.xz" -exec rm -rf {} \;
find packages -type l -xtype l -exec rm -rf {} \;

View File

@ -1,41 +1,33 @@
# Maintainer: Evgeniy Alekseev <arcanis at archlinux dot org> # Maintainer: Evgeniy Alekseev <arcanis at archlinux dot org>
pkgname=plasma5-applet-awesome-widgets pkgname=plasma6-applet-awesome-widgets
_pkgname=awesome-widgets _pkgname=awesome-widgets
pkgver=3.2.1 pkgver=4.0.0alpha1
pkgrel=1 pkgrel=1
pkgdesc="Collection of minimalistic Plasmoids which look like Awesome WM widgets (ex-PyTextMonitor)" pkgdesc="Collection of minimalistic Plasmoids which look like Awesome WM widgets (ex-PyTextMonitor)"
arch=('i686' 'x86_64') arch=('x86_64')
url="https://arcanis.me/projects/awesome-widgets" url="https://arcanis.me/projects/awesome-widgets"
license=('GPL3') license=('GPL3')
depends=('plasma-framework') depends=('plasma-workspace')
optdepends=("catalyst: for GPU monitor" optdepends=("hddtemp: for HDD temperature monitor"
"hddtemp: for HDD temperature monitor"
"smartmontools: for HDD temperature monitor" "smartmontools: for HDD temperature monitor"
"mpd: for music player monitor" "mpd: for music player monitor"
"nvidia-utils: for GPU monitor") "nvidia-utils: for GPU monitor")
makedepends=('cmake' 'extra-cmake-modules' 'python') makedepends=('cmake' 'extra-cmake-modules' 'python')
source=(https://github.com/arcan1s/awesome-widgets/releases/download/V.${pkgver}/${_pkgname}-${pkgver}-src.tar.xz) source=(https://github.com/arcan1s/awesome-widgets/releases/download/${pkgver}/${_pkgname}-${pkgver}-src.tar.xz)
install=${pkgname}.install install="$pkgname.install"
md5sums=('73da19c31aa95edd428ff5ce7b541ee1')
backup=('etc/xdg/plasma-dataengine-extsysmon.conf') backup=('etc/xdg/plasma-dataengine-extsysmon.conf')
prepare() {
rm -rf "${srcdir}/build"
mkdir "${srcdir}/build"
}
build () { build () {
cd "${srcdir}/build" cmake -B build -S "${_pkgname}" \
cmake -DKDE_INSTALL_USE_QT_SYS_PATHS=ON \ -DCMAKE_BUILD_TYPE=Optimization \
-DCMAKE_BUILD_TYPE=Optimization \ -DBUILD_FUTURE=ON \
-DCMAKE_INSTALL_PREFIX=/usr \ -DBUILD_TESTING=OFF
-DBUILD_FUTURE=ON \ cmake --build build
"../${_pkgname}"
make
} }
package() { package() {
cd "${srcdir}/build" DESTDIR="$pkgdir" cmake --install build
make DESTDIR="${pkgdir}" install
} }
sha256sums=('b2a7b07a1df6f710f4e0d6e5898933f4ddb131818b922dc4b8e48afe3e98a664')

View File

@ -1,11 +0,0 @@
cmake
extra-cmake-modules
g++
git
libkf5i18n-dev
libkf5notifications-dev
libkf5service-dev
libkf5windowsystem-dev
plasma-framework-dev
qtbase5-dev
qtdeclarative5-dev

View File

@ -1,402 +0,0 @@
diff --git a/sources/awesome-widget/package/contents/ui/advanced.qml b/sources/awesome-widget/package/contents/ui/advanced.qml
index 01bcd58..1ec7ba6 100644
--- a/sources/awesome-widget/package/contents/ui/advanced.qml
+++ b/sources/awesome-widget/package/contents/ui/advanced.qml
@@ -17,7 +17,6 @@
import QtQuick 2.0
import QtQuick.Controls 1.3 as QtControls
-import QtQuick.Dialogs 1.2 as QtDialogs
import org.kde.plasma.private.awesomewidget 1.0
@@ -372,32 +371,7 @@ Item {
QtControls.Button {
width: parent.width * 3 / 5
text: i18n("Export configuration")
- onClicked: saveConfigAs.open()
- }
-
- QtDialogs.FileDialog {
- id: saveConfigAs
- selectExisting: false
- title: i18n("Export")
- folder: awConfig.configurationDirectory()
- onAccepted: {
- var status = awConfig.exportConfiguration(
- plasmoid.configuration,
- saveConfigAs.fileUrl.toString().replace("file://", ""))
- if (status) {
- messageDialog.title = i18n("Success")
- messageDialog.text = i18n("Please note that binary files were not copied")
- } else {
- messageDialog.title = i18n("Ooops...")
- messageDialog.text = i18n("Could not save configuration file")
- }
- messageDialog.open()
- }
- }
-
- QtDialogs.MessageDialog {
- id: messageDialog
- standardButtons: QtDialogs.StandardButton.Ok
+ onClicked: awConfig.exportConfiguration(plasmoid.configuration)
}
}
@@ -410,42 +385,9 @@ Item {
QtControls.Button {
width: parent.width * 3 / 5
text: i18n("Import configuration")
- onClicked: openConfig.open()
- }
-
- QtDialogs.FileDialog {
- id: openConfig
- title: i18n("Import")
- folder: awConfig.configurationDirectory()
- onAccepted: importSelection.open()
- }
-
- QtDialogs.Dialog {
- id: importSelection
-
- Column {
- QtControls.CheckBox {
- id: importPlasmoid
- text: i18n("Import plasmoid settings")
- }
-
- QtControls.CheckBox {
- id: importExtensions
- text: i18n("Import extensions")
- }
-
- QtControls.CheckBox {
- id: importAdds
- text: i18n("Import additional files")
- }
- }
-
- onAccepted: {
+ onClicked: {
if (debug) console.debug()
- var importConfig = awConfig.importConfiguration(
- openConfig.fileUrl.toString().replace("file://", ""),
- importPlasmoid.checked, importExtensions.checked,
- importAdds.checked)
+ var importConfig = awConfig.importConfiguration()
for (var key in importConfig)
plasmoid.configuration[key] = importConfig[key]
}
diff --git a/sources/awesome-widget/package/contents/ui/main.qml b/sources/awesome-widget/package/contents/ui/main.qml
index 23e9690..ec83b91 100644
--- a/sources/awesome-widget/package/contents/ui/main.qml
+++ b/sources/awesome-widget/package/contents/ui/main.qml
@@ -17,7 +17,6 @@
import QtQuick 2.4
import QtQuick.Controls 1.3 as QtControls
-import QtQuick.Dialogs 1.2 as QtDialogs
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
@@ -110,27 +109,6 @@ Item {
}
}
- QtDialogs.Dialog {
- id: tagSelector
- title: i18n("Select tag")
-
- QtControls.ComboBox {
- id: tagSelectorBox
- width: parent.width
- editable: true
- }
-
- onAccepted: {
- var tag = tagSelectorBox.editText
- var message = i18n("Tag: %1", tag)
- message += "<br>"
- message += i18n("Value: %1", awKeys.valueByKey(tag))
- message += "<br>"
- message += i18n("Info: %1", awKeys.infoByKey(tag))
- awActions.sendNotification("tag", message)
- }
- }
-
Component.onCompleted: {
if (debug) console.debug()
@@ -216,7 +194,12 @@ Item {
function action_requestKey() {
if (debug) console.debug()
- tagSelectorBox.model = awKeys.dictKeys(true)
- return tagSelector.open()
+ var tag = awKeys.graphicalKey()
+ var message = i18n("Tag: %1", tag)
+ message += "<br>"
+ message += i18n("Value: %1", awKeys.valueByKey(tag))
+ message += "<br>"
+ message += i18n("Info: %1", awKeys.infoByKey(tag))
+ awActions.sendNotification("tag", message)
}
}
diff --git a/sources/awesome-widget/plugin/awconfighelper.cpp b/sources/awesome-widget/plugin/awconfighelper.cpp
index 6263b30..5f61d2a 100644
--- a/sources/awesome-widget/plugin/awconfighelper.cpp
+++ b/sources/awesome-widget/plugin/awconfighelper.cpp
@@ -19,10 +19,15 @@
#include <KI18n/KLocalizedString>
+#include <QCheckBox>
+#include <QDialogButtonBox>
#include <QDir>
+#include <QFileDialog>
+#include <QMessageBox>
#include <QQmlPropertyMap>
#include <QSettings>
#include <QTextCodec>
+#include <QVBoxLayout>
#include "awdebug.h"
@@ -50,11 +55,13 @@ bool AWConfigHelper::dropCache() const
}
-bool AWConfigHelper::exportConfiguration(const QObject *nativeConfig,
- const QString fileName) const
+void AWConfigHelper::exportConfiguration(const QObject *nativeConfig) const
{
- qCDebug(LOG_AW) << "Selected filename" << fileName;
-
+ // get file path and init settings object
+ QString fileName = QFileDialog::getSaveFileName(nullptr, i18n("Export"));
+ if (fileName.isEmpty())
+ return;
+ qCInfo(LOG_AW) << "Selected filename" << fileName;
QSettings settings(fileName, QSettings::IniFormat);
// plasmoid configuration
@@ -96,22 +103,33 @@ bool AWConfigHelper::exportConfiguration(QObject *nativeConfig,
// sync settings
settings.sync();
// show additional message
- return settings.status() == QSettings::NoError;
+ switch (settings.status()) {
+ case QSettings::NoError:
+ QMessageBox::information(
+ nullptr, i18n("Success"),
+ i18n("Please note that binary files were not copied"));
+ break;
+ default:
+ QMessageBox::critical(nullptr, i18n("Ooops..."),
+ i18n("Could not save configuration file"));
+ break;
+ }
}
-QVariantMap AWConfigHelper::importConfiguration(const QString fileName,
- const bool importPlasmoid,
- const bool importExtensions,
- const bool importAdds) const
+QVariantMap AWConfigHelper::importConfiguration() const
{
- qCDebug(LOG_AW) << "Selected filename" << fileName;
-
QVariantMap configuration;
+ // get file path and init settings object
+ QString fileName = QFileDialog::getOpenFileName(nullptr, i18n("Import"));
+ if (fileName.isEmpty())
+ return configuration;
+ qCInfo(LOG_AW) << "Selected filename" << fileName;
QSettings settings(fileName, QSettings::IniFormat);
+ QHash<QString, bool> selection = selectImport();
// extensions
- if (importExtensions) {
+ if (selection[QString("extensions")]) {
for (auto item : m_dirs) {
settings.beginGroup(item);
for (auto it : settings.childGroups())
@@ -121,7 +139,7 @@ QVariantMap AWConfigHelper::importConfiguration(const QString fileName,
}
// additional files
- if (importAdds) {
+ if (selection[QString("adds")]) {
settings.beginGroup(QString("json"));
// script filters
writeFile(settings, QString("filters"),
@@ -135,7 +153,7 @@ QVariantMap AWConfigHelper::importConfiguration(const QString fileName,
}
// plasmoid configuration
- if (importPlasmoid) {
+ if (selection[QString("plasmoid")]) {
settings.beginGroup(QString("plasmoid"));
for (auto key : settings.childKeys())
configuration[key] = settings.value(key);
@@ -261,6 +279,50 @@ void AWConfigHelper::readFile(QSettings &settings, const QString key,
}
+QHash<QString, bool> AWConfigHelper::selectImport() const
+{
+ QDialog *dialog = new QDialog(nullptr);
+ QCheckBox *importPlasmoidSettings
+ = new QCheckBox(i18n("Import plasmoid settings"), dialog);
+ importPlasmoidSettings->setChecked(true);
+ QCheckBox *importExtensionsSettings
+ = new QCheckBox(i18n("Import extensions"), dialog);
+ importExtensionsSettings->setChecked(true);
+ QCheckBox *importAddsSettings
+ = new QCheckBox(i18n("Import additional files"), dialog);
+ importAddsSettings->setChecked(true);
+ QDialogButtonBox *dialogButtons
+ = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
+ Qt::Horizontal, dialog);
+ QVBoxLayout *layout = new QVBoxLayout(dialog);
+ layout->addWidget(importPlasmoidSettings);
+ layout->addWidget(importExtensionsSettings);
+ layout->addWidget(importAddsSettings);
+ layout->addWidget(dialogButtons);
+ connect(dialogButtons, SIGNAL(accepted()), dialog, SLOT(accept()));
+ connect(dialogButtons, SIGNAL(rejected()), dialog, SLOT(reject()));
+
+ // get parameters
+ QHash<QString, bool> import;
+ import[QString("plasmoid")] = false;
+ import[QString("extensions")] = false;
+ import[QString("adds")] = false;
+ switch (dialog->exec()) {
+ case QDialog::Accepted:
+ import[QString("plasmoid")] = importPlasmoidSettings->isChecked();
+ import[QString("extensions")] = importExtensionsSettings->isChecked();
+ import[QString("adds")] = importAddsSettings->isChecked();
+ break;
+ case QDialog::Rejected:
+ default:
+ break;
+ }
+ dialog->deleteLater();
+
+ return import;
+}
+
+
void AWConfigHelper::writeFile(QSettings &settings, const QString key,
const QString fileName) const
{
diff --git a/sources/awesome-widget/plugin/awconfighelper.h b/sources/awesome-widget/plugin/awconfighelper.h
index 912ac3d..dc51dfb 100644
--- a/sources/awesome-widget/plugin/awconfighelper.h
+++ b/sources/awesome-widget/plugin/awconfighelper.h
@@ -33,13 +33,9 @@ public:
explicit AWConfigHelper(QObject *parent = nullptr);
virtual ~AWConfigHelper();
Q_INVOKABLE QString configurationDirectory() const;
Q_INVOKABLE bool dropCache() const;
- Q_INVOKABLE bool exportConfiguration(const QObject *nativeConfig,
- const QString fileName) const;
- Q_INVOKABLE QVariantMap importConfiguration(const QString fileName,
- const bool importPlasmoid,
- const bool importExtensions,
- const bool importAdds) const;
+ Q_INVOKABLE void exportConfiguration(const QObject *nativeConfig) const;
+ Q_INVOKABLE QVariantMap importConfiguration() const;
// dataengine
Q_INVOKABLE QVariantMap readDataEngineConfiguration() const;
Q_INVOKABLE bool
@@ -51,6 +47,7 @@ private:
void copySettings(QSettings &from, QSettings &to) const;
void readFile(QSettings &settings, const QString key,
const QString fileName) const;
+ QHash<QString, bool> selectImport() const;
void writeFile(QSettings &settings, const QString key,
const QString fileName) const;
// properties
diff --git a/sources/awesome-widget/plugin/awkeys.cpp b/sources/awesome-widget/plugin/awkeys.cpp
index e5b9861..039d24e 100644
--- a/sources/awesome-widget/plugin/awkeys.cpp
+++ b/sources/awesome-widget/plugin/awkeys.cpp
@@ -324,6 +324,14 @@ QStringList AWKeys::getHddDevices() const
}
+#include <QInputDialog>
+QString AWKeys::graphicalKey() const
+{
+ return QInputDialog::getItem(nullptr, i18n("Select tag"), QString(),
+ dictKeys(true), 0, true);
+}
+
+
QString AWKeys::infoByKey(QString key) const
{
qCDebug(LOG_AW) << "Requested info for key" << key;
diff --git a/sources/awesome-widget/plugin/awkeys.h b/sources/awesome-widget/plugin/awkeys.h
index a8300f1..8edc3bd 100644
--- a/sources/awesome-widget/plugin/awkeys.h
+++ b/sources/awesome-widget/plugin/awkeys.h
@@ -55,6 +55,7 @@ public:
Q_INVOKABLE QStringList dictKeys(const bool sorted = false,
const QString regexp = QString()) const;
Q_INVOKABLE QStringList getHddDevices() const;
+ Q_INVOKABLE QString graphicalKey() const;
// values
Q_INVOKABLE QString infoByKey(QString key) const;
Q_INVOKABLE QString valueByKey(QString key) const;
diff --git a/sources/awdebug.cpp b/sources/awdebug.cpp
index eee61e1..9da8dad 100644
--- a/sources/awdebug.cpp
+++ b/sources/awdebug.cpp
@@ -20,15 +20,11 @@
#include "awdebug.h"
-Q_LOGGING_CATEGORY(LOG_AW, "org.kde.plasma.awesomewidget",
- QtMsgType::QtWarningMsg)
-Q_LOGGING_CATEGORY(LOG_DP, "org.kde.plasma.desktoppanel",
- QtMsgType::QtWarningMsg)
-Q_LOGGING_CATEGORY(LOG_ESM, "org.kde.plasma.extsysmon", QtMsgType::QtWarningMsg)
-Q_LOGGING_CATEGORY(LOG_ESS, "org.kde.plasma.extsysmonsources",
- QtMsgType::QtWarningMsg)
-Q_LOGGING_CATEGORY(LOG_LIB, "org.kde.plasma.awesomewidgets",
- QtMsgType::QtWarningMsg)
+Q_LOGGING_CATEGORY(LOG_AW, "org.kde.plasma.awesomewidget")
+Q_LOGGING_CATEGORY(LOG_DP, "org.kde.plasma.desktoppanel")
+Q_LOGGING_CATEGORY(LOG_ESM, "org.kde.plasma.extsysmon")
+Q_LOGGING_CATEGORY(LOG_ESM, "org.kde.plasma.extsysmonsources")
+Q_LOGGING_CATEGORY(LOG_LIB, "org.kde.plasma.awesomewidgets")
const QStringList getBuildData()
diff --git a/sources/awesome-widget/plugin/awkeys.cpp b/sources/awesome-widget/plugin/awkeys.cpp
index e5b9861..eb73073 100644
--- a/sources/awesome-widget/plugin/awkeys.cpp
+++ b/sources/awesome-widget/plugin/awkeys.cpp
@@ -439,4 +439,4 @@ void AWKeys::dataUpdated(const QString &sourceName,
{
// run concurrent data update
- QtConcurrent::run(m_threadPool, this, &AWKeys::setDataBySource, sourceName,
+ QtConcurrent::run(this, &AWKeys::setDataBySource, sourceName,
data);
diff --git a/sources/libraries.cmake b/sources/libraries.cmake
index 33192f7..46e2b1e 100644
--- a/sources/libraries.cmake
+++ b/sources/libraries.cmake
@@ -2,7 +2,7 @@
find_package(Gettext REQUIRED)
# main qt libraries
-find_package(Qt5 5.4.0 REQUIRED COMPONENTS Core DBus Network Qml Test Widgets)
+find_package(Qt5 5.3.0 REQUIRED COMPONENTS Core DBus Network Qml Test Widgets)
add_definitions(
${Qt5Core_DEFINITIONS} ${Qt5DBus_DEFINITIONS} ${Qt5Network_DEFINITIONS}
${Qt5Qml_DEFINITIONS} ${Qt5Widgets_DEFINITIONS}

View File

@ -1,31 +0,0 @@
diff --git a/sources/awesome-widget/plugin/awkeysaggregator.h b/sources/awesome-widget/plugin/awkeysaggregator.h
index f808d03..a056b3f 100644
--- a/sources/awesome-widget/plugin/awkeysaggregator.h
+++ b/sources/awesome-widget/plugin/awkeysaggregator.h
@@ -21,6 +21,7 @@
#include <QHash>
#include <QObject>
+#include <QStringList>
#include "version.h"
diff --git a/sources/awdebug.h b/sources/awdebug.h
index 43944ce..c679281 100644
--- a/sources/awdebug.h
+++ b/sources/awdebug.h
@@ -21,9 +21,13 @@
#include "version.h"
+#ifndef qCInfo
+#define qCInfo qCDebug
+#endif
+
#ifndef LOG_FORMAT
#define LOG_FORMAT \
- "[%{time process}][%{if-debug}DD%{endif}%{if-info}II%{endif}%{if-" \
+ "[%{time process}][%{if-debug}DD%{endif}%{if-" \
"warning}WW%{endif}%{if-critical}CC%{endif}%{if-fatal}FF%{endif}][%{" \
"category}][%{function}] %{message}"
#endif /* LOG_FORMAT */

View File

@ -1,148 +0,0 @@
diff --git a/sources/awesome-widget/plugin/awupdatehelper.cpp b/sources/awesome-widget/plugin/awupdatehelper.cpp
index 3698602..42871c8 100644
--- a/sources/awesome-widget/plugin/awupdatehelper.cpp
+++ b/sources/awesome-widget/plugin/awupdatehelper.cpp
@@ -37,7 +37,7 @@ AWUpdateHelper::AWUpdateHelper(QObject *parent)
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
- m_foundVersion = QVersionNumber::fromString(VERSION);
+ m_foundVersion = QString(VERSION);
m_genericConfig = QString("%1/awesomewidgets/general.ini")
.arg(QStandardPaths::writableLocation(
QStandardPaths::GenericDataLocation));
@@ -69,15 +69,15 @@ void AWUpdateHelper::checkUpdates(const bool showAnyway)
bool AWUpdateHelper::checkVersion()
{
QSettings settings(m_genericConfig, QSettings::IniFormat);
- QVersionNumber version = QVersionNumber::fromString(
- settings.value(QString("Version"), QString(VERSION)).toString());
+ QString version
+ = settings.value(QString("Version"), QString(VERSION)).toString();
// update version
settings.setValue(QString("Version"), QString(VERSION));
settings.sync();
qCInfo(LOG_AW) << "Found version" << version << "actual one is"
<< m_foundVersion;
- if ((version != m_foundVersion) && (!QString(CHANGELOG).isEmpty())) {
+ if ((version != QString(VERSION)) && (!QString(CHANGELOG).isEmpty())) {
genMessageBox(i18n("Changelog of %1", QString(VERSION)),
QString(CHANGELOG).replace(QChar('@'), QChar('\n')),
QMessageBox::Ok)
@@ -90,12 +90,11 @@ bool AWUpdateHelper::checkVersion()
}
-void AWUpdateHelper::showInfo(const QVersionNumber version)
+void AWUpdateHelper::showInfo(const QString version)
{
qCDebug(LOG_AW) << "Version" << version;
- QString text
- = i18n("You are using the actual version %1", version.toString());
+ QString text = i18n("You are using the actual version %1", version);
if (!QString(COMMIT_SHA).isEmpty())
text += QString(" (%1)").arg(QString(COMMIT_SHA));
return genMessageBox(i18n("No new version found"), text, QMessageBox::Ok)
@@ -103,7 +102,7 @@ void AWUpdateHelper::showInfo(const QVersionNumber version)
}
-void AWUpdateHelper::showUpdates(const QVersionNumber version)
+void AWUpdateHelper::showUpdates(const QString version)
{
qCDebug(LOG_AW) << "Version" << version;
@@ -112,7 +111,7 @@ void AWUpdateHelper::showUpdates(const QVersionNumber version)
text += QString(COMMIT_SHA).isEmpty()
? QString("\n")
: QString(" (%1)\n").arg(QString(COMMIT_SHA));
- text += i18n("New version : %1", version.toString()) + QString("\n\n");
+ text += i18n("New version : %1", version) + QString("\n\n");
text += i18n("Click \"Ok\" to download");
genMessageBox(i18n("There are updates"), text,
@@ -128,8 +127,7 @@ void AWUpdateHelper::userReplyOnUpdates(QAbstractButton *button)
switch (ret) {
case QMessageBox::AcceptRole:
- QDesktopServices::openUrl(QString(RELEASES)
- + m_foundVersion.toString());
+ QDesktopServices::openUrl(QString(RELEASES) + m_foundVersion);
break;
case QMessageBox::RejectRole:
default:
@@ -157,14 +155,23 @@ void AWUpdateHelper::versionReplyRecieved(QNetworkReply *reply,
QVariantMap firstRelease = jsonDoc.toVariant().toList().first().toMap();
QString version = firstRelease[QString("tag_name")].toString();
version.remove(QString("V."));
- m_foundVersion = QVersionNumber::fromString(version);
+ m_foundVersion = version;
qCInfo(LOG_AW) << "Update found version to" << m_foundVersion;
- QVersionNumber oldVersion = QVersionNumber::fromString(VERSION);
- if (oldVersion < m_foundVersion)
- return showUpdates(m_foundVersion);
+ // FIXME: possible there is a better way to check versions
+ int old_major = QString(VERSION).split(QChar('.')).at(0).toInt();
+ int old_minor = QString(VERSION).split(QChar('.')).at(1).toInt();
+ int old_patch = QString(VERSION).split(QChar('.')).at(2).toInt();
+ int new_major = version.split(QChar('.')).at(0).toInt();
+ int new_minor = version.split(QChar('.')).at(1).toInt();
+ int new_patch = version.split(QChar('.')).at(2).toInt();
+ if ((old_major < new_major)
+ || ((old_major == new_major) && (old_minor < new_minor))
+ || ((old_major == new_major) && (old_minor == new_minor)
+ && (old_patch < new_patch)))
+ return showUpdates(version);
else if (showAnyway)
- return showInfo(m_foundVersion);
+ return showInfo(version);
}
diff --git a/sources/awesome-widget/plugin/awupdatehelper.h b/sources/awesome-widget/plugin/awupdatehelper.h
index 359cdb2..9c6a42d 100644
--- a/sources/awesome-widget/plugin/awupdatehelper.h
+++ b/sources/awesome-widget/plugin/awupdatehelper.h
@@ -21,7 +21,6 @@
#include <QMessageBox>
#include <QObject>
-#include <QVersionNumber>
class QNetworkReply;
@@ -37,15 +36,15 @@ public:
bool checkVersion();
private slots:
- void showInfo(const QVersionNumber version);
- void showUpdates(const QVersionNumber version);
+ void showInfo(const QString version);
+ void showUpdates(const QString version);
void userReplyOnUpdates(QAbstractButton *button);
void versionReplyRecieved(QNetworkReply *reply, const bool showAnyway);
private:
QMessageBox *genMessageBox(const QString title, const QString body,
const QMessageBox::StandardButtons buttons);
- QVersionNumber m_foundVersion;
+ QString m_foundVersion;
QString m_genericConfig;
};
diff --git a/sources/libraries.cmake b/sources/libraries.cmake
index 33192f7..339bb58 100644
--- a/sources/libraries.cmake
+++ b/sources/libraries.cmake
@@ -2,7 +2,7 @@
find_package(Gettext REQUIRED)
# main qt libraries
-find_package(Qt5 5.6.0 REQUIRED COMPONENTS Core DBus Network Qml Test Widgets)
+find_package(Qt5 5.4.0 REQUIRED COMPONENTS Core DBus Network Qml Test Widgets)
add_definitions(
${Qt5Core_DEFINITIONS} ${Qt5DBus_DEFINITIONS} ${Qt5Network_DEFINITIONS}
${Qt5Qml_DEFINITIONS} ${Qt5Widgets_DEFINITIONS}

284
sensors Normal file
View File

@ -0,0 +1,284 @@
cpu
cpu/all
cpu/all/averageFrequency
cpu/all/averageTemperature
cpu/all/coreCount
cpu/all/cpuCount
cpu/all/maximumFrequency
cpu/all/maximumTemperature
cpu/all/minimumFrequency
cpu/all/minimumTemperature
cpu/all/name
cpu/all/system
cpu/all/usage
cpu/all/user
cpu/all/wait
cpu/cpu0
cpu/cpu0/frequency
cpu/cpu0/name
cpu/cpu0/system
cpu/cpu0/temperature
cpu/cpu0/usage
cpu/cpu0/user
cpu/cpu0/wait
cpu/cpu1
cpu/cpu1/frequency
cpu/cpu1/name
cpu/cpu1/system
cpu/cpu1/temperature
cpu/cpu1/usage
cpu/cpu1/user
cpu/cpu1/wait
cpu/cpu10
cpu/cpu10/frequency
cpu/cpu10/name
cpu/cpu10/system
cpu/cpu10/temperature
cpu/cpu10/usage
cpu/cpu10/user
cpu/cpu10/wait
cpu/cpu11
cpu/cpu11/frequency
cpu/cpu11/name
cpu/cpu11/system
cpu/cpu11/temperature
cpu/cpu11/usage
cpu/cpu11/user
cpu/cpu11/wait
cpu/cpu12
cpu/cpu12/frequency
cpu/cpu12/name
cpu/cpu12/system
cpu/cpu12/temperature
cpu/cpu12/usage
cpu/cpu12/user
cpu/cpu12/wait
cpu/cpu13
cpu/cpu13/frequency
cpu/cpu13/name
cpu/cpu13/system
cpu/cpu13/temperature
cpu/cpu13/usage
cpu/cpu13/user
cpu/cpu13/wait
cpu/cpu14
cpu/cpu14/frequency
cpu/cpu14/name
cpu/cpu14/system
cpu/cpu14/temperature
cpu/cpu14/usage
cpu/cpu14/user
cpu/cpu14/wait
cpu/cpu15
cpu/cpu15/frequency
cpu/cpu15/name
cpu/cpu15/system
cpu/cpu15/temperature
cpu/cpu15/usage
cpu/cpu15/user
cpu/cpu15/wait
cpu/cpu16
cpu/cpu16/frequency
cpu/cpu16/name
cpu/cpu16/system
cpu/cpu16/temperature
cpu/cpu16/usage
cpu/cpu16/user
cpu/cpu16/wait
cpu/cpu17
cpu/cpu17/frequency
cpu/cpu17/name
cpu/cpu17/system
cpu/cpu17/temperature
cpu/cpu17/usage
cpu/cpu17/user
cpu/cpu17/wait
cpu/cpu18
cpu/cpu18/frequency
cpu/cpu18/name
cpu/cpu18/system
cpu/cpu18/temperature
cpu/cpu18/usage
cpu/cpu18/user
cpu/cpu18/wait
cpu/cpu19
cpu/cpu19/frequency
cpu/cpu19/name
cpu/cpu19/system
cpu/cpu19/temperature
cpu/cpu19/usage
cpu/cpu19/user
cpu/cpu19/wait
cpu/cpu2
cpu/cpu2/frequency
cpu/cpu2/name
cpu/cpu2/system
cpu/cpu2/temperature
cpu/cpu2/usage
cpu/cpu2/user
cpu/cpu2/wait
cpu/cpu3
cpu/cpu3/frequency
cpu/cpu3/name
cpu/cpu3/system
cpu/cpu3/temperature
cpu/cpu3/usage
cpu/cpu3/user
cpu/cpu3/wait
cpu/cpu4
cpu/cpu4/frequency
cpu/cpu4/name
cpu/cpu4/system
cpu/cpu4/temperature
cpu/cpu4/usage
cpu/cpu4/user
cpu/cpu4/wait
cpu/cpu5
cpu/cpu5/frequency
cpu/cpu5/name
cpu/cpu5/system
cpu/cpu5/temperature
cpu/cpu5/usage
cpu/cpu5/user
cpu/cpu5/wait
cpu/cpu6
cpu/cpu6/frequency
cpu/cpu6/name
cpu/cpu6/system
cpu/cpu6/temperature
cpu/cpu6/usage
cpu/cpu6/user
cpu/cpu6/wait
cpu/cpu7
cpu/cpu7/frequency
cpu/cpu7/name
cpu/cpu7/system
cpu/cpu7/temperature
cpu/cpu7/usage
cpu/cpu7/user
cpu/cpu7/wait
cpu/cpu8
cpu/cpu8/frequency
cpu/cpu8/name
cpu/cpu8/system
cpu/cpu8/temperature
cpu/cpu8/usage
cpu/cpu8/user
cpu/cpu8/wait
cpu/cpu9
cpu/cpu9/frequency
cpu/cpu9/name
cpu/cpu9/system
cpu/cpu9/temperature
cpu/cpu9/usage
cpu/cpu9/user
cpu/cpu9/wait
cpu/loadaverages
cpu/loadaverages/loadaverage1
cpu/loadaverages/loadaverage15
cpu/loadaverages/loadaverage5
disk
disk/52e29d18-ad4d-47ad-98c4-a09ab0914a85
disk/52e29d18-ad4d-47ad-98c4-a09ab0914a85/free
disk/52e29d18-ad4d-47ad-98c4-a09ab0914a85/freePercent
disk/52e29d18-ad4d-47ad-98c4-a09ab0914a85/name
disk/52e29d18-ad4d-47ad-98c4-a09ab0914a85/read
disk/52e29d18-ad4d-47ad-98c4-a09ab0914a85/total
disk/52e29d18-ad4d-47ad-98c4-a09ab0914a85/used
disk/52e29d18-ad4d-47ad-98c4-a09ab0914a85/usedPercent
disk/52e29d18-ad4d-47ad-98c4-a09ab0914a85/write
disk/all
disk/all/free
disk/all/freePercent
disk/all/read
disk/all/total
disk/all/used
disk/all/usedPercent
disk/all/write
disk/d10dd7bf-e382-4e44-83d7-9af6c6df7258
disk/d10dd7bf-e382-4e44-83d7-9af6c6df7258/free
disk/d10dd7bf-e382-4e44-83d7-9af6c6df7258/freePercent
disk/d10dd7bf-e382-4e44-83d7-9af6c6df7258/name
disk/d10dd7bf-e382-4e44-83d7-9af6c6df7258/read
disk/d10dd7bf-e382-4e44-83d7-9af6c6df7258/total
disk/d10dd7bf-e382-4e44-83d7-9af6c6df7258/used
disk/d10dd7bf-e382-4e44-83d7-9af6c6df7258/usedPercent
disk/d10dd7bf-e382-4e44-83d7-9af6c6df7258/write
disk/nvme0n1
disk/nvme0n1/name
disk/nvme0n1/read
disk/nvme0n1/total
disk/nvme0n1/write
gpu
lmsensors
lmsensors/BAT0-acpi-0
lmsensors/BAT0-acpi-0/in0
lmsensors/acpitz-acpi-0
lmsensors/acpitz-acpi-0/temp1
lmsensors/iwlwifi_1-virtual-0
lmsensors/iwlwifi_1-virtual-0/temp1
lmsensors/nvme-pci-0400
lmsensors/nvme-pci-0400/temp1
lmsensors/thinkpad-isa-0000
lmsensors/thinkpad-isa-0000/fan1
lmsensors/thinkpad-isa-0000/fan2
lmsensors/thinkpad-isa-0000/temp1
lmsensors/thinkpad-isa-0000/temp2
lmsensors/thinkpad-isa-0000/temp3
lmsensors/thinkpad-isa-0000/temp4
lmsensors/thinkpad-isa-0000/temp5
lmsensors/thinkpad-isa-0000/temp6
lmsensors/thinkpad-isa-0000/temp7
lmsensors/thinkpad-isa-0000/temp8
lmsensors/ucsi_source_psy_USBC000:001-isa-0000
lmsensors/ucsi_source_psy_USBC000:001-isa-0000/curr1
lmsensors/ucsi_source_psy_USBC000:001-isa-0000/in0
lmsensors/ucsi_source_psy_USBC000:002-isa-0000
lmsensors/ucsi_source_psy_USBC000:002-isa-0000/curr1
lmsensors/ucsi_source_psy_USBC000:002-isa-0000/in0
memory
memory/physical
memory/physical/application
memory/physical/applicationPercent
memory/physical/buffer
memory/physical/bufferPercent
memory/physical/cache
memory/physical/cachePercent
memory/physical/free
memory/physical/freePercent
memory/physical/total
memory/physical/used
memory/physical/usedPercent
memory/swap
memory/swap/free
memory/swap/freePercent
memory/swap/total
memory/swap/used
memory/swap/usedPercent
os
os/kernel
os/kernel/name
os/kernel/prettyName
os/kernel/version
os/plasma
os/plasma/kfVersion
os/plasma/plasmaVersion
os/plasma/qtVersion
os/plasma/windowsystem
os/system
os/system/hostname
os/system/logo
os/system/name
os/system/prettyName
os/system/uptime
os/system/url
os/system/version
power
power/4870
power/4870/capacity
power/4870/charge
power/4870/chargePercentage
power/4870/chargeRate
power/4870/design
power/4870/health
power/4870/name

View File

@ -1,27 +1,26 @@
--- ---
Language: Cpp Language: Cpp
AccessModifierOffset: -4 AccessModifierOffset: -4
AlignAfterOpenBracket: true AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false AlignConsecutiveAssignments: None
AlignEscapedNewlinesLeft: false
AlignOperands: true AlignOperands: true
AlignTrailingComments: true AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakBeforeMultilineStrings: false AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false AlwaysBreakTemplateDeclarations: No
BinPackArguments: true BinPackArguments: true
BinPackParameters: true BinPackParameters: true
BreakBeforeBinaryOperators: All BreakBeforeBinaryOperators: All
BreakBeforeBraces: Linux BreakBeforeBraces: Linux
BreakBeforeTernaryOperators: true BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true BreakConstructorInitializersBeforeComma: true
ColumnLimit: 80 ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:' CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4 ConstructorInitializerIndentWidth: 4
@ -59,7 +58,7 @@ SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false SpacesInCStyleCastParentheses: false
SpacesInParentheses: false SpacesInParentheses: false
SpacesInSquareBrackets: false SpacesInSquareBrackets: false
Standard: Cpp11 Standard: Latest
TabWidth: 8 TabWidth: 8
UseTab: Never UseTab: Never
... ...

View File

@ -1,26 +0,0 @@
[Buildset]
BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x1e\x00a\x00w\x00e\x00s\x00o\x00m\x00e\x00-\x00w\x00i\x00d\x00g\x00e\x00t\x00s)
[CMake]
Build Directory Count=1
Current Build Directory Index=0
ProjectRootRelative=./
[CMake][CMake Build Directory 0]
Build Directory Path=file:///home/arcanis/Documents/github/awesome-widgets/build
Build Type=Optimization
CMake Binary=file:///usr/bin/cmake
Environment Profile=
Extra Arguments=
Install Directory=file:///usr
[Defines And Includes][Compiler]
Name=GCC
Path=gcc
Type=GCC
[Launch]
Launch Configurations=
[Project]
VersionControlSupport=kdevgit

View File

@ -1,23 +0,0 @@
[Buildset]
BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x1e\x00a\x00w\x00e\x00s\x00o\x00m\x00e\x00-\x00w\x00i\x00d\x00g\x00e\x00t\x00s)
[CMake]
Build Directory Count=1
Current Build Directory Index=0
ProjectRootRelative=./
[CMake][CMake Build Directory 0]
Build Directory Path=file:///home/arcanis/Documents/github/awesome-widgets/build
Build Type=Release
CMake Binary=file:///usr/bin/cmake
Environment Profile=
Extra Arguments=
Install Directory=file:///usr
[Defines And Includes][Compiler]
Name=GCC
Path=gcc
Type=GCC
[Project]
VersionControlSupport=kdevgit

165
sources/3rdparty/fontdialog/COPYING vendored Normal file
View File

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

4
sources/3rdparty/fontdialog/README.md vendored Normal file
View File

@ -0,0 +1,4 @@
qtadds-fontdialog
=================
Font dialog which provides a font color settings

View File

@ -0,0 +1,140 @@
/***************************************************************************
* Copyright (C) 2014 Evgeniy Alekseev *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 3.0 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library. *
***************************************************************************/
#include "fontdialog.h"
#include <QGridLayout>
CFont::CFont(const QString family, int pointSize, int weight, bool italic, QColor color)
: QFont(family, pointSize, weight, italic)
{
setCurrentColor(color);
}
QColor CFont::color()
{
return currentColor;
}
void CFont::setCurrentColor(const QColor color)
{
currentColor = color;
}
CFont CFont::fromQFont(const QFont font, const QColor color)
{
return CFont(font.family(), font.pointSize(), font.weight(), font.italic(), color);
}
QFont CFont::toQFont()
{
return QFont(family(), pointSize(), weight(), italic());
}
CFontDialog::CFontDialog(QWidget *parent, bool needWeight, bool needItalic)
: QDialog(parent)
{
QGridLayout *mainGrid = new QGridLayout(this);
setLayout(mainGrid);
colorBox = new QComboBox(this);
connect(colorBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(updateColor(QString)));
QStringList colorNames = QColor::colorNames();
int index = 0;
for (int i=0; i<colorNames.count(); i++) {
QColor color(colorNames[i]);
colorBox->addItem(colorNames[i], color);
QModelIndex idx = colorBox->model()->index(index++, 0);
colorBox->model()->setData(idx, color, Qt::BackgroundRole);
}
mainGrid->addWidget(colorBox, 0, 0);
fontBox = new QFontComboBox(this);
mainGrid->addWidget(fontBox, 0, 1);
sizeBox = new QSpinBox(this);
mainGrid->addWidget(sizeBox, 0, 2);
weightBox = new QSpinBox(this);
mainGrid->addWidget(weightBox, 0, 3);
italicBox = new QComboBox(this);
italicBox->addItem(tr("normal"));
italicBox->addItem(tr("italic"));
mainGrid->addWidget(italicBox, 0, 4);
buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
Qt::Horizontal, this);
QObject::connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
QObject::connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
mainGrid->addWidget(buttons, 1, 0, 1, 5);
italicBox->setHidden(!needItalic);
weightBox->setHidden(!needWeight);
}
CFontDialog::~CFontDialog()
{
delete colorBox;
delete buttons;
delete fontBox;
delete italicBox;
delete sizeBox;
delete weightBox;
}
void CFontDialog::updateColor(const QString color)
{
colorBox->setStyleSheet(QString("background:%1").arg(QColor(color).name()));
}
CFont CFontDialog::getFont(const QString title, CFont defaultFont, bool needWeight, bool needItalic, int *status)
{
CFontDialog dlg(0, needWeight, needItalic);
dlg.setWindowTitle(title);
QStringList colorNames = QColor::colorNames();
for (int i=0; i<colorNames.count(); i++)
if (QColor(colorNames[i]) == defaultFont.color()) {
dlg.colorBox->setCurrentIndex(i);
break;
}
dlg.fontBox->setCurrentFont(defaultFont);
dlg.sizeBox->setValue(defaultFont.pointSize());
dlg.weightBox->setValue(defaultFont.weight());
if (defaultFont.italic())
dlg.italicBox->setCurrentIndex(1);
else
dlg.italicBox->setCurrentIndex(0);
CFont font = CFont(defaultFont);
int ret = dlg.exec();
if (ret == 1)
font = CFont(dlg.fontBox->currentFont().family(),
dlg.sizeBox->value(),
dlg.weightBox->value(),
dlg.italicBox->currentIndex() == 1,
QColor(dlg.colorBox->currentText()));
if (status != nullptr)
*status = ret;
return font;
}

View File

@ -0,0 +1,77 @@
/***************************************************************************
* Copyright (C) 2014 Evgeniy Alekseev *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 3.0 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library. *
***************************************************************************/
#ifndef FONTDIALOG_H
#define FONTDIALOG_H
#include <QComboBox>
#include <QDialog>
#include <QDialogButtonBox>
#include <QFontComboBox>
#include <QSpinBox>
class CFont : public QFont
{
public:
explicit CFont(const QString family, int pointSize = -1,
int weight = -1, bool italic = false,
QColor color = QColor(QString("#000000")));
// color properties
QColor color();
void setCurrentColor(const QColor color);
// conversion to QFont
static CFont fromQFont(const QFont font,
const QColor color = QColor(QString("#000000")));
QFont toQFont();
private:
QColor currentColor;
};
class CFontDialog : public QDialog
{
Q_OBJECT
public:
explicit CFontDialog(QWidget *parent = 0,
const bool needWeight = true,
const bool needItalic = true);
~CFontDialog();
static CFont getFont(const QString title = tr("Select font"),
CFont defaultFont = CFont(QString("Arial"),
12, 400, false,
QColor(QString("#000000"))),
const bool needWeight = true,
const bool needItalic = true,
int *status = nullptr);
private slots:
void updateColor(const QString color);
private:
QComboBox *colorBox;
QDialogButtonBox *buttons;
QFontComboBox *fontBox;
QComboBox *italicBox;
QSpinBox *sizeBox;
QSpinBox *weightBox;
};
#endif /* FONTDIALOG_H */

View File

@ -12,7 +12,7 @@ QReplyTimeout::QReplyTimeout(QNetworkReply *reply, const int timeout)
void QReplyTimeout::timeout() void QReplyTimeout::timeout()
{ {
QNetworkReply *reply = static_cast<QNetworkReply *>(parent()); auto *reply = dynamic_cast<QNetworkReply *>(parent());
if (reply->isRunning()) if (reply->isRunning())
reply->close(); reply->close();
} }

View File

@ -1,21 +1,22 @@
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 3.16.0)
# some fucking magic # some fucking magic
cmake_policy(SET CMP0003 OLD)
cmake_policy(SET CMP0002 OLD)
cmake_policy(SET CMP0011 NEW) cmake_policy(SET CMP0011 NEW)
cmake_policy(SET CMP0015 NEW) cmake_policy(SET CMP0015 NEW)
if (POLICY CMP0063) if (POLICY CMP0063)
cmake_policy(SET CMP0063 OLD) cmake_policy(SET CMP0063 NEW)
endif ()
if (POLICY CMP0071)
cmake_policy(SET CMP0071 NEW)
endif () endif ()
project(awesomewidgets) project(awesomewidgets)
set(PROJECT_AUTHOR "Evgeniy Alekseev") set(PROJECT_AUTHOR "Evgeniy Alekseev")
set(PROJECT_CONTACT "esalexeev@gmail.com") set(PROJECT_CONTACT "esalexeev@gmail.com")
set(PROJECT_LICENSE "GPL3") set(PROJECT_LICENSE "GPL3")
set(PROJECT_VERSION_MAJOR "3") set(PROJECT_VERSION_MAJOR "4")
set(PROJECT_VERSION_MINOR "2") set(PROJECT_VERSION_MINOR "0")
set(PROJECT_VERSION_PATCH "1") set(PROJECT_VERSION_PATCH "0")
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
# append git version if any # append git version if any
set(PROJECT_COMMIT_SHA "Commit hash" CACHE INTERNAL "") set(PROJECT_COMMIT_SHA "Commit hash" CACHE INTERNAL "")
@ -41,44 +42,28 @@ option(BUILD_TESTING "Build with additional test abilities" OFF)
set(PROJECT_CHANGELOG "Changelog" CACHE INTERNAL "") set(PROJECT_CHANGELOG "Changelog" CACHE INTERNAL "")
include(changelog.cmake) include(changelog.cmake)
# flags # directories
if (CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "-Wall -Wno-cpp -std=c++11")
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
set(CMAKE_CXX_FLAGS_OPTIMIZATION "-Ofast -DNDEBUG")
# avoid newer gcc warnings
add_definitions(-D_DEFAULT_SOURCE)
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "-Wall -std=c++11 -stdlib=libc++")
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
set(CMAKE_CXX_FLAGS_OPTIMIZATION "-Ofast -DNDEBUG")
# linker flags
set(CMAKE_EXE_LINKER_FLAGS "-lc++abi")
set(CMAKE_MODULE_LINKER_FLAGS "-lc++abi")
set(CMAKE_SHARED_LINKER_FLAGS "-lc++abi")
else ()
message(FATAL_ERROR "Unknown compiler")
endif ()
if (CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_VERBOSE_MAKEFILE ON)
endif ()
set(PROJECT_TRDPARTY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty) set(PROJECT_TRDPARTY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty)
set(PROJECT_LIBRARY awesomewidgets) set(PROJECT_LIBRARY awesomewidgets)
set(PROJECT_MONITORSOURCES extsysmonsources) set(PROJECT_MONITORSOURCES extsysmonsources)
# modules
include(compiler.cmake)
include(libraries.cmake) include(libraries.cmake)
include(clang-format.cmake) include(clang-format.cmake)
include(cppcheck.cmake) include(cppcheck.cmake)
include(coverity.cmake) include(coverity.cmake)
# pre-configure
get_directory_property(CMAKE_DEFINITIONS COMPILE_DEFINITIONS) get_directory_property(CMAKE_DEFINITIONS COMPILE_DEFINITIONS)
configure_file(${CMAKE_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h) configure_file(${CMAKE_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
# build components
add_subdirectory(awesomewidgets) add_subdirectory(awesomewidgets)
add_subdirectory(extsysmonsources) add_subdirectory(extsysmonsources)
add_subdirectory(extsysmon) add_subdirectory(extsysmon)
if (BUILD_PLASMOIDS) if (BUILD_PLASMOIDS)
add_subdirectory(qml)
add_subdirectory(awesome-widget) add_subdirectory(awesome-widget)
add_subdirectory(desktop-panel) add_subdirectory(desktop-panel)
add_subdirectory(translations) add_subdirectory(translations)

View File

@ -16,78 +16,111 @@
***************************************************************************/ ***************************************************************************/
#include <KI18n/KLocalizedString>
#include "awdebug.h" #include "awdebug.h"
Q_LOGGING_CATEGORY(LOG_AW, "org.kde.plasma.awesomewidget", Q_LOGGING_CATEGORY(LOG_AW, "org.kde.plasma.awesomewidget", QtMsgType::QtWarningMsg)
QtMsgType::QtWarningMsg) Q_LOGGING_CATEGORY(LOG_DBUS, "org.kde.plasma.awdbus", QtMsgType::QtWarningMsg)
Q_LOGGING_CATEGORY(LOG_DP, "org.kde.plasma.desktoppanel", Q_LOGGING_CATEGORY(LOG_DP, "org.kde.plasma.desktoppanel", QtMsgType::QtWarningMsg)
QtMsgType::QtWarningMsg)
Q_LOGGING_CATEGORY(LOG_ESM, "org.kde.plasma.extsysmon", QtMsgType::QtWarningMsg) Q_LOGGING_CATEGORY(LOG_ESM, "org.kde.plasma.extsysmon", QtMsgType::QtWarningMsg)
Q_LOGGING_CATEGORY(LOG_ESS, "org.kde.plasma.extsysmonsources", Q_LOGGING_CATEGORY(LOG_ESS, "org.kde.plasma.extsysmonsources", QtMsgType::QtWarningMsg)
QtMsgType::QtWarningMsg) Q_LOGGING_CATEGORY(LOG_LIB, "org.kde.plasma.awesomewidgets", QtMsgType::QtWarningMsg)
Q_LOGGING_CATEGORY(LOG_LIB, "org.kde.plasma.awesomewidgets",
QtMsgType::QtWarningMsg)
const QStringList getBuildData() QString AWDebug::getAboutText(const QString &_type)
{
QString text;
if (_type == "header") {
text = NAME;
} else if (_type == "version") {
text = i18n("Version %1 (build date %2)", VERSION, BUILD_DATE);
if (!QString(COMMIT_SHA).isEmpty())
text += QString(" (%1)").arg(COMMIT_SHA);
} else if (_type == "description") {
text = i18n("A set of minimalistic plasmoid widgets");
} else if (_type == "links") {
text = i18n("Links:") + "<ul>" + QString("<li><a href=\"%1\">%2</a></li>").arg(HOMEPAGE).arg(i18n("Homepage"))
+ QString("<li><a href=\"%1\">%2</a></li>").arg(REPOSITORY).arg(i18n("Repository"))
+ QString("<li><a href=\"%1\">%2</a></li>").arg(BUGTRACKER).arg(i18n("Bugtracker"))
+ QString("<li><a href=\"%1\">%2</a></li>").arg(TRANSLATION).arg(i18n("Translation issue"))
+ QString("<li><a href=\"%1\">%2</a></li>").arg(AUR_PACKAGES).arg(i18n("AUR packages"))
+ QString("<li><a href=\"%1\">%2</a></li>").arg(OPENSUSE_PACKAGES).arg(i18n("openSUSE packages"))
+ "</ul>";
} else if (_type == "copy") {
text = QString("<small>&copy; %1 <a href=\"mailto:%2\">%3</a><br>").arg(DATE).arg(EMAIL).arg(AUTHOR)
+ i18nc("This software is licensed under %1", LICENSE) + "</small>";
} else if (_type == "translators") {
QStringList translatorList = QString(TRANSLATORS).split(',');
for (auto &translator : translatorList)
translator = QString("<li>%1</li>").arg(translator);
text = i18n("Translators:") + "<ul>" + translatorList.join("") + "</ul>";
} else if (_type == "3rdparty") {
QStringList trdPartyList = QString(TRDPARTY_LICENSE).split(';', Qt::SkipEmptyParts);
for (int i = 0; i < trdPartyList.count(); i++)
trdPartyList[i] = QString("<li><a href=\"%3\">%1</a> (%2 license)</li>")
.arg(trdPartyList.at(i).split(',')[0])
.arg(trdPartyList.at(i).split(',')[1])
.arg(trdPartyList.at(i).split(',')[2]);
text = i18n("This software uses:") + "<ul>" + trdPartyList.join("") + "</ul>";
} else if (_type == "thanks") {
QStringList thanks = QString(SPECIAL_THANKS).split(';', Qt::SkipEmptyParts);
for (int i = 0; i < thanks.count(); i++)
thanks[i] = QString("<li><a href=\"%2\">%1</a></li>")
.arg(thanks.at(i).split(',')[0])
.arg(thanks.at(i).split(',')[1]);
text = i18n("Special thanks to:") + "<ul>" + thanks.join("") + "</ul>";
}
return text;
}
QStringList AWDebug::getBuildData()
{ {
QStringList metadata; QStringList metadata;
metadata.append(QString("=== Awesome Widgets configuration details ===")); metadata.append("=== Awesome Widgets configuration details ===");
// build information // build information
metadata.append(QString("Build details:")); metadata.append("Build details:");
metadata.append(QString(" VERSION: %1").arg(VERSION)); metadata.append(QString(" VERSION: %1").arg(VERSION));
metadata.append(QString(" COMMIT_SHA: %1").arg(COMMIT_SHA)); metadata.append(QString(" COMMIT_SHA: %1").arg(COMMIT_SHA));
metadata.append(QString(" BUILD_DATE: %1").arg(BUILD_DATE)); metadata.append(QString(" BUILD_DATE: %1").arg(BUILD_DATE));
// configuration // configuration
metadata.append(QString("API details:")); metadata.append("API details:");
metadata.append(QString(" AWGIAPI: %1").arg(AWGIAPI)); metadata.append(QString(" AW_GRAPHITEM_API: %1").arg(AW_GRAPHITEM_API));
metadata.append(QString(" AWEQAPI: %1").arg(AWEQAPI)); metadata.append(QString(" AW_EXTQUOTES_API: %1").arg(AW_EXTQUOTES_API));
metadata.append(QString(" AWESAPI: %1").arg(AWESAPI)); metadata.append(QString(" AW_EXTSCRIPT_API: %1").arg(AW_EXTSCRIPT_API));
metadata.append(QString(" AWEUAPI: %1").arg(AWEUAPI)); metadata.append(QString(" AW_EXTUPGRADE_API: %1").arg(AW_EXTUPGRADE_API));
metadata.append(QString(" AWEWAPI: %1").arg(AWEWAPI)); metadata.append(QString(" AW_EXTWEATHER_API: %1").arg(AW_EXTWEATHER_API));
metadata.append(QString(" AWEFAPI: %1").arg(AWEFAPI)); metadata.append(QString(" AW_FORMATTER_API: %1").arg(AW_FORMATTER_API));
metadata.append(QString(" REQUEST_TIMEOUT: %1").arg(REQUEST_TIMEOUT)); metadata.append(QString(" REQUEST_TIMEOUT: %1").arg(REQUEST_TIMEOUT));
metadata.append(QString(" TIME_KEYS: %1").arg(TIME_KEYS)); metadata.append(QString(" TIME_KEYS: %1").arg(TIME_KEYS));
metadata.append(QString(" STATIC_KEYS: %1").arg(STATIC_KEYS)); metadata.append(QString(" STATIC_KEYS: %1").arg(STATIC_KEYS));
// cmake properties // cmake properties
metadata.append(QString("cmake properties:")); metadata.append("cmake properties:");
metadata.append(QString(" CMAKE_BUILD_TYPE: %1").arg(CMAKE_BUILD_TYPE)); metadata.append(QString(" CMAKE_BUILD_TYPE: %1").arg(CMAKE_BUILD_TYPE));
metadata.append( metadata.append(QString(" CMAKE_CXX_COMPILER: %1").arg(CMAKE_CXX_COMPILER));
QString(" CMAKE_CXX_COMPILER: %1").arg(CMAKE_CXX_COMPILER));
metadata.append(QString(" CMAKE_CXX_FLAGS: %1").arg(CMAKE_CXX_FLAGS)); metadata.append(QString(" CMAKE_CXX_FLAGS: %1").arg(CMAKE_CXX_FLAGS));
metadata.append( metadata.append(QString(" CMAKE_CXX_FLAGS_DEBUG: %1").arg(CMAKE_CXX_FLAGS_DEBUG));
QString(" CMAKE_CXX_FLAGS_DEBUG: %1").arg(CMAKE_CXX_FLAGS_DEBUG)); metadata.append(QString(" CMAKE_CXX_FLAGS_RELEASE: %1").arg(CMAKE_CXX_FLAGS_RELEASE));
metadata.append(QString(" CMAKE_CXX_FLAGS_RELEASE: %1") metadata.append(QString(" CMAKE_CXX_FLAGS_OPTIMIZATION: %1").arg(CMAKE_CXX_FLAGS_OPTIMIZATION));
.arg(CMAKE_CXX_FLAGS_RELEASE)); metadata.append(QString(" CMAKE_DEFINITIONS: %1").arg(CMAKE_DEFINITIONS));
metadata.append(QString(" CMAKE_CXX_FLAGS_OPTIMIZATION: %1") metadata.append(QString(" CMAKE_INSTALL_PREFIX: %1").arg(CMAKE_INSTALL_PREFIX));
.arg(CMAKE_CXX_FLAGS_OPTIMIZATION)); metadata.append(QString(" CMAKE_MODULE_LINKER_FLAGS: %1").arg(CMAKE_MODULE_LINKER_FLAGS));
metadata.append( metadata.append(QString(" CMAKE_SHARED_LINKER_FLAGS: %1").arg(CMAKE_SHARED_LINKER_FLAGS));
QString(" CMAKE_DEFINITIONS: %1").arg(CMAKE_DEFINITIONS));
metadata.append(
QString(" CMAKE_INSTALL_PREFIX: %1").arg(CMAKE_INSTALL_PREFIX));
metadata.append(QString(" CMAKE_MODULE_LINKER_FLAGS: %1")
.arg(CMAKE_MODULE_LINKER_FLAGS));
metadata.append(QString(" CMAKE_SHARED_LINKER_FLAGS: %1")
.arg(CMAKE_SHARED_LINKER_FLAGS));
// components // components
metadata.append(QString("Components data:")); metadata.append("Components data:");
metadata.append(QString(" BUILD_PLASMOIDS: %1").arg(BUILD_PLASMOIDS)); metadata.append(QString(" BUILD_PLASMOIDS: %1").arg(BUILD_PLASMOIDS));
metadata.append( metadata.append(QString(" BUILD_DEB_PACKAGE: %1").arg(BUILD_DEB_PACKAGE));
QString(" BUILD_DEB_PACKAGE: %1").arg(BUILD_DEB_PACKAGE)); metadata.append(QString(" BUILD_RPM_PACKAGE: %1").arg(BUILD_RPM_PACKAGE));
metadata.append( metadata.append(QString(" CLANGFORMAT_EXECUTABLE: %1").arg(CLANGFORMAT_EXECUTABLE));
QString(" BUILD_RPM_PACKAGE: %1").arg(BUILD_RPM_PACKAGE));
metadata.append(
QString(" CLANGFORMAT_EXECUTABLE: %1").arg(CLANGFORMAT_EXECUTABLE));
metadata.append(QString(" COVERITY_COMMENT: %1").arg(COVERITY_COMMENT)); metadata.append(QString(" COVERITY_COMMENT: %1").arg(COVERITY_COMMENT));
metadata.append( metadata.append(QString(" COVERITY_DIRECTORY: %1").arg(COVERITY_DIRECTORY));
QString(" COVERITY_DIRECTORY: %1").arg(COVERITY_DIRECTORY));
metadata.append(QString(" COVERITY_EMAIL: %1").arg(COVERITY_EMAIL)); metadata.append(QString(" COVERITY_EMAIL: %1").arg(COVERITY_EMAIL));
metadata.append( metadata.append(QString(" COVERITY_EXECUTABLE: %1").arg(COVERITY_EXECUTABLE));
QString(" COVERITY_EXECUTABLE: %1").arg(COVERITY_EXECUTABLE));
metadata.append(QString(" COVERITY_URL: %1").arg(COVERITY_URL)); metadata.append(QString(" COVERITY_URL: %1").arg(COVERITY_URL));
metadata.append( metadata.append(QString(" CPPCHECK_EXECUTABLE: %1").arg(CPPCHECK_EXECUTABLE));
QString(" CPPCHECK_EXECUTABLE: %1").arg(CPPCHECK_EXECUTABLE));
// additional functions // additional functions
metadata.append(QString(" PROP_FUTURE: %1").arg(PROP_FUTURE)); metadata.append(QString(" PROP_FUTURE: %1").arg(PROP_FUTURE));
metadata.append(QString(" PROP_LOAD: %1").arg(PROP_LOAD)); metadata.append(QString(" PROP_LOAD: %1").arg(PROP_LOAD));

View File

@ -23,21 +23,25 @@
#include "version.h" #include "version.h"
#ifndef LOG_FORMAT namespace AWDebug
#define LOG_FORMAT \ {
"[%{time process}][%{if-debug}DD%{endif}%{if-info}II%{endif}%{if-" \ const char LOG_FORMAT[] = "[%{time "
"warning}WW%{endif}%{if-critical}CC%{endif}%{if-fatal}FF%{endif}][%{" \ "process}][%{if-debug}DD%{endif}%{if-info}II%{endif}%"
"category}][%{function}] %{message}" "{if-warning}WW%{endif}%{if-critical}CC%{endif}%{if-"
#endif /* LOG_FORMAT */ "fatal}FF%{endif}][%{category}][%{function}] "
"%{message}";
QString getAboutText(const QString &_type);
QStringList getBuildData();
} // namespace AWDebug
Q_DECLARE_LOGGING_CATEGORY(LOG_AW) Q_DECLARE_LOGGING_CATEGORY(LOG_AW)
Q_DECLARE_LOGGING_CATEGORY(LOG_DBUS)
Q_DECLARE_LOGGING_CATEGORY(LOG_DP) Q_DECLARE_LOGGING_CATEGORY(LOG_DP)
Q_DECLARE_LOGGING_CATEGORY(LOG_ESM) Q_DECLARE_LOGGING_CATEGORY(LOG_ESM)
Q_DECLARE_LOGGING_CATEGORY(LOG_ESS) Q_DECLARE_LOGGING_CATEGORY(LOG_ESS)
Q_DECLARE_LOGGING_CATEGORY(LOG_LIB) Q_DECLARE_LOGGING_CATEGORY(LOG_LIB)
const QStringList getBuildData();
#endif /* AWDEBUG_H */ #endif /* AWDEBUG_H */

View File

@ -1,7 +1,7 @@
set(SUBPROJECT plasma_applet_awesome-widget) set(SUBPROJECT plasma_applet_awesome-widget)
message(STATUS "Subproject ${SUBPROJECT}") message(STATUS "Subproject ${SUBPROJECT}")
configure_file(metadata.desktop ${CMAKE_CURRENT_SOURCE_DIR}/package/metadata.desktop) configure_file(metadata.json ${CMAKE_CURRENT_SOURCE_DIR}/package/metadata.json)
add_subdirectory(plugin) add_subdirectory(plugin)
plasma_install_package(package org.kde.plasma.awesomewidget) plasma_install_package(package org.kde.plasma.awesomewidget)

View File

@ -1,28 +0,0 @@
[Desktop Entry]
Encoding=UTF-8
Name=Awesome Widget
Comment=A minimalistic Plasmoid
Comment[en]=A minimalistic Plasmoid
Comment[es]=Un plasmoide minimalista
Comment[es]=Un script Plasmoïde minimaliste
Comment[pt_BR]=Um script Plasmoid
Comment[ru]=Минималистичный плазмоид
Comment[uk]=Мінімалістичний плазмоїд
X-KDE-ServiceTypes=Plasma/Applet
Type=Service
Icon=utilities-system-monitor
X-KDE-ServiceTypes=Plasma/Applet
X-Plasma-API=declarativeappletscript
X-Plasma-MainScript=ui/main.qml
X-Plasma-RemoteLocation=
X-KDE-PluginInfo-Author=Evgeniy Alekseev aka arcanis
X-KDE-PluginInfo-Email=esalexeev@gmail.com
X-KDE-PluginInfo-Name=org.kde.plasma.awesomewidget
X-KDE-PluginInfo-Version=@PROJECT_VERSION@
X-KDE-PluginInfo-Website=https://arcanis.me/projects/awesome-widgets/
X-KDE-PluginInfo-Category=System Information
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPLv3
X-KDE-PluginInfo-EnabledByDefault=true

View File

@ -0,0 +1,26 @@
{
"KPackageStructure": "Plasma/Applet",
"KPlugin": {
"Authors": [
{
"Email": "esalexeev@gmail.com",
"Name": "Evgeniy Alekseev aka arcanis"
}
],
"Category": "System Information",
"Description": "A minimalistic Plasmoid",
"Description[en]": "A minimalistic Plasmoid",
"Description[es]": "Un script Plasmoïde minimaliste",
"Description[pt_BR]": "Um script Plasmoid",
"Description[ru]": "Минималистичный плазмоид",
"Description[uk]": "Мінімалістичний плазмоїд",
"EnabledByDefault": true,
"Icon": "utilities-system-monitor",
"Id": "org.kde.plasma.awesomewidget",
"License": "GPLv3",
"Name": "Awesome Widget",
"Version": "@PROJECT_VERSION@",
"Website": "https://arcanis.me/projects/awesome-widgets/"
},
"X-Plasma-API-Minimum-Version": "6.0"
}

View File

@ -15,7 +15,7 @@
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/ ***************************************************************************/
import QtQuick 2.0 import QtQuick 2.15
import org.kde.plasma.configuration 2.0 import org.kde.plasma.configuration 2.0

View File

@ -7,137 +7,152 @@
<group name="Widget"> <group name="Widget">
<!-- widget --> <!-- widget -->
<entry name="text" type="string"> <entry name="text" type="String">
<default>[cpu: $cpu%] [mem: $mem%] [swap: $swap%] [$netdev: $down/$upKB/s]</default> <default>[cpu: $cpu%] [mem: $mem%] [swap: $swap%] [$netdev: $down/$upKB/s]</default>
</entry> </entry>
</group> </group>
<group name="Advanced"> <group name="Advanced">
<!-- advanced --> <!-- advanced -->
<entry name="background" type="bool"> <entry name="background" type="Bool">
<default>true</default> <default>true</default>
</entry> </entry>
<entry name="translateStrings" type="bool"> <entry name="translateStrings" type="Bool">
<default>true</default> <default>true</default>
</entry> </entry>
<entry name="wrapNewLines" type="bool"> <entry name="wrapNewLines" type="Bool">
<default>false</default> <default>false</default>
</entry> </entry>
<entry name="wrapText" type="bool"> <entry name="wrapText" type="Bool">
<default>false</default> <default>false</default>
</entry> </entry>
<entry name="notify" type="bool"> <entry name="notify" type="Bool">
<default>true</default> <default>true</default>
</entry> </entry>
<entry name="checkUpdates" type="bool"> <entry name="checkUpdates" type="Bool">
<default>true</default> <default>true</default>
</entry> </entry>
<entry name="optimize" type="bool"> <entry name="optimize" type="Bool">
<default>true</default> <default>true</default>
</entry> </entry>
<entry name="height" type="int"> <entry name="height" type="Int">
<default>0</default> <default>0</default>
</entry> </entry>
<entry name="width" type="int"> <entry name="width" type="Int">
<default>0</default> <default>0</default>
</entry> </entry>
<entry name="interval" type="int"> <entry name="interval" type="Int">
<default>1000</default> <default>1000</default>
</entry> </entry>
<entry name="queueLimit" type="int"> <entry name="queueLimit" type="Int">
<default>0</default> <default>0</default>
</entry> </entry>
<entry name="tempUnits" type="string"> <entry name="tempUnits" type="String">
<default>Celsius</default> <default>Celsius</default>
</entry> </entry>
<entry name="customTime" type="string"> <entry name="customTime" type="String">
<default>$hh:$mm</default> <default>$hh:$mm</default>
</entry> </entry>
<entry name="customUptime" type="string"> <entry name="customUptime" type="String">
<default>$dd,$hh,$mm</default> <default>$dd,$hh,$mm</default>
</entry> </entry>
<entry name="acOnline" type="string"> <entry name="acOnline" type="String">
<default>(*)</default> <default>(*)</default>
</entry> </entry>
<entry name="acOffline" type="string"> <entry name="acOffline" type="String">
<default>( )</default> <default>( )</default>
</entry> </entry>
<entry name="telemetryCount" type="Int">
<default>100</default>
</entry>
<entry name="telemetryRemote" type="Bool">
<default>false</default>
</entry>
<entry name="telemetryId" type="String">
<default></default>
</entry>
</group> </group>
<group name="Tooltip"> <group name="Tooltip">
<entry name="tooltipNumber" type="int"> <entry name="tooltipNumber" type="Int">
<default>100</default> <default>100</default>
</entry> </entry>
<entry name="useTooltipBackground" type="bool"> <entry name="useTooltipBackground" type="Bool">
<default>true</default> <default>true</default>
</entry> </entry>
<entry name="tooltipBackground" type="string"> <entry name="tooltipBackground" type="String">
<default>#ffffff</default> <default>#ffffff</default>
</entry> </entry>
<entry name="cpuTooltip" type="bool"> <entry name="cpuTooltip" type="Bool">
<default>true</default> <default>true</default>
</entry> </entry>
<entry name="cpuTooltipColor" type="string"> <entry name="cpuTooltipColor" type="String">
<default>#ff0000</default> <default>#ff0000</default>
</entry> </entry>
<entry name="cpuclTooltip" type="bool"> <entry name="cpuclTooltip" type="Bool">
<default>true</default> <default>true</default>
</entry> </entry>
<entry name="cpuclTooltipColor" type="string"> <entry name="cpuclTooltipColor" type="String">
<default>#00ff00</default> <default>#00ff00</default>
</entry> </entry>
<entry name="memTooltip" type="bool"> <entry name="memTooltip" type="Bool">
<default>true</default> <default>true</default>
</entry> </entry>
<entry name="memTooltipColor" type="string"> <entry name="memTooltipColor" type="String">
<default>#0000ff</default> <default>#0000ff</default>
</entry> </entry>
<entry name="swapTooltip" type="bool"> <entry name="swapTooltip" type="Bool">
<default>true</default> <default>true</default>
</entry> </entry>
<entry name="swapTooltipColor" type="string"> <entry name="swapTooltipColor" type="String">
<default>#ffff00</default> <default>#ffff00</default>
</entry> </entry>
<entry name="downkbTooltip" type="bool"> <entry name="downkbTooltip" type="Bool">
<default>true</default> <default>true</default>
</entry> </entry>
<entry name="downkbTooltipColor" type="string"> <entry name="downkbTooltipColor" type="String">
<default>#00ffff</default> <default>#00ffff</default>
</entry> </entry>
<entry name="upkbTooltipColor" type="string"> <entry name="upkbTooltipColor" type="String">
<default>#ff00ff</default> <default>#ff00ff</default>
</entry> </entry>
<entry name="batTooltip" type="bool"> <entry name="batTooltip" type="Bool">
<default>true</default> <default>true</default>
</entry> </entry>
<entry name="batTooltipColor" type="string"> <entry name="batTooltipColor" type="String">
<default>#008800</default> <default>#008800</default>
</entry> </entry>
<entry name="batInTooltipColor" type="string"> <entry name="batInTooltipColor" type="String">
<default>#880000</default> <default>#880000</default>
</entry> </entry>
</group> </group>
<group name="Appearance"> <group name="Appearance">
<!-- appearance --> <!-- appearance -->
<entry name="textAlign" type="string"> <entry name="textAlign" type="String">
<default>center</default> <default>center</default>
</entry> </entry>
<entry name="fontFamily" type="string"> <entry name="fontFamily" type="String">
<default>Terminus</default> <default>Terminus</default>
</entry> </entry>
<entry name="fontSize" type="int"> <entry name="fontSize" type="Int">
<default>12</default> <default>12</default>
</entry> </entry>
<entry name="fontColor" type="string"> <entry name="fontColor" type="String">
<default>#000000</default> <default>#000000</default>
</entry> </entry>
<entry name="fontWeight" type="string"> <entry name="fontWeight" type="String">
<default>normal</default> <default>normal</default>
</entry> </entry>
<entry name="fontStyle" type="string"> <entry name="fontStyle" type="String">
<default>normal</default> <default>normal</default>
</entry> </entry>
<entry name="textStyle" type="String">
<default>normal</default>
</entry>
<entry name="textStyleColor" type="String">
<default>#000000</default>
</entry>
</group> </group>
</kcfg> </kcfg>

View File

@ -15,113 +15,27 @@
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/ ***************************************************************************/
import QtQuick 2.0 import QtQuick 2.15
import QtQuick.Controls 1.3 as QtControls
import QtQuick.Layouts 1.0 as QtLayouts
import org.kde.plasma.private.awesomewidget 1.0 import org.kde.plasma.private.awesomewidget 1.0
Item { Item {
id: aboutPage id: aboutPage
// backend
AWActions { AWActions {
id: awActions id: awActions
} }
width: childrenRect.width width: childrenRect.width
height: childrenRect.height height: childrenRect.height
implicitWidth: pageColumn.implicitWidth
implicitHeight: pageColumn.implicitHeight
property bool debug: awActions.isDebugEnabled() property bool debug: awActions.isDebugEnabled()
AboutTab {
Column { textProvider: awActions
id: pageColumn
anchors.fill: parent
QtControls.TabView {
height: parent.height
width: parent.width
QtControls.Tab {
anchors.margins: 10.0
title: i18n("About")
QtLayouts.ColumnLayout {
QtControls.Label {
QtLayouts.Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
text: awActions.getAboutText("header")
}
QtControls.Label {
QtLayouts.Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
text: awActions.getAboutText("version")
}
QtControls.Label {
QtLayouts.Layout.fillWidth: true
horizontalAlignment: Text.AlignJustify
text: awActions.getAboutText("description")
}
QtControls.Label {
QtLayouts.Layout.fillWidth: true
horizontalAlignment: Text.AlignLeft
textFormat: Text.RichText
text: awActions.getAboutText("links")
onLinkActivated: Qt.openUrlExternally(link);
}
QtControls.Label {
QtLayouts.Layout.fillHeight: true
QtLayouts.Layout.fillWidth: true
font.capitalization: Font.SmallCaps
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignBottom
textFormat: Text.RichText
text: awActions.getAboutText("copy")
}
}
}
QtControls.Tab {
anchors.margins: 10.0
title: i18n("Acknowledgment")
QtLayouts.ColumnLayout {
QtControls.Label {
QtLayouts.Layout.fillWidth: true
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignJustify
text: awActions.getAboutText("translators")
}
QtControls.Label {
QtLayouts.Layout.fillWidth: true
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignJustify
textFormat: Text.RichText
text: awActions.getAboutText("3rdparty")
onLinkActivated: Qt.openUrlExternally(link);
}
QtControls.Label {
QtLayouts.Layout.fillHeight: true
QtLayouts.Layout.fillWidth: true
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignJustify
verticalAlignment: Text.AlignTop
textFormat: Text.RichText
text: awActions.getAboutText("thanks")
onLinkActivated: Qt.openUrlExternally(link);
}
}
}
}
} }
Component.onCompleted: { Component.onCompleted: {
if (debug) console.debug() if (debug) console.debug()
} }

View File

@ -15,9 +15,8 @@
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/ ***************************************************************************/
import QtQuick 2.0 import QtQuick 2.15
import QtQuick.Controls 1.3 as QtControls import QtQuick.Controls
import QtQuick.Dialogs 1.2 as QtDialogs
import org.kde.plasma.private.awesomewidget 1.0 import org.kde.plasma.private.awesomewidget 1.0
@ -28,9 +27,6 @@ Item {
AWActions { AWActions {
id: awActions id: awActions
} }
AWConfigHelper {
id: awConfig
}
width: childrenRect.width width: childrenRect.width
height: childrenRect.height height: childrenRect.height
@ -50,420 +46,206 @@ Item {
property alias cfg_width: widgetWidth.value property alias cfg_width: widgetWidth.value
property alias cfg_interval: update.value property alias cfg_interval: update.value
property alias cfg_queueLimit: queueLimit.value property alias cfg_queueLimit: queueLimit.value
property string cfg_tempUnits: tempUnits.currentText property string cfg_tempUnits: tempUnits.value
property alias cfg_customTime: customTime.text property alias cfg_customTime: customTime.value
property alias cfg_customUptime: customUptime.text property alias cfg_customUptime: customUptime.value
property alias cfg_acOnline: acOnline.text property alias cfg_acOnline: acOnline.value
property alias cfg_acOffline: acOffline.text property alias cfg_acOffline: acOffline.value
property alias cfg_telemetryCount: telemetryCount.value
property alias cfg_telemetryRemote: telemetryRemote.checked
property alias cfg_telemetryId: telemetryId.value
Column { Column {
id: pageColumn id: pageColumn
anchors.fill: parent anchors.fill: parent
Row {
height: implicitHeight CheckBoxSelector {
width: parent.width id: background
QtControls.Label { text: i18n("Enable background")
height: parent.heigth
width: parent.width * 2 / 5
}
QtControls.CheckBox {
id: background
width: parent.width * 3 / 5
text: i18n("Enable background")
}
} }
Row { CheckBoxSelector {
height: implicitHeight id: translate
width: parent.width text: i18n("Translate strings")
QtControls.Label {
height: parent.heigth
width: parent.width * 2 / 5
}
QtControls.CheckBox {
id: translate
width: parent.width * 3 / 5
text: i18n("Translate strings")
}
} }
Row { CheckBoxSelector {
height: implicitHeight id: wrapNewLines
width: parent.width text: i18n("Wrap new lines")
QtControls.Label {
height: parent.heigth
width: parent.width * 2 / 5
}
QtControls.CheckBox {
id: wrapNewLines
width: parent.width * 3 / 5
text: i18n("Wrap new lines")
}
} }
Row { CheckBoxSelector {
height: implicitHeight id: wordWrap
width: parent.width text: i18n("Enable word wrap")
QtControls.Label {
height: parent.heigth
width: parent.width * 2 / 5
}
QtControls.CheckBox {
id: wordWrap
width: parent.width * 3 / 5
text: i18n("Enable word wrap")
}
} }
Row { CheckBoxSelector {
height: implicitHeight id: notify
width: parent.width text: i18n("Enable notifications")
QtControls.Label {
height: parent.heigth
width: parent.width * 2 / 5
}
QtControls.CheckBox {
id: notify
width: parent.width * 3 / 5
text: i18n("Enable notifications")
}
} }
Row { CheckBoxSelector {
height: implicitHeight id: updates
width: parent.width text: i18n("Check updates on startup")
QtControls.Label {
height: parent.heigth
width: parent.width * 2 / 5
}
QtControls.CheckBox {
id: updates
width: parent.width * 3 / 5
text: i18n("Check updates on startup")
}
} }
Row { CheckBoxSelector {
height: implicitHeight id: optimize
width: parent.width text: i18n("Optimize subscription")
QtControls.Label {
height: parent.heigth
width: parent.width * 2 / 5
}
QtControls.CheckBox {
id: optimize
width: parent.width * 3 / 5
text: i18n("Optimize subscription")
}
} }
Row { IntegerSelector {
height: implicitHeight id: widgetHeight
width: parent.width maximumValue: 4096
QtControls.Label { minimumValue: 0
height: parent.height stepSize: 50
width: parent.width * 2 / 5 text: i18n("Widget height, px")
horizontalAlignment: Text.AlignRight value: plasmoid.configuration.height
verticalAlignment: Text.AlignVCenter
text: i18n("Widget height, px")
}
QtControls.SpinBox {
id: widgetHeight
width: parent.width * 3 / 5
minimumValue: 0
maximumValue: 4096
stepSize: 50
value: plasmoid.configuration.height
}
} }
Row { IntegerSelector {
height: implicitHeight id: widgetWidth
width: parent.width maximumValue: 4096
QtControls.Label { minimumValue: 0
height: parent.height stepSize: 50
width: parent.width * 2 / 5 text: i18n("Widget width, px")
horizontalAlignment: Text.AlignRight value: plasmoid.configuration.width
verticalAlignment: Text.AlignVCenter
text: i18n("Widget width, px")
}
QtControls.SpinBox {
id: widgetWidth
width: parent.width * 3 / 5
minimumValue: 0
maximumValue: 4096
stepSize: 50
value: plasmoid.configuration.width
}
} }
Row { IntegerSelector {
height: implicitHeight id: update
width: parent.width maximumValue: 10000
QtControls.Label { minimumValue: 1000
height: parent.height stepSize: 500
width: parent.width * 2 / 5 text: i18n("Time interval")
horizontalAlignment: Text.AlignRight value: plasmoid.configuration.interval
verticalAlignment: Text.AlignVCenter
text: i18n("Time interval")
}
QtControls.SpinBox {
id: update
width: parent.width * 3 / 5
minimumValue: 1000
maximumValue: 10000
stepSize: 500
value: plasmoid.configuration.interval
}
} }
Row { IntegerSelector {
height: implicitHeight id: queueLimit
width: parent.width maximumValue: 99
QtControls.Label { minimumValue: 0
height: parent.height stepSize: 1
width: parent.width * 2 / 5 text: i18n("Messages queue limit")
horizontalAlignment: Text.AlignRight value: plasmoid.configuration.queueLimit
verticalAlignment: Text.AlignVCenter
text: i18n("Messages queue limit")
}
QtControls.SpinBox {
id: queueLimit
width: parent.width * 3 / 5
minimumValue: 0
maximumValue: 99
stepSize: 1
value: plasmoid.configuration.queueLimit
}
} }
Row { ComboBoxSelector {
height: implicitHeight id: tempUnits
model: [
{
'label': i18n("Celsius"),
'name': "Celsius"
},
{
'label': i18n("Fahrenheit"),
'name': "Fahrenheit"
},
{
'label': i18n("Kelvin"),
'name': "Kelvin"
},
{
'label': i18n("Reaumur"),
'name': "Reaumur"
},
{
'label': i18n("cm^-1"),
'name': "cm^-1"
},
{
'label': i18n("kJ/mol"),
'name': "kJ/mol"
},
{
'label': i18n("kcal/mol"),
'name': "kcal/mol"
}
]
text: i18n("Temperature units")
value: plasmoid.configuration.tempUnits
onValueEdited: newValue => cfg_tempUnits = newValue
}
LineSelector {
id: customTime
text: i18n("Custom time format")
value: plasmoid.configuration.customTime
}
LineSelector {
id: customUptime
text: i18n("Custom uptime format")
value: plasmoid.configuration.customUptime
}
LineSelector {
id: acOnline
text: i18n("AC online tag")
value: plasmoid.configuration.acOnline
}
LineSelector {
id: acOffline
text: i18n("AC offline tag")
value: plasmoid.configuration.acOffline
}
GroupBox {
width: parent.width width: parent.width
QtControls.Label { title: i18n("Actions")
height: parent.height
width: parent.width * 2 / 5 Column {
horizontalAlignment: Text.AlignRight width: parent.width
verticalAlignment: Text.AlignVCenter ButtonSelector {
text: i18n("Temperature units") value: i18n("Drop key cache")
} onButtonActivated: awActions.dropCache()
QtControls.ComboBox { }
id: tempUnits ButtonSelector {
width: parent.width * 3 / 5 ExportDialog {
textRole: "label" id: saveConfigAs
model: [ configuration: plasmoid.configuration
{
'label': i18n("Celsius"),
'name': "Celsius"
},
{
'label': i18n("Fahrenheit"),
'name': "Fahrenheit"
},
{
'label': i18n("Kelvin"),
'name': "Kelvin"
},
{
'label': i18n("Reaumur"),
'name': "Reaumur"
},
{
'label': i18n("cm^-1"),
'name': "cm^-1"
},
{
'label': i18n("kJ/mol"),
'name': "kJ/mol"
},
{
'label': i18n("kcal/mol"),
'name': "kcal/mol"
} }
] value: i18n("Export configuration")
onCurrentIndexChanged: cfg_tempUnits = model[currentIndex]["name"] onButtonActivated: saveConfigAs.open()
Component.onCompleted: { }
if (debug) console.debug() ButtonSelector {
for (var i = 0; i < model.length; i++) { ImportDialog {
if (model[i]["name"] == plasmoid.configuration.tempUnits) { id: loadConfigFrom
if (debug) console.info("Found", model[i]["name"], "on", i) onConfigurationReceived: {
tempUnits.currentIndex = i; for (var key in configuration)
plasmoid.configuration[key] = configuration[key]
} }
} }
value: i18n("Import configuration")
onButtonActivated: loadConfigFrom.open()
} }
} }
} }
Row { GroupBox {
height: implicitHeight
width: parent.width width: parent.width
QtControls.Label { title: i18n("Telemetry")
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Custom time format")
}
QtControls.TextField {
id: customTime
width: parent.width * 3 / 5
text: plasmoid.configuration.customTime
}
}
Row { Column {
height: implicitHeight width: parent.width
width: parent.width CheckBoxSelector {
QtControls.Label { id: telemetryRemote
height: parent.height text: i18n("Enable remote telemetry")
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Custom uptime format")
}
QtControls.TextField {
id: customUptime
width: parent.width * 3 / 5
text: plasmoid.configuration.customUptime
}
}
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("AC online tag")
}
QtControls.TextField {
id: acOnline
width: parent.width * 3 / 5
text: plasmoid.configuration.acOnline
}
}
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("AC offline tag")
}
QtControls.TextField {
id: acOffline
width: parent.width * 3 / 5
text: plasmoid.configuration.acOffline
}
}
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
}
QtControls.Button {
width: parent.width * 3 / 5
text: i18n("Drop key cache")
onClicked: awActions.dropCache()
}
}
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
}
QtControls.Button {
width: parent.width * 3 / 5
text: i18n("Export configuration")
onClicked: saveConfigAs.open()
}
QtDialogs.FileDialog {
id: saveConfigAs
selectExisting: false
title: i18n("Export")
folder: awConfig.configurationDirectory()
onAccepted: {
var status = awConfig.exportConfiguration(
plasmoid.configuration,
saveConfigAs.fileUrl.toString().replace("file://", ""))
if (status) {
messageDialog.title = i18n("Success")
messageDialog.text = i18n("Please note that binary files were not copied")
} else {
messageDialog.title = i18n("Ooops...")
messageDialog.text = i18n("Could not save configuration file")
}
messageDialog.open()
} }
} IntegerSelector {
id: telemetryCount
QtDialogs.MessageDialog { maximumValue: 10000
id: messageDialog minimumValue: 0
standardButtons: QtDialogs.StandardButton.Ok stepSize: 50
} text: i18n("History count")
} value: plasmoid.configuration.telemetryCount
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
}
QtControls.Button {
width: parent.width * 3 / 5
text: i18n("Import configuration")
onClicked: openConfig.open()
}
QtDialogs.FileDialog {
id: openConfig
title: i18n("Import")
folder: awConfig.configurationDirectory()
onAccepted: importSelection.open()
}
QtDialogs.Dialog {
id: importSelection
Column {
QtControls.CheckBox {
id: importPlasmoid
text: i18n("Import plasmoid settings")
}
QtControls.CheckBox {
id: importExtensions
text: i18n("Import extensions")
}
QtControls.CheckBox {
id: importAdds
text: i18n("Import additional files")
}
} }
LineSelector {
onAccepted: { id: telemetryId
if (debug) console.debug() text: i18n("Telemetry ID")
var importConfig = awConfig.importConfiguration( value: plasmoid.configuration.telemetryId
openConfig.fileUrl.toString().replace("file://", ""),
importPlasmoid.checked, importExtensions.checked,
importAdds.checked)
for (var key in importConfig)
plasmoid.configuration[key] = importConfig[key]
} }
} }
} }

View File

@ -15,12 +15,10 @@
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/ ***************************************************************************/
import QtQuick 2.0 import QtQuick 2.15
import QtQuick.Controls 1.3 as QtControls
import QtQuick.Controls.Styles 1.3 as QtStyles
import QtQuick.Dialogs 1.1 as QtDialogs
import org.kde.plasma.private.awesomewidget 1.0 import org.kde.plasma.private.awesomewidget 1.0
import "."
Item { Item {
@ -44,195 +42,68 @@ Item {
87: 5 87: 5
} }
property alias cfg_fontFamily: selectFont.text property alias cfg_fontFamily: font.value
property alias cfg_fontSize: fontSize.value property alias cfg_fontSize: fontSize.value
property string cfg_fontWeight: fontWeight.currentText property string cfg_fontWeight: fontWeight.value
property string cfg_fontStyle: fontStyle.currentText property string cfg_fontStyle: fontStyle.value
property alias cfg_fontColor: selectColor.text property alias cfg_fontColor: selectColor.value
property alias cfg_textStyleColor: selectStyleColor.value
property string cfg_textStyle: textStyle.value
Column { Column {
id: pageColumn id: pageColumn
anchors.fill: parent anchors.fill: parent
Row {
height: implicitHeight FontSelector {
width: parent.width id: font
QtControls.Label { text: i18n("Font")
height: parent.height value: plasmoid.configuration.fontFamily
width: parent.width / 3
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Font")
}
QtControls.Button {
id: selectFont
width: parent.width * 2 / 3
text: plasmoid.configuration.fontFamily
onClicked: {
if (debug) console.debug()
fontDialog.setFont()
fontDialog.visible = true
}
}
} }
Row { IntegerSelector {
height: implicitHeight id: fontSize
width: parent.width maximumValue: 32
QtControls.Label { minimumValue: 8
height: parent.height stepSize: 1
width: parent.width / 3 text: i18n("Font size")
horizontalAlignment: Text.AlignRight value: plasmoid.configuration.fontSize
verticalAlignment: Text.AlignVCenter
text: i18n("Font size")
}
QtControls.SpinBox {
id: fontSize
width: parent.width * 2 / 3
minimumValue: 8
maximumValue: 32
stepSize: 1
value: plasmoid.configuration.fontSize
}
} }
Row { ComboBoxSelector {
height: implicitHeight id: fontWeight
width: parent.width model: General.fontWeightModel
QtControls.Label { text: i18n("Font weight")
height: parent.height value: plasmoid.configuration.fontWeight
width: parent.width / 3 onValueEdited: newValue => cfg_fontWeight = newValue
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Font weight")
}
QtControls.ComboBox {
id: fontWeight
width: parent.width * 2 / 3
textRole: "label"
model: [
{
'label': i18n("light"),
'name': "light"
},
{
'label': i18n("normal"),
'name': "normal"
},
{
'label': i18n("demi bold"),
'name': "demibold"
},
{
'label': i18n("bold"),
'name': "bold"
},
{
'label': i18n("black"),
'name': "black"
}
]
onCurrentIndexChanged: cfg_fontWeight = model[currentIndex]["name"]
Component.onCompleted: {
if (debug) console.debug()
for (var i = 0; i < model.length; i++) {
if (model[i]["name"] == plasmoid.configuration.fontWeight) {
if (debug) console.info("Found", model[i]["name"], "on", i)
fontWeight.currentIndex = i;
}
}
}
}
} }
Row { ComboBoxSelector {
height: implicitHeight id: fontStyle
width: parent.width model: General.fontStyleModel
QtControls.Label { text: i18n("Font style")
height: parent.height value: plasmoid.configuration.fontStyle
width: parent.width / 3 onValueEdited: newValue => cfg_fontStyle = newValue
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Font style")
}
QtControls.ComboBox {
id: fontStyle
width: parent.width * 2 / 3
textRole: "label"
model: [
{
'label': i18n("normal"),
'name': "normal"
},
{
'label': i18n("italic"),
'name': "italic"
}
]
onCurrentIndexChanged: cfg_fontStyle = model[currentIndex]["name"]
Component.onCompleted: {
if (debug) console.debug()
for (var i = 0; i < model.length; i++) {
if (model[i]["name"] == plasmoid.configuration.fontStyle) {
if (debug) console.info("Found", model[i]["name"], "on", i)
fontStyle.currentIndex = i;
}
}
}
}
} }
Row { ColorSelector {
height: implicitHeight id: selectColor
width: parent.width text: i18n("Font color")
QtControls.Label { value: plasmoid.configuration.fontColor
height: parent.height
width: parent.width / 3
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Font color")
}
QtControls.Button {
id: selectColor
width: parent.width * 2 / 3
style: QtStyles.ButtonStyle {
background: Rectangle {
color: plasmoid.configuration.fontColor
}
}
text: plasmoid.configuration.fontColor
onClicked: colorDialog.visible = true
}
} }
}
QtDialogs.ColorDialog { ComboBoxSelector {
id: colorDialog id: textStyle
title: i18n("Select a color") model: General.textStyleModel
color: selectColor.text text: i18n("Style")
onAccepted: selectColor.text = colorDialog.color value: plasmoid.configuration.textStyle
} onValueEdited: newValue => cfg_textStyle = newValue
QtDialogs.FontDialog {
id: fontDialog
title: i18n("Select a font")
signal setFont
onAccepted: {
if (debug) console.debug()
selectFont.text = fontDialog.font.family
fontSize.value = fontDialog.font.pointSize
fontStyle.currentIndex = fontDialog.font.italic ? 1 : 0
fontWeight.currentIndex = weight[fontDialog.font.weight]
} }
onSetFont: {
if (debug) console.debug() ColorSelector {
fontDialog.font = Qt.font({ id: selectStyleColor
family: selectFont.text, text: i18n("Style color")
pointSize: fontSize.value > 0 ? fontSize.value : 12, value: plasmoid.configuration.textStyleColor
italic: fontStyle.currentIndex == 1,
weight: Font.Normal,
})
} }
} }

View File

@ -15,9 +15,8 @@
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/ ***************************************************************************/
import QtQuick 2.0 import QtQuick 2.15
import QtQuick.Controls 1.3 as QtControls import QtQuick.Controls
import QtQuick.Dialogs 1.1 as QtDialogs
import org.kde.plasma.private.awesomewidget 1.0 import org.kde.plasma.private.awesomewidget 1.0
@ -48,286 +47,196 @@ Item {
Column { Column {
id: pageColumn id: pageColumn
anchors.fill: parent anchors.fill: parent
QtControls.GroupBox { GroupBox {
height: implicitHeight height: implicitHeight
width: parent.width width: parent.width
title: i18n("ACPI") title: i18n("ACPI")
Row { LineSelector {
height: implicitHeight text: i18n("ACPI path")
width: parent.width value: cfg_dataengine["ACPIPATH"]
QtControls.Label { onValueEdited: newValue => cfg_dataengine["ACPIPATH"] = newValue
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("ACPI path")
}
QtControls.TextField {
width: parent.width * 3 / 5
text: cfg_dataengine["ACPIPATH"]
onEditingFinished: cfg_dataengine["ACPIPATH"] = text
}
} }
} }
QtControls.GroupBox { GroupBox {
height: implicitHeight height: implicitHeight
width: parent.width width: parent.width
title: i18n("GPU") title: i18n("GPU")
Row { ComboBoxSelector {
height: implicitHeight model: [
width: parent.width {
QtControls.Label { 'label': "auto",
height: parent.height 'name': "auto"
width: parent.width * 2 / 5 },
horizontalAlignment: Text.AlignRight {
verticalAlignment: Text.AlignVCenter 'label': "disable",
text: i18n("GPU device") 'name': "disable"
} },
QtControls.ComboBox { {
id: gpuDev 'label': "ati",
width: parent.width * 3 / 5 'name': "ati"
model: ["auto", "disable", "ati", "nvidia"] },
Component.onCompleted: { {
if (debug) console.debug() 'label': "nvidia",
for (var i=0; i<model.length; i++) { 'name': "nvidia"
if (model[i] == cfg_dataengine["GPUDEV"]) {
if (debug) console.info("Found", model[i], "on", i)
currentIndex = i;
}
}
} }
} ]
text: i18n("GPU device")
value: cfg_dataengine["GPUDEV"]
onValueEdited: newValue => cfg_dataengine["GPUDEV"] = newValue
} }
} }
QtControls.GroupBox { GroupBox {
height: implicitHeight height: implicitHeight
width: parent.width width: parent.width
title: i18n("HDD temperature") title: i18n("HDD temperature")
Column { Column {
height: implicitHeight height: implicitHeight
width: parent.width width: parent.width
Row { ComboBoxSelector {
height: implicitHeight id: hdd
width: parent.width text: i18n("HDD")
QtControls.Label { value: cfg_dataengine["HDDDEV"]
height: parent.height onValueEdited: newValue => cfg_dataengine["HDDDEV"] = newValue
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("HDD")
}
QtControls.ComboBox {
id: hdd
width: parent.width * 3 / 5
}
} }
Row { LineSelector {
height: implicitHeight text: i18n("hddtemp cmd")
width: parent.width value: cfg_dataengine["HDDTEMPCMD"]
QtControls.Label { onValueEdited: newValue => cfg_dataengine["HDDTEMPCMD"] = newValue
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("hddtemp cmd")
}
QtControls.TextField {
width: parent.width * 3 / 5
text: cfg_dataengine["HDDTEMPCMD"]
onEditingFinished: cfg_dataengine["HDDTEMPCMD"] = text
}
} }
} }
} }
QtControls.GroupBox { GroupBox {
height: implicitHeight height: implicitHeight
width: parent.width width: parent.width
title: i18n("Player") title: i18n("Player")
Column { Column {
height: implicitHeight height: implicitHeight
width: parent.width width: parent.width
Row { IntegerSelector {
height: implicitHeight maximumValue: 100
width: parent.width minimumValue: 1
QtControls.Label { stepSize: 1
height: parent.height text: i18n("Player data symbols")
width: parent.width * 2 / 5 value: cfg_dataengine["PLAYERSYMBOLS"]
horizontalAlignment: Text.AlignRight onValueEdited: newValue => cfg_dataengine["PLAYERSYMBOLS"] = newValue
verticalAlignment: Text.AlignVCenter
text: i18n("Player data symbols")
}
QtControls.SpinBox {
width: parent.width * 3 / 5
minimumValue: 1
maximumValue: 100
stepSize: 1
value: cfg_dataengine["PLAYERSYMBOLS"]
onEditingFinished: cfg_dataengine["PLAYERSYMBOLS"] = value
}
} }
Row { ComboBoxSelector {
height: implicitHeight model: [
width: parent.width {
QtControls.Label { 'label': "disable",
height: parent.height 'name': "disable"
width: parent.width * 2 / 5 },
horizontalAlignment: Text.AlignRight {
verticalAlignment: Text.AlignVCenter 'label': "mpris",
text: i18n("Music player") 'name': "mpris"
} },
QtControls.ComboBox { {
id: player 'label': "mpd",
width: parent.width * 3 / 5 'name': "mpd"
model: ["disable", "mpris", "mpd"]
Component.onCompleted: {
if (debug) console.debug()
for (var i=0; i<model.length; i++) {
if (model[i] == cfg_dataengine["PLAYER"]) {
if (debug) console.info("Found", model[i], "on", i)
player.currentIndex = i;
}
}
} }
} ]
text: i18n("Music player")
value: cfg_dataengine["PLAYER"]
onValueEdited: newValue => cfg_dataengine["PLAYER"] = newValue
} }
Row { ComboBoxSelector {
height: implicitHeight id: mpris
width: parent.width editable: true
QtControls.Label { model: [
height: parent.height {
width: parent.width * 2 / 5 'label': 'auto',
horizontalAlignment: Text.AlignRight 'name': 'auto'
verticalAlignment: Text.AlignVCenter },
text: i18n("MPRIS player name") {
} 'label': 'amarok',
QtControls.ComboBox { 'name': 'amarok'
id: mpris },
width: parent.width * 3 / 5 {
editable: true 'label': 'audacious',
model: ["auto", "amarok", "audacious", "clementine", "deadbeef", 'name': 'audacious'
"vlc", "qmmp", "xmms2", cfg_dataengine["MPRIS"]] },
currentIndex: model.length - 1 {
} 'label': 'clementine',
'name': 'clementine'
},
{
'label': 'DeaDBeeF',
'name': 'DeaDBeeF'
},
{
'label': 'vlc',
'name': 'vlc'
},
{
'label': 'qmmp',
'name': 'qmmp'
},
{
'label': 'xmms2',
'name': 'xmms2'
},
{
'label': cfg_dataengine["MPRIS"],
'name': cfg_dataengine["MPRIS"]
}
]
text: i18n("MPRIS player name")
currentIndex: model.length - 1
} }
Row { LineSelector {
height: implicitHeight text: i18n("MPD address")
width: parent.width value: cfg_dataengine["MPDADDRESS"]
QtControls.Label { onValueEdited: newValue => cfg_dataengine["MPDADDRESS"] = newValue
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("MPD address")
}
QtControls.TextField {
width: parent.width * 3 / 5
text: cfg_dataengine["MPDADDRESS"]
onEditingFinished: cfg_dataengine["MPDADDRESS"] = text
}
} }
Row { IntegerSelector {
height: implicitHeight maximumValue: 65535
width: parent.width minimumValue: 1000
QtControls.Label { stepSize: 1
height: parent.height text: i18n("MPD port")
width: parent.width * 2 / 5 value: cfg_dataengine["MPDPORT"]
horizontalAlignment: Text.AlignRight onValueEdited: newValue => cfg_dataengine["MPDPORT"] = newValue
verticalAlignment: Text.AlignVCenter
text: i18n("MPD port")
}
QtControls.SpinBox {
width: parent.width * 3 / 5
minimumValue: 1000
maximumValue: 65535
stepSize: 1
value: cfg_dataengine["MPDPORT"]
onEditingFinished: cfg_dataengine["MPDPORT"] = value
}
} }
} }
} }
QtControls.GroupBox { GroupBox {
height: implicitHeight height: implicitHeight
width: parent.width width: parent.width
title: i18n("Extensions") title: i18n("Extensions")
Column { Column {
height: implicitHeight height: implicitHeight
width: parent.width width: parent.width
Row { ButtonSelector {
height: implicitHeight value: i18n("Custom scripts")
width: parent.width onButtonActivated: awKeys.editItem("extscript")
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Custom scripts")
}
QtControls.Button {
width: parent.width * 3 / 5
text: i18n("Edit scripts")
onClicked: awKeys.editItem("extscript")
}
} }
Row { ButtonSelector {
height: implicitHeight value: i18n("Network requests")
width: parent.width onButtonActivated: awKeys.editItem("extnetworkrequest")
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Quotes monitor")
}
QtControls.Button {
width: parent.width * 3 / 5
text: i18n("Edit tickers")
onClicked: awKeys.editItem("extquotes")
}
} }
Row { ButtonSelector {
height: implicitHeight value: i18n("Package manager")
width: parent.width onButtonActivated: awKeys.editItem("extupgrade")
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Package manager")
}
QtControls.Button {
width: parent.width * 3 / 5
text: i18n("Edit command")
onClicked: awKeys.editItem("extupgrade")
}
} }
Row { ButtonSelector {
height: implicitHeight value: i18n("Quotes monitor")
width: parent.width onButtonActivated: awKeys.editItem("extquotes")
QtControls.Label { }
height: parent.height
width: parent.width * 2 / 5 ButtonSelector {
horizontalAlignment: Text.AlignRight value: i18n("Weather")
verticalAlignment: Text.AlignVCenter onButtonActivated: awKeys.editItem("extweather")
text: i18n("Weather")
}
QtControls.Button {
width: parent.width * 3 / 5
text: i18n("Edit weather")
onClicked: awKeys.editItem("extweather")
}
} }
} }
} }
@ -342,21 +251,13 @@ Item {
// update hdd model // update hdd model
hdd.model = awKeys.getHddDevices() hdd.model = awKeys.getHddDevices()
for (var i=0; i<hdd.model.length; i++) { hdd.onCompleted
if (hdd.model[i] == cfg_dataengine["HDDDEV"]) {
if (debug) console.info("Found", hdd.model[i], "on", i)
hdd.currentIndex = i;
}
}
} }
Component.onDestruction: { Component.onDestruction: {
if (debug) console.debug() if (debug) console.debug()
cfg_dataengine["GPUDEV"] = gpuDev.currentText cfg_dataengine["MPRIS"] = mpris.editText
cfg_dataengine["HDDDEV"] = hdd.currentText
cfg_dataengine["PLAYER"] = player.currentText
cfg_dataengine["MPRIS"] = mpris.currentText
awConfig.writeDataEngineConfiguration(cfg_dataengine) awConfig.writeDataEngineConfiguration(cfg_dataengine)
} }
} }

View File

@ -15,19 +15,18 @@
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/ ***************************************************************************/
import QtQuick 2.4 import QtQuick 2.15
import QtQuick.Controls 1.3 as QtControls import QtQuick.Controls
import QtQuick.Dialogs 1.2 as QtDialogs import QtQuick.Dialogs
import QtQuick.Layouts 1.1 import QtQuick.Layouts
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.private.awesomewidget 1.0 import org.kde.plasma.private.awesomewidget 1.0
import "." import "."
Item { PlasmoidItem {
id: main id: main
// backend // backend
AWKeys { AWKeys {
@ -36,6 +35,12 @@ Item {
AWActions { AWActions {
id: awActions id: awActions
} }
AWTelemetryHandler {
id: awTelemetryHandler
}
BugReport {
id: bugReport
}
property bool debug: awActions.isDebugEnabled() property bool debug: awActions.isDebugEnabled()
property variant tooltipSettings: { property variant tooltipSettings: {
@ -68,17 +73,12 @@ Item {
signal sizeUpdate signal sizeUpdate
// init Layout.fillWidth: PlasmoidItem.formFactor != PlasmaCore.Planar
Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation Layout.fillHeight: PlasmoidItem.formFactor != PlasmaCore.Planar
Plasmoid.compactRepresentation: Plasmoid.fullRepresentation
Layout.fillWidth: plasmoid.formFactor != PlasmaCore.Planar
Layout.fillHeight: plasmoid.formFactor != PlasmaCore.Planar
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Plasmoid.icon: "utilities-system-monitor" Plasmoid.icon: "utilities-system-monitor"
Plasmoid.backgroundHints: plasmoid.configuration.background ? "DefaultBackground" : "NoBackground" Plasmoid.backgroundHints: plasmoid.configuration.background ? "DefaultBackground" : "NoBackground"
Plasmoid.associatedApplication: "ksysguard"
// ui // ui
@ -89,14 +89,17 @@ Item {
textFormat: Text.RichText textFormat: Text.RichText
wrapMode: plasmoid.configuration.wrapText ? Text.WordWrap : Text.NoWrap wrapMode: plasmoid.configuration.wrapText ? Text.WordWrap : Text.NoWrap
horizontalAlignment: general.align[plasmoid.configuration.textAlign] horizontalAlignment: General.align[plasmoid.configuration.textAlign]
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
color: plasmoid.configuration.fontColor color: plasmoid.configuration.fontColor
font.family: plasmoid.configuration.fontFamily font.family: plasmoid.configuration.fontFamily
font.italic: plasmoid.configuration.fontStyle == "italic" ? true : false font.italic: plasmoid.configuration.fontStyle == "italic" ? true : false
font.pointSize: plasmoid.configuration.fontSize font.pointSize: plasmoid.configuration.fontSize
font.weight: general.fontWeight[plasmoid.configuration.fontWeight] font.weight: General.fontWeight[plasmoid.configuration.fontWeight]
style: General.textStyle[plasmoid.configuration.textStyle]
styleColor: plasmoid.configuration.textStyleColor
PlasmaCore.ToolTipArea { PlasmaCore.ToolTipArea {
height: tooltip.height height: tooltip.height
@ -110,11 +113,11 @@ Item {
} }
} }
QtDialogs.Dialog { Dialog {
id: tagSelector id: tagSelector
title: i18n("Select tag") title: i18n("Select tag")
QtControls.ComboBox { ComboBox {
id: tagSelectorBox id: tagSelectorBox
width: parent.width width: parent.width
editable: true editable: true
@ -131,16 +134,29 @@ Item {
} }
} }
Plasmoid.contextualActions: [
PlasmaCore.Action {
text: i18n("Request key")
icon.name: "utilities-system-monitor"
},
PlasmaCore.Action {
text: i18n("Show README")
icon.name: "text-x-readme"
},
PlasmaCore.Action {
text: i18n("Check updates")
icon.name: "system-software-update"
},
PlasmaCore.Action {
text: i18n("Report bug")
icon.name: "tools-report-bug"
}
]
Component.onCompleted: { Component.onCompleted: {
if (debug) console.debug() if (debug) console.debug()
// actions
// it makes no sense to use this field with optimization enable
if (!plasmoid.configuration.optimize)
plasmoid.setAction("requestKey", i18n("Request key"), "utilities-system-monitor")
plasmoid.setAction("showReadme", i18n("Show README"), "text-x-readme")
plasmoid.setAction("checkUpdates", i18n("Check updates"), "system-software-update")
// init submodule // init submodule
Plasmoid.userConfiguringChanged(false) Plasmoid.userConfiguringChanged(false)
// connect data // connect data
@ -150,14 +166,14 @@ Item {
if (plasmoid.configuration.checkUpdates) return awActions.checkUpdates(false) if (plasmoid.configuration.checkUpdates) return awActions.checkUpdates(false)
} }
onNeedTextUpdate: { onNeedTextUpdate: newText => {
if (debug) console.debug() if (debug) console.debug()
text.text = newText text.text = newText
sizeUpdate() sizeUpdate()
} }
onNeedToolTipUpdate: { onNeedToolTipUpdate: newText => {
if (debug) console.debug() if (debug) console.debug()
tooltip.text = newText tooltip.text = newText
@ -200,6 +216,15 @@ Item {
awKeys.setAggregatorProperty("customUptime", plasmoid.configuration.customUptime) awKeys.setAggregatorProperty("customUptime", plasmoid.configuration.customUptime)
awKeys.setAggregatorProperty("tempUnits", plasmoid.configuration.tempUnits) awKeys.setAggregatorProperty("tempUnits", plasmoid.configuration.tempUnits)
awKeys.setAggregatorProperty("translate", plasmoid.configuration.translateStrings) awKeys.setAggregatorProperty("translate", plasmoid.configuration.translateStrings)
// update telemetry ID
if (plasmoid.configuration.telemetryId.length == 0)
plasmoid.configuration.telemetryId = generateUuid()
// save telemetry
awTelemetryHandler.init(plasmoid.configuration.telemetryCount,
plasmoid.configuration.telemetryRemote,
plasmoid.configuration.telemetryId)
if (awTelemetryHandler.put("awwidgetconfig", plasmoid.configuration.text))
awTelemetryHandler.uploadTelemetry("awwidgetconfig", plasmoid.configuration.text)
} }
@ -215,10 +240,25 @@ Item {
return awActions.showReadme() return awActions.showReadme()
} }
function action_reportBug() {
if (debug) console.debug()
bugReport.reset()
bugReport.open()
}
function action_requestKey() { function action_requestKey() {
if (debug) console.debug() if (debug) console.debug()
tagSelectorBox.model = awKeys.dictKeys(true) tagSelectorBox.model = awKeys.dictKeys(true)
return tagSelector.open() return tagSelector.open()
} }
// code from http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
function generateUuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
} }

View File

@ -1 +1,27 @@
singleton general 1.0 general.qml # Do not edit qmldir directly it will be overrided during compilation,
# edit qml/qmldir.in file instead.
# common QML constants
singleton General 1.0 file:///usr/share/awesomewidgets/qml/General.qml
# custom QML UI classes
AboutTab file:///usr/share/awesomewidgets/qml/AboutTab.qml
AWExtensions file:///usr/share/awesomewidgets/qml/AWExtensions.qml
AWInfoLabel file:///usr/share/awesomewidgets/qml/AWInfoLabel.qml
AWTagSelector file:///usr/share/awesomewidgets/qml/AWTagSelector.qml
AWTextEditor file:///usr/share/awesomewidgets/qml/AWTextEditor.qml
BugReport file:///usr/share/awesomewidgets/qml/BugReport.qml
ButtonSelector file:///usr/share/awesomewidgets/qml/ButtonSelector.qml
CheckBoxSelector file:///usr/share/awesomewidgets/qml/CheckBoxSelector.qml
ColorSelector file:///usr/share/awesomewidgets/qml/ColorSelector.qml
ComboBoxSelector file:///usr/share/awesomewidgets/qml/ComboBoxSelector.qml
ExportDialog file:///usr/share/awesomewidgets/qml/ExportDialog.qml
FontSelector file:///usr/share/awesomewidgets/qml/FontSelector.qml
HtmlDefaultFunctionsBar file:///usr/share/awesomewidgets/qml/HtmlDefaultFunctionsBar.qml
HtmlEditorButton file:///usr/share/awesomewidgets/qml/HtmlEditorButton.qml
HtmlEditorColor file:///usr/share/awesomewidgets/qml/HtmlEditorColor.qml
HtmlEditorFont file:///usr/share/awesomewidgets/qml/HtmlEditorFont.qml
ImportDialog file:///usr/share/awesomewidgets/qml/ImportDialog.qml
IntegerSelector file:///usr/share/awesomewidgets/qml/IntegerSelector.qml
LineSelector file:///usr/share/awesomewidgets/qml/LineSelector.qml

View File

@ -15,10 +15,8 @@
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/ ***************************************************************************/
import QtQuick 2.0 import QtQuick 2.15
import QtQuick.Controls 1.3 as QtControls import QtQuick.Controls
import QtQuick.Controls.Styles 1.3 as QtStyles
import QtQuick.Dialogs 1.1 as QtDialogs
import org.kde.plasma.private.awesomewidget 1.0 import org.kde.plasma.private.awesomewidget 1.0
@ -39,27 +37,28 @@ Item {
property alias cfg_tooltipNumber: tooltipNumber.value property alias cfg_tooltipNumber: tooltipNumber.value
property alias cfg_useTooltipBackground: useTooltipBackground.checked property alias cfg_useTooltipBackground: useTooltipBackground.checked
property alias cfg_tooltipBackground: tooltipBackground.text property alias cfg_tooltipBackground: tooltipBackground.value
property alias cfg_cpuTooltip: cpuTooltip.checked property alias cfg_cpuTooltip: cpuTooltip.checked
property alias cfg_cpuTooltipColor: cpuTooltipColor.text property alias cfg_cpuTooltipColor: cpuTooltipColor.value
property alias cfg_cpuclTooltip: cpuclTooltip.checked property alias cfg_cpuclTooltip: cpuclTooltip.checked
property alias cfg_cpuclTooltipColor: cpuclTooltipColor.text property alias cfg_cpuclTooltipColor: cpuclTooltipColor.value
property alias cfg_memTooltip: memTooltip.checked property alias cfg_memTooltip: memTooltip.checked
property alias cfg_memTooltipColor: memTooltipColor.text property alias cfg_memTooltipColor: memTooltipColor.value
property alias cfg_swapTooltip: swapTooltip.checked property alias cfg_swapTooltip: swapTooltip.checked
property alias cfg_swapTooltipColor: swapTooltipColor.text property alias cfg_swapTooltipColor: swapTooltipColor.value
property alias cfg_downkbTooltip: downkbTooltip.checked property alias cfg_downkbTooltip: networkTooltip.checked
property alias cfg_downkbTooltipColor: downkbTooltipColor.text property alias cfg_downkbTooltipColor: downkbTooltipColor.value
property alias cfg_upkbTooltipColor: upkbTooltipColor.text property alias cfg_upkbTooltipColor: upkbTooltipColor.value
property alias cfg_batTooltip: batTooltip.checked property alias cfg_batTooltip: batTooltip.checked
property alias cfg_batTooltipColor: batTooltipColor.text property alias cfg_batTooltipColor: batTooltipColor.value
property alias cfg_batInTooltipColor: batInTooltipColor.text property alias cfg_batInTooltipColor: batInTooltipColor.value
Column { Column {
id: pageColumn id: pageColumn
anchors.fill: parent anchors.fill: parent
QtControls.Label {
Label {
width: parent.width width: parent.width
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
@ -67,347 +66,153 @@ Item {
text: i18n("CPU, CPU clock, memory, swap and network labels support graphical tooltip. To enable them just make needed checkbox checked.") text: i18n("CPU, CPU clock, memory, swap and network labels support graphical tooltip. To enable them just make needed checkbox checked.")
} }
Row { IntegerSelector {
height: implicitHeight id: tooltipNumber
width: parent.width maximumValue: 1000
QtControls.Label { minimumValue: 50
height: parent.height stepSize: 25
width: parent.width * 2 / 5 text: i18n("Number of values for tooltips")
horizontalAlignment: Text.AlignRight value: plasmoid.configuration.tooltipNumber
verticalAlignment: Text.AlignVCenter
text: i18n("Number of values for tooltips")
}
QtControls.SpinBox {
id: tooltipNumber
width: parent.width * 3 / 5
minimumValue: 50
maximumValue: 1000
stepSize: 25
value: plasmoid.configuration.tooltipNumber
}
} }
QtControls.GroupBox { GroupBox {
id: useTooltipBackground id: useTooltipBackground
height: implicitHeight
width: parent.width width: parent.width
checkable: true
title: i18n("Background")
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Background color")
}
QtControls.Button {
id: tooltipBackground
width: parent.width * 3 / 5
style: QtStyles.ButtonStyle {
background: Rectangle {
color: plasmoid.configuration.tooltipBackground
}
}
text: plasmoid.configuration.tooltipBackground
onClicked: tooltipBackgroundDialog.visible = true
}
QtDialogs.ColorDialog { property alias checked: useTooltipBackgroundLabel.checked
id: tooltipBackgroundDialog label: CheckBox {
title: i18n("Select a color") id: useTooltipBackgroundLabel
color: tooltipBackground.text text: i18n("Background")
onAccepted: tooltipBackground.text = tooltipBackgroundDialog.color }
}
ColorSelector {
id: tooltipBackground
enabled: useTooltipBackgroundLabel.checked
text: i18n("Background color")
value: plasmoid.configuration.tooltipBackground
} }
} }
QtControls.GroupBox { GroupBox {
id: cpuTooltip id: cpuTooltip
height: implicitHeight
width: parent.width width: parent.width
checkable: true
title: i18n("CPU")
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("CPU color")
}
QtControls.Button {
id: cpuTooltipColor
width: parent.width * 3 / 5
style: QtStyles.ButtonStyle {
background: Rectangle {
color: plasmoid.configuration.cpuTooltipColor
}
}
text: plasmoid.configuration.cpuTooltipColor
onClicked: cpuTooltipColorDialog.visible = true
}
QtDialogs.ColorDialog { property alias checked: cpuTooltipLabel.checked
id: cpuTooltipColorDialog label: CheckBox {
title: i18n("Select a color") id: cpuTooltipLabel
color: cpuTooltipColor.text text: i18n("CPU")
onAccepted: cpuTooltipColor.text = cpuTooltipColorDialog.color }
}
ColorSelector {
id: cpuTooltipColor
enabled: cpuTooltipLabel.checked
text: i18n("CPU color")
value: plasmoid.configuration.cpuTooltipColor
} }
} }
QtControls.GroupBox { GroupBox {
id: cpuclTooltip id: cpuclTooltip
height: implicitHeight
width: parent.width width: parent.width
checkable: true
title: i18n("CPU clock")
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("CPU clock color")
}
QtControls.Button {
id: cpuclTooltipColor
width: parent.width * 3 / 5
style: QtStyles.ButtonStyle {
background: Rectangle {
color: plasmoid.configuration.cpuclTooltipColor
}
}
text: plasmoid.configuration.cpuclTooltipColor
onClicked: cpuclTooltipColorDialog.visible = true
}
QtDialogs.ColorDialog { property alias checked: cpuclTooltipLabel.checked
id: cpuclTooltipColorDialog label: CheckBox {
title: i18n("Select a color") id: cpuclTooltipLabel
color: cpuclTooltipColor.text text: i18n("CPU clock")
onAccepted: cpuclTooltipColor.text = cpuclTooltipColorDialog.color }
}
ColorSelector {
id: cpuclTooltipColor
enabled: cpuclTooltipLabel.checked
text: i18n("CPU clock color")
value: plasmoid.configuration.cpuclTooltipColor
} }
} }
QtControls.GroupBox { GroupBox {
id: memTooltip id: memTooltip
height: implicitHeight
width: parent.width width: parent.width
checkable: true
title: i18n("Memory")
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Memory color")
}
QtControls.Button {
id: memTooltipColor
width: parent.width * 3 / 5
style: QtStyles.ButtonStyle {
background: Rectangle {
color: plasmoid.configuration.memTooltipColor
}
}
text: plasmoid.configuration.memTooltipColor
onClicked: memTooltipColorDialog.visible = true
}
QtDialogs.ColorDialog { property alias checked: memTooltipLabel.checked
id: memTooltipColorDialog label: CheckBox {
title: i18n("Select a color") id: memTooltipLabel
color: memTooltipColor.text text: i18n("Memory")
onAccepted: memTooltipColor.text = memTooltipColorDialog.color }
}
ColorSelector {
id: memTooltipColor
enabled: memTooltipLabel.checked
text: i18n("Memory color")
value: plasmoid.configuration.memTooltipColor
} }
} }
QtControls.GroupBox { GroupBox {
id: swapTooltip id: swapTooltip
height: implicitHeight
width: parent.width width: parent.width
checkable: true
title: i18n("Swap")
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Swap color")
}
QtControls.Button {
id: swapTooltipColor
width: parent.width * 3 / 5
style: QtStyles.ButtonStyle {
background: Rectangle {
color: plasmoid.configuration.swapTooltipColor
}
}
text: plasmoid.configuration.swapTooltipColor
onClicked: swapTooltipColorDialog.visible = true
}
QtDialogs.ColorDialog { property alias checked: swapTooltipLabel.checked
id: swapTooltipColorDialog label: CheckBox {
title: i18n("Select a color") id: swapTooltipLabel
color: swapTooltipColor.text text: i18n("Swap")
onAccepted: swapTooltipColor.text = swapTooltipColorDialog.color }
}
ColorSelector {
id: swapTooltipColor
enabled: swapTooltipLabel.checked
text: i18n("Swap color")
value: plasmoid.configuration.swapTooltipColor
} }
} }
QtControls.GroupBox { GroupBox {
id: downkbTooltip id: networkTooltip
height: implicitHeight
width: parent.width width: parent.width
checkable: true
title: i18n("Network") property alias checked: networkTooltipLabel.checked
label: CheckBox {
id: networkTooltipLabel
text: i18n("Network")
}
Column { Column {
height: implicitHeight
width: parent.width width: parent.width
Row { enabled: networkTooltipLabel.checked
height: implicitHeight ColorSelector {
width: parent.width id: downkbTooltipColor
QtControls.Label { text: i18n("Download speed color")
height: parent.height value: plasmoid.configuration.downkbTooltipColor
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Download speed color")
}
QtControls.Button {
id: downkbTooltipColor
width: parent.width * 3 / 5
style: QtStyles.ButtonStyle {
background: Rectangle {
color: plasmoid.configuration.downkbTooltipColor
}
}
text: plasmoid.configuration.downkbTooltipColor
onClicked: downkbTooltipColorDialog.visible = true
}
QtDialogs.ColorDialog {
id: downkbTooltipColorDialog
title: i18n("Select a color")
color: downkbTooltipColor.text
onAccepted: downkbTooltipColor.text = downkbTooltipColorDialog.color
}
} }
Row { ColorSelector {
height: implicitHeight id: upkbTooltipColor
width: parent.width text: i18n("Upload speed color")
QtControls.Label { value: plasmoid.configuration.upkbTooltipColor
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Upload speed color")
}
QtControls.Button {
id: upkbTooltipColor
width: parent.width * 3 / 5
style: QtStyles.ButtonStyle {
background: Rectangle {
color: plasmoid.configuration.upkbTooltipColor
}
}
text: plasmoid.configuration.upkbTooltipColor
onClicked: upkbTooltipColorDialog.visible = true
}
QtDialogs.ColorDialog {
id: upkbTooltipColorDialog
title: i18n("Select a color")
color: upkbTooltipColor.text
onAccepted: upkbTooltipColor.text = upkbTooltipColorDialog.color
}
} }
} }
} }
QtControls.GroupBox { GroupBox {
id: batTooltip id: batTooltip
height: implicitHeight
width: parent.width width: parent.width
checkable: true
title: i18n("Battery") property alias checked: batteryTooltipLabel.checked
label: CheckBox {
id: batteryTooltipLabel
text: i18n("Battery")
}
Column { Column {
height: implicitHeight
width: parent.width width: parent.width
Row { enabled: batteryTooltipLabel.checked
height: implicitHeight ColorSelector {
width: parent.width id: batTooltipColor
QtControls.Label { text: i18n("Battery active color")
height: parent.height value: plasmoid.configuration.batTooltipColor
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Battery active color")
}
QtControls.Button {
id: batTooltipColor
width: parent.width * 3 / 5
style: QtStyles.ButtonStyle {
background: Rectangle {
color: plasmoid.configuration.batTooltipColor
}
}
text: plasmoid.configuration.batTooltipColor
onClicked: batTooltipColorDialog.visible = true
}
QtDialogs.ColorDialog {
id: batTooltipColorDialog
title: i18n("Select a color")
color: batTooltipColor.text
onAccepted: batTooltipColor.text = batTooltipColorDialog.color
}
} }
Row { ColorSelector {
height: implicitHeight id: batInTooltipColor
width: parent.width text: i18n("Battery inactive color")
QtControls.Label { value: plasmoid.configuration.batInTooltipColor
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Battery inactive color")
}
QtControls.Button {
id: batInTooltipColor
width: parent.width * 3 / 5
style: QtStyles.ButtonStyle {
background: Rectangle {
color: plasmoid.configuration.batInTooltipColor
}
}
text: plasmoid.configuration.batInTooltipColor
onClicked: batInTooltipColorDialog.visible = true
}
QtDialogs.ColorDialog {
id: batInTooltipColorDialog
title: i18n("Select a color")
color: batInTooltipColor.text
onAccepted: batInTooltipColor.text = batInTooltipColorDialog.color
}
} }
} }
} }

View File

@ -15,11 +15,10 @@
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/ ***************************************************************************/
import QtQuick 2.0 import QtQuick 2.15
import QtQuick.Controls 1.3 as QtControls
import QtQuick.Dialogs 1.2 as QtDialogs
import org.kde.plasma.private.awesomewidget 1.0 import org.kde.plasma.private.awesomewidget 1.0
import "."
Item { Item {
@ -31,9 +30,6 @@ Item {
AWActions { AWActions {
id: awActions id: awActions
} }
AWFormatterConfigFactory {
id: awFormatter
}
width: childrenRect.width width: childrenRect.width
height: childrenRect.height height: childrenRect.height
@ -51,313 +47,33 @@ Item {
Column { Column {
id: pageColumn id: pageColumn
anchors.fill: parent anchors.fill: parent
QtControls.Label {
width: parent.width AWInfoLabel {}
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter HtmlDefaultFunctionsBar {
wrapMode: Text.WordWrap textArea: textPattern
text: i18n("Detailed information may be found on <a href=\"https://arcanis.me/projects/awesome-widgets/\">project homepage</a>")
onLinkActivated: Qt.openUrlExternally(link);
} }
Row { AWTagSelector {
height: implicitHeight backend: awKeys
width: parent.width notifyBackend: awActions
QtControls.Button { textArea: textPattern
width: parent.width * 3 / 15 groups: General.awTagRegexp
text: i18n("Bgcolor")
onClicked: backgroundDialog.visible = true
QtDialogs.ColorDialog {
id: backgroundDialog
title: i18n("Select a color")
onAccepted: {
var text = textPattern.text
textPattern.text = "<body bgcolor=\"" +
backgroundDialog.color + "\">" +
text + "</body>"
}
}
}
QtControls.Button {
width: parent.width * 3 / 15
text: i18n("Font")
iconName: "font"
onClicked: {
if (debug) console.debug("Font button")
var defaultFont = {
"color": plasmoid.configuration.fontColor,
"family": plasmoid.configuration.fontFamily,
"size": plasmoid.configuration.fontSize
}
var font = awActions.getFont(defaultFont)
if (font.applied != 1) {
if (debug) console.debug("No font selected")
return
}
var selected = textPattern.selectedText
textPattern.remove(textPattern.selectionStart, textPattern.selectionEnd)
textPattern.insert(textPattern.cursorPosition,
"<span style=\"color:" + font.color +
"; font-family:'" + font.family +
"'; font-size:" + font.size + "pt;\">" +
selected + "</span>")
}
}
QtControls.Button {
width: parent.width / 15
iconName: "format-indent-more"
onClicked: {
if (debug) console.debug("Indent button")
var selected = textPattern.selectedText
textPattern.remove(textPattern.selectionStart, textPattern.selectionEnd)
textPattern.insert(textPattern.cursorPosition, selected + "<br>\n")
}
}
QtControls.Button {
width: parent.width / 15
iconName: "format-text-bold"
onClicked: {
if (debug) console.debug("Bold button")
var selected = textPattern.selectedText
textPattern.remove(textPattern.selectionStart, textPattern.selectionEnd)
textPattern.insert(textPattern.cursorPosition, "<b>" + selected + "</b>")
}
}
QtControls.Button {
width: parent.width / 15
iconName: "format-text-italic"
onClicked: {
if (debug) console.debug("Italic button")
var selected = textPattern.selectedText
textPattern.remove(textPattern.selectionStart, textPattern.selectionEnd)
textPattern.insert(textPattern.cursorPosition, "<i>" + selected + "</i>")
}
}
QtControls.Button {
width: parent.width / 15
iconName: "format-text-underline"
onClicked: {
if (debug) console.debug("Underline button")
var selected = textPattern.selectedText
textPattern.remove(textPattern.selectionStart, textPattern.selectionEnd)
textPattern.insert(textPattern.cursorPosition, "<u>" + selected + "</u>")
}
}
QtControls.Button {
width: parent.width / 15
iconName: "format-text-strikethrough"
onClicked: {
if (debug) console.debug("Strike button")
var selected = textPattern.selectedText
textPattern.remove(textPattern.selectionStart, textPattern.selectionEnd)
textPattern.insert(textPattern.cursorPosition, "<s>" + selected + "</s>")
}
}
QtControls.Button {
width: parent.width / 15
iconName: "format-justify-left"
onClicked: {
if (debug) console.debug("Left button")
var selected = textPattern.selectedText
textPattern.remove(textPattern.selectionStart, textPattern.selectionEnd)
textPattern.insert(textPattern.cursorPosition, "<p align=\"left\">" + selected + "</p>")
}
}
QtControls.Button {
width: parent.width / 15
iconName: "format-justify-center"
onClicked: {
if (debug) console.debug("Center button")
var selected = textPattern.selectedText
textPattern.remove(textPattern.selectionStart, textPattern.selectionEnd)
textPattern.insert(textPattern.cursorPosition, "<p align=\"center\">" + selected + "</p>")
}
}
QtControls.Button {
width: parent.width / 15
iconName: "format-justify-right"
onClicked: {
if (debug) console.debug("Right button")
var selected = textPattern.selectedText
textPattern.remove(textPattern.selectionStart, textPattern.selectionEnd)
textPattern.insert(textPattern.cursorPosition, "<p align=\"right\">" + selected + "</p>")
}
}
QtControls.Button {
width: parent.width / 15
iconName: "format-justify-fill"
onClicked: {
if (debug) console.debug("Justify button")
var selected = textPattern.selectedText
textPattern.remove(textPattern.selectionStart, textPattern.selectionEnd)
textPattern.insert(textPattern.cursorPosition, "<p align=\"justify\">" + selected + "</p>")
}
}
} }
Row { AWExtensions {
height: implicitHeight id: extensions
width: parent.width backend: awKeys
QtControls.ComboBox { textArea: textPattern
width: parent.width * 2 / 5 onUnlock: lock = false
textRole: "label"
model: [
{
'label': i18n("AC"),
'regexp': "^(ac|bat).*"
},
{
'label': i18n("Bars"),
'regexp': "^bar.*"
},
{
'label': i18n("CPU"),
'regexp': "^(cpu|gpu|la|ps|temp(?!erature)).*"
},
{
'label': i18n("Desktops"),
'regexp': "^(n|t)?desktop(s)?"
},
{
'label': i18n("HDD"),
'regexp': "^hdd.*"
},
{
'label': i18n("Memory"),
'regexp': "^(mem|swap).*"
},
{
'label': i18n("Network"),
'regexp': "^(netdev|(down|up(?!time)).*)"
},
{
'label': i18n("Music player"),
'regexp': "(^|d|s)(album|artist|duration|progress|title)"
},
{
'label': i18n("Scripts"),
'regexp': "^custom.*"
},
{
'label': i18n("Time"),
'regexp': ".*time$"
},
{
'label': i18n("Quotes"),
'regexp': "^(perc)?(ask|bid|price)(chg)?.*"
},
{
'label': i18n("Upgrades"),
'regexp': "^pkgcount.*"
},
{
'label': i18n("Weathers"),
'regexp': "^(weather(Id)?|humidity|pressure|temperature|timestamp)"
},
{
'label': i18n("Functions"),
'regexp': "functions"
}
]
onCurrentIndexChanged: {
if (debug) console.debug()
if (model[currentIndex]["regexp"] == "functions")
tags.model = ["{{\n\n}}", "template{{\n\n}}",
"aw_all<>{{}}", "aw_count<>{{}}", "aw_keys<>{{}}",
"aw_macro<>{{}}", "aw_names<>{{}}"]
else
tags.model = awKeys.dictKeys(true, model[currentIndex]["regexp"])
if (debug) console.info("Init model", tags.model, "for", model[currentIndex]["label"])
tags.currentIndex = -1
}
}
QtControls.ComboBox {
id: tags
width: parent.width * 1 / 5
}
QtControls.Button {
width: parent.width * 1 / 5
text: i18n("Add")
onClicked: {
if (!tags.currentText) return
if (debug) console.debug("Add tag button")
var selected = textPattern.selectedText
textPattern.remove(textPattern.selectionStart, textPattern.selectionEnd)
textPattern.insert(textPattern.cursorPosition, selected + "$" + tags.currentText)
}
}
QtControls.Button {
width: parent.width * 1 / 5
text: i18n("Show value")
onClicked: {
if (!tags.currentText) return
if (debug) console.debug("Show tag button")
var message = i18n("Tag: %1", tags.currentText)
message += "<br>"
message += i18n("Value: %1", awKeys.valueByKey(tags.currentText))
message += "<br>"
message += i18n("Info: %1", awKeys.infoByKey(tags.currentText))
awActions.sendNotification("tag", message)
}
}
} }
Row { AWTextEditor {
height: implicitHeight
width: parent.width
QtControls.Button {
width: parent.width * 3 / 10
text: i18n("Edit bars")
onClicked: awKeys.editItem("graphicalitem")
}
QtControls.Button {
width: parent.width * 3 / 10
text: i18n("Formatters")
onClicked: awFormatter.showDialog(awKeys.dictKeys(true))
}
QtControls.Button {
width: parent.width * 2 / 5
text: i18n("Preview")
onClicked: {
lock = false
awKeys.initKeys(textPattern.text, plasmoid.configuration.interval,
plasmoid.configuration.queueLimit, false)
}
}
}
QtControls.TextArea {
id: textPattern id: textPattern
width: parent.width backend: awKeys
height: parent.height * 4 / 5
textFormat: TextEdit.PlainText
text: plasmoid.configuration.text
} }
} }
QtDialogs.MessageDialog {
id: compiledText
modality: Qt.NonModal
title: i18n("Preview")
}
Component.onCompleted: { Component.onCompleted: {
if (debug) console.debug() if (debug) console.debug()
@ -374,12 +90,11 @@ Item {
awKeys.setAggregatorProperty("translate", plasmoid.configuration.translateStrings) awKeys.setAggregatorProperty("translate", plasmoid.configuration.translateStrings)
} }
onNeedTextUpdate: { onNeedTextUpdate: newText => {
if (lock) return if (lock) return
if (debug) console.debug() if (debug) console.debug()
compiledText.text = newText.replace(/&nbsp;/g, " ") extensions.showMessage(newText)
compiledText.open() lock = true
lock = true;
} }
} }

View File

@ -1,28 +0,0 @@
[Desktop Entry]
Encoding=UTF-8
Name=Awesome Widget
Comment=A minimalistic Plasmoid
Comment[en]=A minimalistic Plasmoid
Comment[es]=Un plasmoide minimalista
Comment[es]=Un script Plasmoïde minimaliste
Comment[pt_BR]=Um script Plasmoid
Comment[ru]=Минималистичный плазмоид
Comment[uk]=Мінімалістичний плазмоїд
X-KDE-ServiceTypes=Plasma/Applet
Type=Service
Icon=utilities-system-monitor
X-KDE-ServiceTypes=Plasma/Applet
X-Plasma-API=declarativeappletscript
X-Plasma-MainScript=ui/main.qml
X-Plasma-RemoteLocation=
X-KDE-PluginInfo-Author=Evgeniy Alekseev aka arcanis
X-KDE-PluginInfo-Email=esalexeev@gmail.com
X-KDE-PluginInfo-Name=org.kde.plasma.awesomewidget
X-KDE-PluginInfo-Version=3.2.1
X-KDE-PluginInfo-Website=https://arcanis.me/projects/awesome-widgets/
X-KDE-PluginInfo-Category=System Information
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPLv3
X-KDE-PluginInfo-EnabledByDefault=true

View File

@ -0,0 +1,26 @@
{
"KPackageStructure": "Plasma/Applet",
"KPlugin": {
"Authors": [
{
"Email": "esalexeev@gmail.com",
"Name": "Evgeniy Alekseev aka arcanis"
}
],
"Category": "System Information",
"Description": "A minimalistic Plasmoid",
"Description[en]": "A minimalistic Plasmoid",
"Description[es]": "Un script Plasmoïde minimaliste",
"Description[pt_BR]": "Um script Plasmoid",
"Description[ru]": "Минималистичный плазмоид",
"Description[uk]": "Мінімалістичний плазмоїд",
"EnabledByDefault": true,
"Icon": "utilities-system-monitor",
"Id": "org.kde.plasma.awesomewidget",
"License": "GPLv3",
"Name": "Awesome Widget",
"Version": "3.5.1",
"Website": "https://arcanis.me/projects/awesome-widgets/"
},
"X-Plasma-API-Minimum-Version": "6.0"
}

View File

@ -7,17 +7,17 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/../../${PROJECT_LIBRARY}/ ${CMAKE_CURRENT_SOURCE_DIR}/../../${PROJECT_LIBRARY}/
${PROJECT_TRDPARTY_DIR} ${PROJECT_TRDPARTY_DIR}
${Qt_INCLUDE} ${Qt_INCLUDE}
${Kf5_INCLUDE} ${Kf6_INCLUDE}
) )
file(GLOB SUBPROJECT_SOURCE *.cpp ${PROJECT_TRDPARTY_DIR}/fontdialog/*.cpp ${CMAKE_SOURCE_DIR}/*.cpp) file(GLOB SUBPROJECT_SOURCE *.cpp ${PROJECT_TRDPARTY_DIR}/fontdialog/*.cpp ${CMAKE_SOURCE_DIR}/*.cpp)
file(GLOB SUBPROJECT_UI *.ui) file(GLOB SUBPROJECT_UI *.ui)
file(GLOB SUBPROJECT_NOTIFY *.notifyrc) file(GLOB SUBPROJECT_NOTIFY *.notifyrc)
qt5_wrap_ui(SUBPROJECT_UI_HEADER ${SUBPROJECT_UI}) qt6_wrap_ui(SUBPROJECT_UI_HEADER ${SUBPROJECT_UI})
add_library(${PLUGIN_NAME} SHARED ${SUBPROJECT_SOURCE} ${SUBPROJECT_UI_HEADER}) add_library(${PLUGIN_NAME} SHARED ${SUBPROJECT_SOURCE} ${SUBPROJECT_UI_HEADER})
target_link_libraries(${PLUGIN_NAME} ${PROJECT_LIBRARY} ${Qt_LIBRARIES} ${Kf5_LIBRARIES}) target_link_libraries(${PLUGIN_NAME} ${PROJECT_LIBRARY} ${Qt_LIBRARIES} ${Kf6_LIBRARIES})
install(TARGETS ${PLUGIN_NAME} DESTINATION ${QML_INSTALL_DIR}/org/kde/plasma/private/awesomewidget) install(TARGETS ${PLUGIN_NAME} DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/private/awesomewidget)
install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/plasma/private/awesomewidget) install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/private/awesomewidget)
install(FILES ${SUBPROJECT_NOTIFY} DESTINATION ${KNOTIFYRC_INSTALL_DIR}) install(FILES ${SUBPROJECT_NOTIFY} DESTINATION ${KDE_INSTALL_KNOTIFYRCDIR})

View File

@ -0,0 +1,181 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#include "awabstractpairconfig.h"
#include "ui_awabstractpairconfig.h"
#include <KI18n/KLocalizedString>
#include <QPushButton>
#include <utility>
#include "awabstractselector.h"
#include "awdebug.h"
AWAbstractPairConfig::AWAbstractPairConfig(QWidget *_parent, const bool _hasEdit, QStringList _keys)
: QDialog(_parent)
, ui(new Ui::AWAbstractPairConfig)
, m_hasEdit(_hasEdit)
, m_keys(std::move(_keys))
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
ui->setupUi(this);
connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
// edit feature
if (m_hasEdit) {
m_editButton = ui->buttonBox->addButton(i18n("Edit"), QDialogButtonBox::ActionRole);
connect(m_editButton, SIGNAL(clicked(bool)), this, SLOT(edit()));
}
}
AWAbstractPairConfig::~AWAbstractPairConfig()
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
clearSelectors();
delete ui;
}
void AWAbstractPairConfig::showDialog()
{
// update dialog
updateDialog();
// exec dialog
return execDialog();
}
void AWAbstractPairConfig::setEditable(const bool _first, const bool _second)
{
qCDebug(LOG_AW) << "Set editable" << _first << _second;
m_editable = {_first, _second};
}
void AWAbstractPairConfig::edit()
{
m_helper->editPairs();
updateDialog();
}
void AWAbstractPairConfig::updateUi()
{
QPair<QString, QString> current = dynamic_cast<AWAbstractSelector *>(sender())->current();
int index = m_selectors.indexOf(dynamic_cast<AWAbstractSelector *>(sender()));
if ((current.first.isEmpty()) && (current.second.isEmpty())) {
// remove current selector if it is empty and does not last
if (sender() == m_selectors.last())
return;
AWAbstractSelector *selector = m_selectors.takeAt(index);
ui->verticalLayout->removeWidget(selector);
selector->deleteLater();
} else {
// add new selector if something changed
if (sender() != m_selectors.last())
return;
auto keys = initKeys();
addSelector(keys.first, keys.second, QPair<QString, QString>());
}
}
void AWAbstractPairConfig::addSelector(const QStringList &_keys, const QStringList &_values,
const QPair<QString, QString> &_current)
{
qCDebug(LOG_AW) << "Add selector with keys" << _keys << "values" << _values << "and current ones" << _current;
auto *selector = new AWAbstractSelector(ui->scrollAreaWidgetContents, m_editable);
selector->init(_keys, _values, _current);
ui->verticalLayout->insertWidget(ui->verticalLayout->count() - 1, selector);
connect(selector, SIGNAL(selectionChanged()), this, SLOT(updateUi()));
m_selectors.append(selector);
}
void AWAbstractPairConfig::clearSelectors()
{
for (auto &selector : m_selectors) {
disconnect(selector, SIGNAL(selectionChanged()), this, SLOT(updateUi()));
ui->verticalLayout->removeWidget(selector);
selector->deleteLater();
}
m_selectors.clear();
}
void AWAbstractPairConfig::execDialog()
{
int ret = exec();
QHash<QString, QString> data;
for (auto &selector : m_selectors) {
QPair<QString, QString> select = selector->current();
if (select.first.isEmpty())
continue;
data[select.first] = select.second;
}
// save configuration if required
auto status = true;
switch (ret) {
case 0:
break;
case 1:
default:
status &= m_helper->writeItems(data);
status &= m_helper->removeUnusedKeys(data.keys());
break;
}
qCDebug(LOG_AW) << "Configuration save status" << status;
}
QPair<QStringList, QStringList> AWAbstractPairConfig::initKeys() const
{
// we are adding empty string at the start
QStringList left = {""};
left.append(m_helper->leftKeys().isEmpty() ? m_keys : m_helper->leftKeys());
left.sort();
QStringList right = {""};
right.append(m_helper->rightKeys().isEmpty() ? m_keys : m_helper->rightKeys());
right.sort();
return QPair<QStringList, QStringList>(left, right);
}
void AWAbstractPairConfig::updateDialog()
{
clearSelectors();
auto pairs = m_helper->pairs();
auto keys = initKeys();
for (auto &key : m_helper->keys())
addSelector(keys.first, keys.second, QPair<QString, QString>(key, m_helper->pairs()[key]));
// empty one
addSelector(keys.first, keys.second, QPair<QString, QString>());
}

View File

@ -0,0 +1,72 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#ifndef AWABSTRACTPAIRCONFIG_H
#define AWABSTRACTPAIRCONFIG_H
#include <QDialog>
#include "awabstractpairhelper.h"
class AWAbstractSelector;
namespace Ui
{
class AWAbstractPairConfig;
}
class AWAbstractPairConfig : public QDialog
{
Q_OBJECT
public:
explicit AWAbstractPairConfig(QWidget *_parent = nullptr, bool _hasEdit = false, QStringList _keys = QStringList());
~AWAbstractPairConfig() override;
template <class T> void initHelper()
{
delete m_helper;
m_helper = new T(this);
}
void showDialog();
// properties
void setEditable(bool _first, bool _second);
private slots:
void edit();
void updateUi();
private:
QPushButton *m_editButton = nullptr;
Ui::AWAbstractPairConfig *ui = nullptr;
AWAbstractPairHelper *m_helper = nullptr;
QList<AWAbstractSelector *> m_selectors;
// properties
QPair<bool, bool> m_editable = {false, false};
bool m_hasEdit = false;
QStringList m_keys;
// methods
void addSelector(const QStringList &_keys, const QStringList &_values, const QPair<QString, QString> &_current);
void clearSelectors();
void execDialog();
[[nodiscard]] QPair<QStringList, QStringList> initKeys() const;
void updateDialog();
};
#endif /* AWABSTRACTPAIRCONFIG_H */

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>AWFormatterConfig</class> <class>AWAbstractPairConfig</class>
<widget class="QDialog" name="AWFormatterConfig"> <widget class="QDialog" name="AWAbstractPairConfig">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -60,7 +60,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>accepted()</signal> <signal>accepted()</signal>
<receiver>AWFormatterConfig</receiver> <receiver>AWAbstractPairConfig</receiver>
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -76,7 +76,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>AWFormatterConfig</receiver> <receiver>AWAbstractPairConfig</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -0,0 +1,135 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#include "awabstractpairhelper.h"
#include <QSettings>
#include <QStandardPaths>
#include <utility>
#include "awdebug.h"
AWAbstractPairHelper::AWAbstractPairHelper(QString _filePath, QString _section)
: m_filePath(std::move(_filePath))
, m_section(std::move(_section))
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
AWAbstractPairHelper::initItems();
}
AWAbstractPairHelper::~AWAbstractPairHelper()
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
}
QStringList AWAbstractPairHelper::keys() const
{
return m_pairs.keys();
}
QHash<QString, QString> AWAbstractPairHelper::pairs() const
{
return m_pairs;
}
QStringList AWAbstractPairHelper::values() const
{
return m_pairs.values();
}
QSet<QString> AWAbstractPairHelper::valuesSet() const
{
auto values = m_pairs.values();
return {values.cbegin(), values.cend()};
}
void AWAbstractPairHelper::initItems()
{
m_pairs.clear();
QStringList configs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, m_filePath);
for (auto &fileName : configs) {
QSettings settings(fileName, QSettings::IniFormat);
qCInfo(LOG_AW) << "Configuration file" << settings.fileName();
settings.beginGroup(m_section);
QStringList keys = settings.childKeys();
for (auto &key : keys) {
QString value = settings.value(key).toString();
qCInfo(LOG_AW) << "Found key" << key << "for value" << value << "in" << settings.fileName();
if (value.isEmpty()) {
qCInfo(LOG_AW) << "Skip empty value for" << key;
continue;
}
m_pairs[key] = value;
}
settings.endGroup();
}
}
bool AWAbstractPairHelper::writeItems(const QHash<QString, QString> &_configuration) const
{
qCDebug(LOG_AW) << "Write configuration" << _configuration;
QString fileName
= QString("%1/%2").arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)).arg(m_filePath);
QSettings settings(fileName, QSettings::IniFormat);
qCInfo(LOG_AW) << "Configuration file" << fileName;
settings.beginGroup(m_section);
for (auto &key : _configuration.keys())
settings.setValue(key, _configuration[key]);
settings.endGroup();
settings.sync();
return (settings.status() == QSettings::NoError);
}
bool AWAbstractPairHelper::removeUnusedKeys(const QStringList &_keys) const
{
qCDebug(LOG_AW) << "Remove keys" << _keys;
QString fileName
= QString("%1/%2").arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)).arg(m_filePath);
QSettings settings(fileName, QSettings::IniFormat);
qCInfo(LOG_AW) << "Configuration file" << fileName;
settings.beginGroup(m_section);
QStringList foundKeys = settings.childKeys();
for (auto &key : foundKeys) {
if (_keys.contains(key))
continue;
settings.remove(key);
}
settings.endGroup();
settings.sync();
return (settings.status() == QSettings::NoError);
}

View File

@ -0,0 +1,51 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#ifndef AWABSTRACTPAIRHELPER_H
#define AWABSTRACTPAIRHELPER_H
#include <QHash>
class AWAbstractPairHelper
{
public:
explicit AWAbstractPairHelper(QString _filePath = "", QString _section = "");
virtual ~AWAbstractPairHelper();
[[nodiscard]] QStringList keys() const;
[[nodiscard]] QHash<QString, QString> pairs() const;
[[nodiscard]] QStringList values() const;
[[nodiscard]] QSet<QString> valuesSet() const;
// read-write methods
virtual void initItems();
[[nodiscard]] virtual bool writeItems(const QHash<QString, QString> &_configuration) const;
[[nodiscard]] virtual bool removeUnusedKeys(const QStringList &_keys) const;
// configuration related
virtual void editPairs() = 0;
virtual QStringList leftKeys() = 0;
virtual QStringList rightKeys() = 0;
private:
// properties
QHash<QString, QString> m_pairs;
QString m_filePath;
QString m_section;
};
#endif /* AWABSTRACTPAIRHELPER_H */

View File

@ -21,18 +21,18 @@
#include "awdebug.h" #include "awdebug.h"
AWAbstractSelector::AWAbstractSelector(QWidget *parent) AWAbstractSelector::AWAbstractSelector(QWidget *_parent, const QPair<bool, bool> &_editable)
: QWidget(parent) : QWidget(_parent)
, ui(new Ui::AWAbstractSelector) , ui(new Ui::AWAbstractSelector)
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
ui->setupUi(this); ui->setupUi(this);
ui->comboBox_key->setEditable(_editable.first);
ui->comboBox_value->setEditable(_editable.second);
connect(ui->comboBox_key, SIGNAL(currentIndexChanged(int)), this, connect(ui->comboBox_key, SIGNAL(currentIndexChanged(int)), this, SIGNAL(selectionChanged()));
SIGNAL(selectionChanged())); connect(ui->comboBox_value, SIGNAL(currentIndexChanged(int)), this, SIGNAL(selectionChanged()));
connect(ui->comboBox_value, SIGNAL(currentIndexChanged(int)), this,
SIGNAL(selectionChanged()));
} }
@ -53,24 +53,23 @@ QPair<QString, QString> AWAbstractSelector::current() const
} }
void AWAbstractSelector::init(const QStringList keys, const QStringList values, void AWAbstractSelector::init(const QStringList &_keys, const QStringList &_values,
const QPair<QString, QString> current) const QPair<QString, QString> &_current)
{ {
if ((!keys.contains(current.first)) || (!values.contains(current.second))) { if ((!_keys.contains(_current.first)) || (!_values.contains(_current.second))) {
qCWarning(LOG_AW) << "Invalid current value" << current qCWarning(LOG_AW) << "Invalid current value" << _current << "not found in default ones";
<< "not found in default ones";
return; return;
} }
qCDebug(LOG_AW) << "Init selector with keys" << keys << "and values" qCDebug(LOG_AW) << "Init selector with keys" << _keys << "and values" << _values << "and current ones are"
<< values << "and current ones are" << current; << _current;
// set data // set data
ui->comboBox_key->clear(); ui->comboBox_key->clear();
ui->comboBox_key->addItems(keys); ui->comboBox_key->addItems(_keys);
ui->comboBox_value->clear(); ui->comboBox_value->clear();
ui->comboBox_value->addItems(values); ui->comboBox_value->addItems(_values);
// set current values // set current values
ui->comboBox_key->setCurrentText(current.first); ui->comboBox_key->setCurrentText(_current.first);
ui->comboBox_value->setCurrentText(current.second); ui->comboBox_value->setCurrentText(_current.second);
} }

View File

@ -32,11 +32,10 @@ class AWAbstractSelector : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit AWAbstractSelector(QWidget *parent = nullptr); explicit AWAbstractSelector(QWidget *_parent = nullptr, const QPair<bool, bool> &_editable = {false, false});
virtual ~AWAbstractSelector(); ~AWAbstractSelector() override;
QPair<QString, QString> current() const; [[nodiscard]] QPair<QString, QString> current() const;
void init(const QStringList keys, const QStringList values, void init(const QStringList &_keys, const QStringList &_values, const QPair<QString, QString> &_current);
const QPair<QString, QString> current);
signals: signals:
void selectionChanged(); void selectionChanged();

View File

@ -21,6 +21,7 @@
#include <KNotifications/KNotification> #include <KNotifications/KNotification>
#include <QDesktopServices> #include <QDesktopServices>
#include <QFile>
#include <QProcess> #include <QProcess>
#include <QUrl> #include <QUrl>
@ -30,8 +31,8 @@
#include "awupdatehelper.h" #include "awupdatehelper.h"
AWActions::AWActions(QObject *parent) AWActions::AWActions(QObject *_parent)
: QObject(parent) : QObject(_parent)
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
@ -42,140 +43,106 @@ AWActions::AWActions(QObject *parent)
AWActions::~AWActions() AWActions::~AWActions()
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
delete m_updateHelper;
} }
void AWActions::checkUpdates(const bool showAnyway) void AWActions::checkUpdates(const bool _showAnyway)
{ {
qCDebug(LOG_AW) << "Show anyway" << showAnyway; qCDebug(LOG_AW) << "Show anyway" << _showAnyway;
if (!m_updateHelper->checkVersion()) if (!m_updateHelper->checkVersion())
m_updateHelper->checkUpdates(showAnyway); m_updateHelper->checkUpdates(_showAnyway);
}
QString AWActions::getFileContent(const QString &_path)
{
qCDebug(LOG_AW) << "Get content from file" << _path;
QFile inputFile(_path);
if (!inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qCWarning(LOG_AW) << "Could not open file as text" << inputFile.fileName();
return "";
}
QString output = inputFile.readAll();
inputFile.close();
return output;
} }
// HACK: since QML could not use QLoggingCategory I need this hack // HACK: since QML could not use QLoggingCategory I need this hack
bool AWActions::isDebugEnabled() const bool AWActions::isDebugEnabled()
{ {
return LOG_AW().isDebugEnabled(); return LOG_AW().isDebugEnabled();
} }
bool AWActions::runCmd(const QString cmd) const bool AWActions::runCmd(const QString &_cmd, const QStringList &_args)
{ {
qCDebug(LOG_AW) << "Cmd" << cmd; qCDebug(LOG_AW) << "Cmd" << _cmd << "args" << _args;
sendNotification(QString("Info"), i18n("Run %1", cmd)); sendNotification(QString("Info"), i18n("Run %1", _cmd));
return QProcess::startDetached(cmd); return QProcess::startDetached(_cmd, _args);
} }
// HACK: this method uses variable from version.h // HACK: this method uses variable from version.h
void AWActions::showReadme() const void AWActions::showReadme()
{ {
QDesktopServices::openUrl(QUrl(HOMEPAGE)); QDesktopServices::openUrl(QUrl(HOMEPAGE));
} }
// HACK: this method uses variables from version.h void AWActions::showLegacyInfo()
QString AWActions::getAboutText(const QString type) const
{ {
qCDebug(LOG_AW) << "Type" << type; auto *msgBox = new QMessageBox(nullptr);
msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->setModal(false);
msgBox->setWindowTitle(i18n("Not supported"));
msgBox->setText(i18n("You are using mammoth's Qt version, try to update it first"));
msgBox->setStandardButtons(QMessageBox::Ok);
msgBox->setIcon(QMessageBox::Information);
QString text; msgBox->open();
if (type == QString("header")) {
text = QString(NAME);
} else if (type == QString("version")) {
text = i18n("Version %1 (build date %2)", QString(VERSION),
QString(BUILD_DATE));
if (!QString(COMMIT_SHA).isEmpty())
text += QString(" (%1)").arg(QString(COMMIT_SHA));
} else if (type == QString("description")) {
text = i18n("A set of minimalistic plasmoid widgets");
} else if (type == QString("links")) {
text = i18n("Links:") + QString("<br>")
+ QString("<a href=\"%1\">%2</a><br>")
.arg(QString(HOMEPAGE))
.arg(i18n("Homepage"))
+ QString("<a href=\"%1\">%2</a><br>")
.arg(QString(REPOSITORY))
.arg(i18n("Repository"))
+ QString("<a href=\"%1\">%2</a><br>")
.arg(QString(BUGTRACKER))
.arg(i18n("Bugtracker"))
+ QString("<a href=\"%1\">%2</a><br>")
.arg(QString(TRANSLATION))
.arg(i18n("Translation issue"))
+ QString("<a href=\"%1\">%2</a><br>")
.arg(QString(AUR_PACKAGES))
.arg(i18n("AUR packages"))
+ QString("<a href=\"%1\">%2</a>")
.arg(QString(OPENSUSE_PACKAGES))
.arg(i18n("openSUSE packages"));
} else if (type == QString("copy")) {
text = QString("<small>&copy; %1 <a href=\"mailto:%2\">%3</a><br>")
.arg(QString(DATE))
.arg(QString(EMAIL))
.arg(QString(AUTHOR))
+ i18n("This software is licensed under %1", QString(LICENSE))
+ QString("</small>");
} else if (type == QString("translators")) {
text = i18n("Translators: %1", QString(TRANSLATORS));
} else if (type == QString("3rdparty")) {
QStringList trdPartyList
= QString(TRDPARTY_LICENSE)
.split(QChar(';'), QString::SkipEmptyParts);
for (int i = 0; i < trdPartyList.count(); i++)
trdPartyList[i] = QString("<a href=\"%3\">%1</a> (%2 license)")
.arg(trdPartyList.at(i).split(QChar(','))[0])
.arg(trdPartyList.at(i).split(QChar(','))[1])
.arg(trdPartyList.at(i).split(QChar(','))[2]);
text = i18n("This software uses: %1", trdPartyList.join(QString(", ")));
} else if (type == QString("thanks")) {
QStringList thanks = QString(SPECIAL_THANKS)
.split(QChar(';'), QString::SkipEmptyParts);
for (int i = 0; i < thanks.count(); i++)
thanks[i] = QString("<a href=\"%2\">%1</a>")
.arg(thanks.at(i).split(QChar(','))[0])
.arg(thanks.at(i).split(QChar(','))[1]);
text = i18n("Special thanks to %1", thanks.join(QString(", ")));
}
return text;
} }
QVariantMap AWActions::getFont(const QVariantMap defaultFont) const // HACK: this method uses variables from version.h
QString AWActions::getAboutText(const QString &_type)
{ {
qCDebug(LOG_AW) << "Default font is" << defaultFont; qCDebug(LOG_AW) << "Type" << _type;
return AWDebug::getAboutText(_type);
}
QVariantMap AWActions::getFont(const QVariantMap &_defaultFont)
{
qCDebug(LOG_AW) << "Default font is" << _defaultFont;
QVariantMap fontMap; QVariantMap fontMap;
int ret = 0; int ret = 0;
CFont defaultCFont = CFont(defaultFont[QString("family")].toString(), CFont defaultCFont = CFont(_defaultFont["family"].toString(), _defaultFont["size"].toInt(), 400, false,
defaultFont[QString("size")].toInt(), 400, false, _defaultFont["color"].toString());
defaultFont[QString("color")].toString()); CFont font = CFontDialog::getFont(i18n("Select font"), defaultCFont, false, false, &ret);
CFont font = CFontDialog::getFont(i18n("Select font"), defaultCFont, false,
false, &ret);
fontMap[QString("applied")] = ret; fontMap["applied"] = ret;
fontMap[QString("color")] = font.color().name(); fontMap["color"] = font.color().name();
fontMap[QString("family")] = font.family(); fontMap["family"] = font.family();
fontMap[QString("size")] = font.pointSize(); fontMap["size"] = font.pointSize();
return fontMap; return fontMap;
} }
// to avoid additional object definition this method is static // to avoid additional object definition this method is static
void AWActions::sendNotification(const QString eventId, const QString message) void AWActions::sendNotification(const QString &_eventId, const QString &_message)
{ {
qCDebug(LOG_AW) << "Event" << eventId << "with message" << message; qCDebug(LOG_AW) << "Event" << _eventId << "with message" << _message;
KNotification *notification = KNotification::event( KNotification *notification
eventId, QString("Awesome Widget ::: %1").arg(eventId), message); = KNotification::event(_eventId, QString("Awesome Widget ::: %1").arg(_eventId), _message);
notification->setComponentName( notification->setComponentName("plasma-applet-org.kde.plasma.awesome-widget");
QString("plasma-applet-org.kde.plasma.awesome-widget"));
} }

View File

@ -30,20 +30,20 @@ class AWActions : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit AWActions(QObject *parent = nullptr); explicit AWActions(QObject *_parent = nullptr);
virtual ~AWActions(); ~AWActions() override;
Q_INVOKABLE void checkUpdates(const bool showAnyway = false); Q_INVOKABLE void checkUpdates(bool _showAnyway = false);
Q_INVOKABLE bool isDebugEnabled() const; Q_INVOKABLE static QString getFileContent(const QString &_path);
Q_INVOKABLE bool runCmd(const QString cmd = QString("/usr/bin/true")) const; Q_INVOKABLE static bool isDebugEnabled();
Q_INVOKABLE void showReadme() const; Q_INVOKABLE static bool runCmd(const QString &_cmd, const QStringList &_args);
Q_INVOKABLE static void showLegacyInfo();
Q_INVOKABLE static void showReadme();
// configuration slots // configuration slots
Q_INVOKABLE QString getAboutText(const QString type Q_INVOKABLE static QString getAboutText(const QString &_type);
= QString("header")) const; Q_INVOKABLE static QVariantMap getFont(const QVariantMap &_defaultFont);
Q_INVOKABLE QVariantMap getFont(const QVariantMap defaultFont) const;
public slots: public slots:
Q_INVOKABLE static void sendNotification(const QString eventId, Q_INVOKABLE static void sendNotification(const QString &_eventId, const QString &_message);
const QString message);
private: private:
AWUpdateHelper *m_updateHelper = nullptr; AWUpdateHelper *m_updateHelper = nullptr;

View File

@ -0,0 +1,149 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#include "awbugreporter.h"
#include <KI18n/KLocalizedString>
#include <QDesktopServices>
#include <QJsonDocument>
#include <QMessageBox>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include "awdebug.h"
AWBugReporter::AWBugReporter(QObject *_parent)
: QObject(_parent)
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
}
AWBugReporter::~AWBugReporter()
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
}
void AWBugReporter::doConnect()
{
// additional method for testing needs
connect(this, SIGNAL(replyReceived(const int, const QString &)), this, SLOT(showInformation(int, const QString &)));
}
QString AWBugReporter::generateText(const QString &_description, const QString &_reproduce, const QString &_expected,
const QString &_logs)
{
// do not log _logs here, it may have quite large size
qCDebug(LOG_AW) << "Generate text with description" << _description << "steps" << _reproduce
<< "and expected result" << _expected;
QString output;
output += QString("**Description**\n\n%1\n\n").arg(_description);
output += QString("**Step to _reproduce**\n\n%1\n\n").arg(_reproduce);
output += QString("**Expected result**\n\n%1\n\n").arg(_expected);
output += QString("**Version**\n\n%1\n\n").arg(AWDebug::getBuildData().join(QString("\n")));
// append _logs
output += QString("**Logs**\n\n%1").arg(_logs);
return output;
}
void AWBugReporter::sendBugReport(const QString &_title, const QString &_body)
{
qCDebug(LOG_AW) << "Send bug report with title" << _title << "and body" << _body;
auto *manager = new QNetworkAccessManager(nullptr);
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(issueReplyRecieved(QNetworkReply *)));
QNetworkRequest request = QNetworkRequest(QUrl(BUGTRACKER_API));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
// generate payload
QVariantMap payload;
payload["title"] = _title;
payload["body"] = _body;
payload["labels"] = QStringList() << "from application";
// convert to QByteArray to send request
QByteArray data = QJsonDocument::fromVariant(payload).toJson(QJsonDocument::Compact);
qCInfo(LOG_AW) << "Send request with _body" << data.data() << "and size" << data.size();
manager->post(request, data);
}
void AWBugReporter::issueReplyRecieved(QNetworkReply *_reply)
{
if (_reply->error() != QNetworkReply::NoError) {
qCWarning(LOG_AW) << "An error occurs" << _reply->error() << "with message" << _reply->errorString();
return emit(replyReceived(0, ""));
}
QJsonParseError error{};
QJsonDocument jsonDoc = QJsonDocument::fromJson(_reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(LOG_AW) << "Parse error" << error.errorString();
return emit(replyReceived(0, ""));
}
_reply->deleteLater();
// convert to map
QVariantMap response = jsonDoc.toVariant().toMap();
QString url = response["html_url"].toString();
int number = response["number"].toInt();
return emit(replyReceived(number, url));
}
void AWBugReporter::showInformation(const int _number, const QString &_url)
{
qCDebug(LOG_AW) << "Created issue with number" << _number << "and url" << _url;
// cache url first
m_lastBugUrl = _url;
auto *msgBox = new QMessageBox(nullptr);
msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->setModal(false);
msgBox->setWindowTitle(i18n("Issue created"));
msgBox->setText(i18n("Issue %1 has been created", _number));
msgBox->setStandardButtons(QMessageBox::Open | QMessageBox::Close);
msgBox->setIcon(QMessageBox::Information);
msgBox->open(this, SLOT(userReplyOnBugReport(QAbstractButton *)));
}
void AWBugReporter::userReplyOnBugReport(QAbstractButton *_button)
{
QMessageBox::ButtonRole ret = dynamic_cast<QMessageBox *>(sender())->buttonRole(_button);
qCInfo(LOG_AW) << "User select" << ret;
switch (ret) {
case QMessageBox::AcceptRole:
QDesktopServices::openUrl(m_lastBugUrl);
break;
case QMessageBox::RejectRole:
default:
break;
}
}

View File

@ -0,0 +1,53 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#ifndef AWBUGREPORTER_H
#define AWBUGREPORTER_H
#include <QObject>
class QAbstractButton;
class QNetworkReply;
class AWBugReporter : public QObject
{
Q_OBJECT
public:
explicit AWBugReporter(QObject *_parent = nullptr);
~AWBugReporter() override;
Q_INVOKABLE void doConnect();
Q_INVOKABLE static QString generateText(const QString &_description, const QString &_reproduce,
const QString &_expected, const QString &_logs);
Q_INVOKABLE void sendBugReport(const QString &_title, const QString &_body);
signals:
void replyReceived(int _number, const QString &_url);
private slots:
void issueReplyRecieved(QNetworkReply *_reply);
void showInformation(int _number, const QString &_url);
void userReplyOnBugReport(QAbstractButton *_button);
private:
QString m_lastBugUrl;
};
#endif /* AWBUGREPORTER_H */

View File

@ -17,20 +17,20 @@
#include "awconfighelper.h" #include "awconfighelper.h"
#include <KI18n/KLocalizedString>
#include <QDir> #include <QDir>
#include <QQmlPropertyMap> #include <QQmlPropertyMap>
#include <QSettings> #include <QSettings>
#include <QTextCodec> #include <QStandardPaths>
#include "awdebug.h" #include "awdebug.h"
AWConfigHelper::AWConfigHelper(QObject *parent) AWConfigHelper::AWConfigHelper(QObject *_parent)
: QObject(parent) : QObject(_parent)
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
m_baseDir = QString("%1/awesomewidgets").arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation));
} }
@ -40,17 +40,15 @@ AWConfigHelper::~AWConfigHelper()
} }
QString AWConfigHelper::configurationDirectory() const QString AWConfigHelper::configurationDirectory()
{ {
// get readable directory // get readable directory
QString localDir = QString("%1/awesomewidgets/configs") QString localDir = QString("%1/awesomewidgets/configs")
.arg(QStandardPaths::writableLocation( .arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation));
QStandardPaths::GenericDataLocation));
// create directory and copy files from default settings // create directory and copy files from default settings
QDir localDirectory; QDir localDirectory;
if ((!localDirectory.exists(localDir)) if ((!localDirectory.exists(localDir)) && (localDirectory.mkpath(localDir))) {
&& (localDirectory.mkpath(localDir))) {
qCInfo(LOG_AW) << "Created directory" << localDir; qCInfo(LOG_AW) << "Created directory" << localDir;
copyConfigs(localDir); copyConfigs(localDir);
} }
@ -59,28 +57,24 @@ QString AWConfigHelper::configurationDirectory() const
} }
bool AWConfigHelper::dropCache() const bool AWConfigHelper::dropCache()
{ {
QString fileName = QString("%1/awesomewidgets.ndx") QString fileName
.arg(QStandardPaths::writableLocation( = QString("%1/awesomewidgets.ndx").arg(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation));
QStandardPaths::GenericCacheLocation));
return QFile(fileName).remove(); return QFile(fileName).remove();
} }
bool AWConfigHelper::exportConfiguration(const QObject *nativeConfig, bool AWConfigHelper::exportConfiguration(QObject *_nativeConfig, const QString &_fileName) const
const QString fileName) const
{ {
qCDebug(LOG_AW) << "Selected filename" << fileName; qCDebug(LOG_AW) << "Selected filename" << _fileName;
QSettings settings(fileName, QSettings::IniFormat);
QSettings settings(_fileName, QSettings::IniFormat);
// plasmoid configuration // plasmoid configuration
const QQmlPropertyMap *configuration const auto *configuration = dynamic_cast<const QQmlPropertyMap *>(_nativeConfig);
= static_cast<const QQmlPropertyMap *>(nativeConfig); settings.beginGroup("plasmoid");
settings.beginGroup(QString("plasmoid")); for (auto &key : configuration->keys()) {
for (auto key : configuration->keys()) {
QVariant value = configuration->value(key); QVariant value = configuration->value(key);
if (!value.isValid()) if (!value.isValid())
continue; continue;
@ -89,30 +83,28 @@ bool AWConfigHelper::exportConfiguration(const QObject *nativeConfig,
settings.endGroup(); settings.endGroup();
// extensions // extensions
for (auto item : m_dirs) { for (auto &item : m_dirs) {
QStringList items QStringList items
= QDir(QString("%1/%2").arg(m_baseDir).arg(item)) = QDir(QString("%1/%2").arg(m_baseDir).arg(item)).entryList(QStringList() << "*.desktop", QDir::Files);
.entryList(QStringList() << QString("*.desktop"),
QDir::Files);
settings.beginGroup(item); settings.beginGroup(item);
for (auto it : items) for (auto &it : items)
copyExtensions(it, item, settings, false); copyExtensions(it, item, settings, false);
settings.endGroup(); settings.endGroup();
} }
// additional files // additional files
settings.beginGroup(QString("json")); settings.beginGroup("json");
// script filters // script filters
readFile(settings, QString("filters"), readFile(settings, "filters", QString("%1/scripts/awesomewidgets-extscripts-filters.json").arg(m_baseDir));
QString("%1/scripts/awesomewidgets-extscripts-filters.json")
.arg(m_baseDir));
// weather icon settings // weather icon settings
readFile(settings, QString("weathers"), readFile(settings, "weathers", QString("%1/weather/awesomewidgets-extweather-ids.json").arg(m_baseDir));
QString("%1/weather/awesomewidgets-extweather-ids.json") settings.endGroup();
.arg(m_baseDir));
settings.beginGroup("ini");
// formatter settings // formatter settings
readFile(settings, QString("formatters"), readFile(settings, "formatters", QString("%1/formatters/formatters.ini").arg(m_baseDir));
QString("%1/formatters/formatters.ini").arg(m_baseDir)); // custom keys settings
readFile(settings, "custom", QString("%1/custom.ini").arg(m_baseDir));
settings.endGroup(); settings.endGroup();
// sync settings // sync settings
@ -122,47 +114,45 @@ bool AWConfigHelper::exportConfiguration(const QObject *nativeConfig,
} }
QVariantMap AWConfigHelper::importConfiguration(const QString fileName, QVariantMap AWConfigHelper::importConfiguration(const QString &_fileName, const bool _importPlasmoid,
const bool importPlasmoid, const bool _importExtensions, const bool _importAdds) const
const bool importExtensions,
const bool importAdds) const
{ {
qCDebug(LOG_AW) << "Selected filename" << fileName; qCDebug(LOG_AW) << "Selected filename" << _fileName;
QVariantMap configuration; QVariantMap configuration;
QSettings settings(fileName, QSettings::IniFormat); QSettings settings(_fileName, QSettings::IniFormat);
// extensions // extensions
if (importExtensions) { if (_importExtensions) {
for (auto item : m_dirs) { for (auto &item : m_dirs) {
settings.beginGroup(item); settings.beginGroup(item);
for (auto it : settings.childGroups()) for (auto &it : settings.childGroups())
copyExtensions(it, item, settings, true); copyExtensions(it, item, settings, true);
settings.endGroup(); settings.endGroup();
} }
} }
// additional files // additional files
if (importAdds) { if (_importAdds) {
settings.beginGroup(QString("json")); settings.beginGroup("json");
// script filters // script filters
writeFile(settings, QString("filters"), writeFile(settings, "filters", QString("%1/scripts/awesomewidgets-extscripts-filters.json").arg(m_baseDir));
QString("%1/scripts/awesomewidgets-extscripts-filters.json")
.arg(m_baseDir));
// weather icon settings // weather icon settings
writeFile(settings, QString("weathers"), writeFile(settings, "weathers", QString("%1/weather/awesomewidgets-extweather-ids.json").arg(m_baseDir));
QString("%1/weather/awesomewidgets-extweather-ids.json") settings.endGroup();
.arg(m_baseDir));
settings.beginGroup("ini");
// formatter settings // formatter settings
writeFile(settings, QString("formatters"), writeFile(settings, "formatters", QString("%1/formatters/formatters.ini").arg(m_baseDir));
QString("%1/formatters/formatters.ini").arg(m_baseDir)); // custom keys settings
writeFile(settings, "custom", QString("%1/custom.ini").arg(m_baseDir));
settings.endGroup(); settings.endGroup();
} }
// plasmoid configuration // plasmoid configuration
if (importPlasmoid) { if (_importPlasmoid) {
settings.beginGroup(QString("plasmoid")); settings.beginGroup("plasmoid");
for (auto key : settings.childKeys()) for (auto &key : settings.childKeys())
configuration[key] = settings.value(key); configuration[key] = settings.value(key);
settings.endGroup(); settings.endGroup();
} }
@ -171,34 +161,23 @@ QVariantMap AWConfigHelper::importConfiguration(const QString fileName,
} }
QVariantMap AWConfigHelper::readDataEngineConfiguration() const QVariantMap AWConfigHelper::readDataEngineConfiguration()
{ {
QString fileName QString fileName = QStandardPaths::locate(QStandardPaths::ConfigLocation, "plasma-dataengine-extsysmon.conf");
= QStandardPaths::locate(QStandardPaths::ConfigLocation,
QString("plasma-dataengine-extsysmon.conf"));
qCInfo(LOG_AW) << "Configuration file" << fileName; qCInfo(LOG_AW) << "Configuration file" << fileName;
QSettings settings(fileName, QSettings::IniFormat); QSettings settings(fileName, QSettings::IniFormat);
QVariantMap configuration; QVariantMap configuration;
settings.beginGroup(QString("Configuration")); settings.beginGroup("Configuration");
configuration[QString("ACPIPATH")] = settings.value( configuration["ACPIPATH"] = settings.value("ACPIPATH", "/sys/class/power_supply/");
QString("ACPIPATH"), QString("/sys/class/power_supply/")); configuration["GPUDEV"] = settings.value("GPUDEV", "auto");
configuration[QString("GPUDEV")] configuration["HDDDEV"] = settings.value("HDDDEV", "all");
= settings.value(QString("GPUDEV"), QString("auto")); configuration["HDDTEMPCMD"] = settings.value("HDDTEMPCMD", "sudo smartctl -a");
configuration[QString("HDDDEV")] configuration["MPDADDRESS"] = settings.value("MPDADDRESS", "localhost");
= settings.value(QString("HDDDEV"), QString("all")); configuration["MPDPORT"] = settings.value("MPDPORT", "6600");
configuration[QString("HDDTEMPCMD")] configuration["MPRIS"] = settings.value("MPRIS", "auto");
= settings.value(QString("HDDTEMPCMD"), QString("sudo smartctl -a")); configuration["PLAYER"] = settings.value("PLAYER", "mpris");
configuration[QString("MPDADDRESS")] configuration["PLAYERSYMBOLS"] = settings.value("PLAYERSYMBOLS", "10");
= settings.value(QString("MPDADDRESS"), QString("localhost"));
configuration[QString("MPDPORT")]
= settings.value(QString("MPDPORT"), QString("6600"));
configuration[QString("MPRIS")]
= settings.value(QString("MPRIS"), QString("auto"));
configuration[QString("PLAYER")]
= settings.value(QString("PLAYER"), QString("mpris"));
configuration[QString("PLAYERSYMBOLS")]
= settings.value(QString("PLAYERSYMBOLS"), QString("10"));
settings.endGroup(); settings.endGroup();
qCInfo(LOG_AW) << "Configuration" << configuration; qCInfo(LOG_AW) << "Configuration" << configuration;
@ -207,30 +186,25 @@ QVariantMap AWConfigHelper::readDataEngineConfiguration() const
} }
bool AWConfigHelper::writeDataEngineConfiguration( bool AWConfigHelper::writeDataEngineConfiguration(const QVariantMap &_configuration)
const QVariantMap configuration) const
{ {
qCDebug(LOG_AW) << "Configuration" << configuration; qCDebug(LOG_AW) << "Configuration" << _configuration;
QString fileName QString fileName = QString("%1/plasma-dataengine-extsysmon.conf")
= QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) .arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation));
+ QString("/plasma-dataengine-extsysmon.conf");
QSettings settings(fileName, QSettings::IniFormat); QSettings settings(fileName, QSettings::IniFormat);
qCInfo(LOG_AW) << "Configuration file" << settings.fileName(); qCInfo(LOG_AW) << "Configuration file" << settings.fileName();
settings.beginGroup(QString("Configuration")); settings.beginGroup("Configuration");
settings.setValue(QString("ACPIPATH"), configuration[QString("ACPIPATH")]); settings.setValue("ACPIPATH", _configuration["ACPIPATH"]);
settings.setValue(QString("GPUDEV"), configuration[QString("GPUDEV")]); settings.setValue("GPUDEV", _configuration["GPUDEV"]);
settings.setValue(QString("HDDDEV"), configuration[QString("HDDDEV")]); settings.setValue("HDDDEV", _configuration["HDDDEV"]);
settings.setValue(QString("HDDTEMPCMD"), settings.setValue("HDDTEMPCMD", _configuration["HDDTEMPCMD"]);
configuration[QString("HDDTEMPCMD")]); settings.setValue("MPDADDRESS", _configuration["MPDADDRESS"]);
settings.setValue(QString("MPDADDRESS"), settings.setValue("MPDPORT", _configuration["MPDPORT"]);
configuration[QString("MPDADDRESS")]); settings.setValue("MPRIS", _configuration["MPRIS"]);
settings.setValue(QString("MPDPORT"), configuration[QString("MPDPORT")]); settings.setValue("PLAYER", _configuration["PLAYER"]);
settings.setValue(QString("MPRIS"), configuration[QString("MPRIS")]); settings.setValue("PLAYERSYMBOLS", _configuration["PLAYERSYMBOLS"]);
settings.setValue(QString("PLAYER"), configuration[QString("PLAYER")]);
settings.setValue(QString("PLAYERSYMBOLS"),
configuration[QString("PLAYERSYMBOLS")]);
settings.endGroup(); settings.endGroup();
settings.sync(); settings.sync();
@ -239,91 +213,81 @@ bool AWConfigHelper::writeDataEngineConfiguration(
} }
void AWConfigHelper::copyConfigs(const QString localDir) const void AWConfigHelper::copyConfigs(const QString &_localDir)
{ {
qCDebug(LOG_AW) << "Local directory" << localDir; qCDebug(LOG_AW) << "Local directory" << _localDir;
QStringList dirs = QStandardPaths::locateAll( QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "awesomewidgets/configs",
QStandardPaths::GenericDataLocation, QString("awesomewidgets/configs"), QStandardPaths::LocateDirectory);
QStandardPaths::LocateDirectory); for (auto &dir : dirs) {
for (auto dir : dirs) { if (dir == _localDir)
if (dir == localDir)
continue; continue;
QStringList files = QDir(dir).entryList(QDir::Files); QStringList files = QDir(dir).entryList(QDir::Files);
for (auto source : files) { for (auto &source : files) {
QString destination = QString("%1/%2").arg(localDir).arg(source); QString destination = QString("%1/%2").arg(_localDir).arg(source);
bool status = QFile::copy(QString("%1/%2").arg(dir).arg(source), bool status = QFile::copy(QString("%1/%2").arg(dir).arg(source), destination);
destination); qCInfo(LOG_AW) << "File" << source << "has been copied to" << destination << "with status" << status;
qCInfo(LOG_AW) << "File" << source << "has been copied to"
<< destination << "with status" << status;
} }
} }
} }
void AWConfigHelper::copyExtensions(const QString item, const QString type, void AWConfigHelper::copyExtensions(const QString &_item, const QString &_type, QSettings &_settings,
QSettings &settings, const bool _inverse) const
const bool inverse) const
{ {
qCDebug(LOG_AW) << "Extension" << item << "has type" << type qCDebug(LOG_AW) << "Extension" << _item << "has type" << _type << "inverse copying" << _inverse;
<< "inverse copying" << inverse;
settings.beginGroup(item); _settings.beginGroup(_item);
QSettings itemSettings( QSettings itemSettings(QString("%1/%2/%3").arg(m_baseDir).arg(_type).arg(_item), QSettings::IniFormat);
QString("%1/%2/%3").arg(m_baseDir).arg(type).arg(item), itemSettings.beginGroup("Desktop Entry");
QSettings::IniFormat); if (_inverse)
itemSettings.beginGroup(QString("Desktop Entry")); copySettings(_settings, itemSettings);
if (inverse)
copySettings(settings, itemSettings);
else else
copySettings(itemSettings, settings); copySettings(itemSettings, _settings);
itemSettings.endGroup(); itemSettings.endGroup();
settings.endGroup(); _settings.endGroup();
if (inverse) if (_inverse)
itemSettings.sync(); itemSettings.sync();
} }
void AWConfigHelper::copySettings(QSettings &from, QSettings &to) const void AWConfigHelper::copySettings(QSettings &_from, QSettings &_to)
{ {
for (auto key : from.childKeys()) for (auto &key : _from.childKeys())
to.setValue(key, from.value(key)); _to.setValue(key, _from.value(key));
} }
void AWConfigHelper::readFile(QSettings &settings, const QString key, void AWConfigHelper::readFile(QSettings &_settings, const QString &_key, const QString &_fileName)
const QString fileName) const
{ {
qCDebug(LOG_AW) << "Key" << key << "from file" << fileName; qCDebug(LOG_AW) << "Key" << _key << "from file" << _fileName;
QFile file(fileName); QFile file(_fileName);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QString text = QString::fromUtf8(file.readAll()); QString text = QString::fromUtf8(file.readAll());
file.close(); file.close();
settings.setValue(key, text); _settings.setValue(_key, text);
} else { } else {
qCWarning(LOG_AW) << "Could not open" << file.fileName(); qCWarning(LOG_AW) << "Could not open to read" << file.fileName();
} }
} }
void AWConfigHelper::writeFile(QSettings &settings, const QString key, void AWConfigHelper::writeFile(QSettings &_settings, const QString &_key, const QString &_fileName)
const QString fileName) const
{ {
qCDebug(LOG_AW) << "Key" << key << "to file" << fileName; qCDebug(LOG_AW) << "Key" << _key << "to file" << _fileName;
if (!settings.contains(key)) if (!_settings.contains(_key))
return; return;
QFile file(fileName); QFile file(_fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&file); QTextStream out(&file);
out.setCodec("UTF-8"); out << _settings.value(_key).toString().toUtf8();
out << settings.value(key).toString().toUtf8();
out.flush(); out.flush();
file.close(); file.close();
} else { } else {
qCWarning(LOG_AW) << "Could not open" << file.fileName(); qCWarning(LOG_AW) << "Could not open to write" << file.fileName();
} }
} }

View File

@ -20,7 +20,6 @@
#define AWCONFIGHELPER_H #define AWCONFIGHELPER_H
#include <QObject> #include <QObject>
#include <QStandardPaths>
#include <QVariant> #include <QVariant>
@ -31,39 +30,27 @@ class AWConfigHelper : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit AWConfigHelper(QObject *parent = nullptr); explicit AWConfigHelper(QObject *_parent = nullptr);
virtual ~AWConfigHelper(); ~AWConfigHelper() override;
Q_INVOKABLE QString configurationDirectory() const; Q_INVOKABLE [[nodiscard]] static QString configurationDirectory();
Q_INVOKABLE bool dropCache() const; Q_INVOKABLE static bool dropCache();
Q_INVOKABLE bool exportConfiguration(const QObject *nativeConfig, Q_INVOKABLE bool exportConfiguration(QObject *_nativeConfig, const QString &_fileName) const;
const QString fileName) const; Q_INVOKABLE [[nodiscard]] QVariantMap importConfiguration(const QString &_fileName, bool _importPlasmoid,
Q_INVOKABLE QVariantMap importConfiguration(const QString fileName, bool _importExtensions, bool _importAdds) const;
const bool importPlasmoid,
const bool importExtensions,
const bool importAdds) const;
// dataengine // dataengine
Q_INVOKABLE QVariantMap readDataEngineConfiguration() const; Q_INVOKABLE static QVariantMap readDataEngineConfiguration();
Q_INVOKABLE bool Q_INVOKABLE static bool writeDataEngineConfiguration(const QVariantMap &_configuration);
writeDataEngineConfiguration(const QVariantMap configuration) const;
private: private:
// methods // methods
void copyConfigs(const QString localDir) const; static void copyConfigs(const QString &_localDir);
void copyExtensions(const QString item, const QString type, void copyExtensions(const QString &_item, const QString &_type, QSettings &_settings, bool _inverse) const;
QSettings &settings, const bool inverse) const; static void copySettings(QSettings &_from, QSettings &_to);
void copySettings(QSettings &from, QSettings &to) const; static void readFile(QSettings &_settings, const QString &_key, const QString &_fileName);
void readFile(QSettings &settings, const QString key, static void writeFile(QSettings &_settings, const QString &_key, const QString &_fileName);
const QString fileName) const;
void writeFile(QSettings &settings, const QString key,
const QString fileName) const;
// properties // properties
QString m_baseDir = QString("%1/awesomewidgets") QString m_baseDir;
.arg(QStandardPaths::writableLocation( QStringList m_dirs = {"desktops", "quotes", "scripts", "upgrade", "weather", "formatters"};
QStandardPaths::GenericDataLocation));
QStringList m_dirs = QStringList()
<< QString("desktops") << QString("quotes")
<< QString("scripts") << QString("upgrade")
<< QString("weather") << QString("formatters");
}; };

View File

@ -15,28 +15,23 @@
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/ ***************************************************************************/
#include "awformatterconfigfactory.h" #include "awcustomkeysconfig.h"
#include "awcustomkeyshelper.h"
#include "awdebug.h" #include "awdebug.h"
#include "awformatterconfig.h"
AWFormatterConfigFactory::AWFormatterConfigFactory(QObject *parent) AWCustomKeysConfig::AWCustomKeysConfig(QWidget *_parent, const QStringList &_keys)
: QObject(parent) : AWAbstractPairConfig(_parent, false, _keys)
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
setEditable(true, false);
initHelper<AWCustomKeysHelper>();
}
AWCustomKeysConfig::~AWCustomKeysConfig()
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
} }
AWFormatterConfigFactory::~AWFormatterConfigFactory()
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
}
void AWFormatterConfigFactory::showDialog(const QStringList keys)
{
AWFormatterConfig *config = new AWFormatterConfig(nullptr, keys);
config->showDialog();
config->deleteLater();
}

View File

@ -16,23 +16,20 @@
***************************************************************************/ ***************************************************************************/
#ifndef AWFORMATTERCONFIGFACTORY_H #ifndef AWCUSTOMKEYSCONFIG_H
#define AWFORMATTERCONFIGFACTORY_H #define AWCUSTOMKEYSCONFIG_H
#include <QObject> #include "awabstractpairconfig.h"
class AWFormatterConfigFactory : public QObject class AWCustomKeysConfig : public AWAbstractPairConfig
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AWFormatterConfigFactory(QObject *parent = nullptr); explicit AWCustomKeysConfig(QWidget *_parent = nullptr, const QStringList &_keys = QStringList());
virtual ~AWFormatterConfigFactory(); ~AWCustomKeysConfig() override;
Q_INVOKABLE void showDialog(const QStringList keys);
private:
}; };
#endif /* AWFORMATTERCONFIGFACTORY_H */ #endif /* AWCUSTOMKEYSCONFIG_H */

View File

@ -0,0 +1,78 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#include "awcustomkeyshelper.h"
#include <QSet>
#include "awdebug.h"
AWCustomKeysHelper::AWCustomKeysHelper(QObject *_parent)
: QObject(_parent)
, AWAbstractPairHelper("awesomewidgets/custom.ini", "Custom")
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
}
AWCustomKeysHelper::~AWCustomKeysHelper()
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
}
QString AWCustomKeysHelper::source(const QString &_key) const
{
qCDebug(LOG_AW) << "Get source by key" << _key;
return pairs()[_key];
}
QStringList AWCustomKeysHelper::sources() const
{
return valuesSet().values();
}
QStringList AWCustomKeysHelper::refinedSources() const
{
auto allSources = valuesSet();
QSet<QString> output;
while (output != allSources) {
output.clear();
for (auto &src : allSources)
output.insert(pairs().contains(src) ? source(src) : src);
allSources = output;
}
return output.values();
}
QStringList AWCustomKeysHelper::leftKeys()
{
return keys();
}
QStringList AWCustomKeysHelper::rightKeys()
{
return {};
}

View File

@ -0,0 +1,47 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#ifndef AWCUSTOMKEYSHELPER_H
#define AWCUSTOMKEYSHELPER_H
#include <QObject>
#include "awabstractpairhelper.h"
class AWCustomKeysHelper : public QObject, public AWAbstractPairHelper
{
Q_OBJECT
public:
explicit AWCustomKeysHelper(QObject *_parent = nullptr);
~AWCustomKeysHelper() override;
// get
[[nodiscard]] QString source(const QString &_key) const;
[[nodiscard]] QStringList sources() const;
[[nodiscard]] QStringList refinedSources() const;
// configuration related
void editPairs() override{};
QStringList leftKeys() override;
QStringList rightKeys() override;
private:
};
#endif /* AWCUSTOMKEYSHELPER_H */

View File

@ -22,8 +22,6 @@
#include <QBuffer> #include <QBuffer>
#include <QGraphicsScene> #include <QGraphicsScene>
#include <QGraphicsView> #include <QGraphicsView>
#include <QPixmap>
#include <QtConcurrent/QtConcurrent>
#include <cmath> #include <cmath>
@ -31,22 +29,20 @@
#include "awdebug.h" #include "awdebug.h"
AWDataAggregator::AWDataAggregator(QObject *parent) AWDataAggregator::AWDataAggregator(QObject *_parent)
: QObject(parent) : QObject(_parent)
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
m_boundaries[QString("cpuTooltip")] = 100.0; m_boundaries["cpuTooltip"] = 100.0;
m_boundaries[QString("cpuclTooltip")] = 4000.0; m_boundaries["cpuclTooltip"] = 4000.0;
m_boundaries[QString("memTooltip")] = 100.0; m_boundaries["memTooltip"] = 100.0;
m_boundaries[QString("swapTooltip")] = 100.0; m_boundaries["swapTooltip"] = 100.0;
m_boundaries[QString("downkbTooltip")] = 1.0; m_boundaries["downkbTooltip"] = 1.0;
m_boundaries[QString("upkbTooltip")] = 1.0; m_boundaries["upkbTooltip"] = 1.0;
m_boundaries[QString("batTooltip")] = 100.0; m_boundaries["batTooltip"] = 100.0;
initScene(); initScene();
connect(this, SIGNAL(updateData(const QVariantHash &)), this,
SLOT(dataUpdate(const QVariantHash &)));
} }
@ -58,68 +54,56 @@ AWDataAggregator::~AWDataAggregator()
} }
QList<float> AWDataAggregator::getData(const QString key) const QString AWDataAggregator::htmlImage(const QPixmap &_source)
{
qCDebug(LOG_AW) << "Key" << key;
return m_values[QString("%1Tooltip").arg(key)];
}
QString AWDataAggregator::htmlImage(const QPixmap &source) const
{ {
QByteArray byteArray; QByteArray byteArray;
QBuffer buffer(&byteArray); QBuffer buffer(&byteArray);
source.save(&buffer, "PNG"); _source.save(&buffer, "PNG");
return byteArray.isEmpty() return byteArray.isEmpty() ? ""
? QString() : QString("<img src=\"data:image/png;base64,%1\"/>").arg(QString(byteArray.toBase64()));
: QString("<img src=\"data:image/png;base64,%1\"/>")
.arg(QString(byteArray.toBase64()));
} }
void AWDataAggregator::setParameters(QVariantMap settings) void AWDataAggregator::setParameters(const QVariantMap &_settings)
{ {
qCDebug(LOG_AW) << "Settings" << settings; qCDebug(LOG_AW) << "Settings" << _settings;
// cast from QVariantMap to QVariantHash without data lost // cast from QVariantMap to QVariantHash without data lost
m_configuration = qvariant_cast<QVariantHash>(settings); m_configuration = qvariant_cast<QVariantHash>(_settings);
m_enablePopup = m_configuration[QString("notify")].toBool(); m_enablePopup = m_configuration["notify"].toBool();
m_counts = 0; m_counts = 0;
m_counts += m_configuration[QString("cpuTooltip")].toInt(); m_counts += m_configuration["cpuTooltip"].toInt();
m_counts += m_configuration[QString("cpuclTooltip")].toInt(); m_counts += m_configuration["cpuclTooltip"].toInt();
m_counts += m_configuration[QString("memTooltip")].toInt(); m_counts += m_configuration["memTooltip"].toInt();
m_counts += m_configuration[QString("swapTooltip")].toInt(); m_counts += m_configuration["swapTooltip"].toInt();
m_counts += m_configuration[QString("downkbTooltip")].toInt(); m_counts += m_configuration["downkbTooltip"].toInt();
m_counts += m_configuration[QString("batTooltip")].toInt(); m_counts += m_configuration["batTooltip"].toInt();
// resize tooltip image // resize tooltip image
m_toolTipView->resize(100 * m_counts, 105); m_toolTipView->resize(100 * m_counts, 105);
requiredKeys.clear(); requiredKeys.clear();
if (m_configuration[QString("cpuTooltip")].toBool()) if (m_configuration["cpuTooltip"].toBool())
requiredKeys.append(QString("cpuTooltip")); requiredKeys.append("cpuTooltip");
if (m_configuration[QString("cpuclTooltip")].toBool()) if (m_configuration["cpuclTooltip"].toBool())
requiredKeys.append(QString("cpuclTooltip")); requiredKeys.append("cpuclTooltip");
if (m_configuration[QString("memTooltip")].toBool()) if (m_configuration["memTooltip"].toBool())
requiredKeys.append(QString("memTooltip")); requiredKeys.append("memTooltip");
if (m_configuration[QString("swapTooltip")].toBool()) if (m_configuration["swapTooltip"].toBool())
requiredKeys.append(QString("swapTooltip")); requiredKeys.append("swapTooltip");
if (m_configuration[QString("downkbTooltip")].toBool()) if (m_configuration["downkbTooltip"].toBool())
requiredKeys.append(QString("downkbTooltip")); requiredKeys.append("downkbTooltip");
if (m_configuration[QString("upkbTooltip")].toBool()) if (m_configuration["upkbTooltip"].toBool())
requiredKeys.append(QString("upkbTooltip")); requiredKeys.append("upkbTooltip");
if (m_configuration[QString("batTooltip")].toBool()) if (m_configuration["batTooltip"].toBool())
requiredKeys.append(QString("batTooltip")); requiredKeys.append("batTooltip");
// background // background
m_toolTipScene->setBackgroundBrush( m_toolTipScene->setBackgroundBrush(m_configuration["useTooltipBackground"].toBool()
m_configuration[QString("useTooltipBackground")].toBool() ? QBrush(QColor(m_configuration["tooltipBackground"].toString()))
? QBrush(QColor( : QBrush(Qt::NoBrush));
m_configuration[QString("tooltipBackground")].toString()))
: QBrush(Qt::NoBrush));
} }
@ -129,37 +113,32 @@ QPixmap AWDataAggregator::tooltipImage()
m_toolTipScene->clear(); m_toolTipScene->clear();
QPen pen; QPen pen;
bool down = false; bool down = false;
for (auto key : requiredKeys) { for (auto &key : requiredKeys) {
// create frame // create frame
float normX = 100.0f / static_cast<float>(m_values[key].count()); float normX = 100.0f / static_cast<float>(m_values[key].count());
float normY = 100.0f / (1.5f * m_boundaries[key]); float normY = 100.0f / (1.5f * m_boundaries[key]);
float shift = requiredKeys.indexOf(key) * 100.0f; float shift = static_cast<float>(requiredKeys.indexOf(key)) * 100.0f;
if (down) if (down)
shift -= 100.0; shift -= 100.0;
// apply pen color // apply pen color
if (key != QString("batTooltip")) if (key != "batTooltip")
pen.setColor(QColor( pen.setColor(QColor(m_configuration[QString("%1Color").arg(key)].toString()));
m_configuration[QString("%1Color").arg(key)].toString()));
// paint data inside frame // paint data inside frame
for (int j = 0; j < m_values[key].count() - 1; j++) { for (int j = 0; j < m_values[key].count() - 1; j++) {
// some magic here // some magic here
float x1 = j * normX + shift; float x1 = j * normX + shift;
float y1 = -fabs(m_values[key].at(j)) * normY + 5.0f; float y1 = -std::fabs(m_values[key].at(j)) * normY + 5.0f;
float x2 = (j + 1) * normX + shift; float x2 = (j + 1) * normX + shift;
float y2 = -fabs(m_values[key].at(j + 1)) * normY + 5.0f; float y2 = -std::fabs(m_values[key].at(j + 1)) * normY + 5.0f;
if (key == QString("batTooltip")) { if (key == "batTooltip") {
if (m_values[key].at(j + 1) > 0) if (m_values[key].at(j + 1) > 0)
pen.setColor( pen.setColor(QColor(m_configuration["batTooltipColor"].toString()));
QColor(m_configuration[QString("batTooltipColor")]
.toString()));
else else
pen.setColor( pen.setColor(QColor(m_configuration["batInTooltipColor"].toString()));
QColor(m_configuration[QString("batInTooltipColor")]
.toString()));
} }
m_toolTipScene->addLine(x1, y1, x2, y2, pen); m_toolTipScene->addLine(x1, y1, x2, y2, pen);
} }
if (key == QString("downkbTooltip")) if (key == "downkbTooltip")
down = true; down = true;
} }
@ -167,43 +146,36 @@ QPixmap AWDataAggregator::tooltipImage()
} }
void AWDataAggregator::dataUpdate(const QVariantHash &values) void AWDataAggregator::dataUpdate(const QVariantHash &_values)
{ {
// do not log these arguments // do not log these arguments
setData(values); setData(_values);
emit(toolTipPainted(htmlImage(tooltipImage()))); emit(toolTipPainted(htmlImage(tooltipImage())));
} }
void AWDataAggregator::checkValue(const QString source, const float value, void AWDataAggregator::checkValue(const QString &_source, const float _value, const float _extremum) const
const float extremum) const
{ {
qCDebug(LOG_AW) << "Notification source" << source << "with value" << value qCDebug(LOG_AW) << "Notification source" << _source << "with value" << _value << "called with extremum"
<< "called with extremum" << extremum; << _extremum;
if (value >= 0.0) { if (_value >= 0.0) {
if ((m_enablePopup) && (value > extremum) if ((m_enablePopup) && (_value > _extremum) && (m_values[_source].last() < _extremum))
&& (m_values[source].last() < extremum)) return AWActions::sendNotification("event", notificationText(_source, _value));
return AWActions::sendNotification(QString("event"),
notificationText(source, value));
} else { } else {
if ((m_enablePopup) && (value < extremum) if ((m_enablePopup) && (_value < _extremum) && (m_values[_source].last() > _extremum))
&& (m_values[source].last() > extremum)) return AWActions::sendNotification("event", notificationText(_source, _value));
return AWActions::sendNotification(QString("event"),
notificationText(source, value));
} }
} }
void AWDataAggregator::checkValue(const QString source, const QString current, void AWDataAggregator::checkValue(const QString &_source, const QString &_current, const QString &_received) const
const QString received) const
{ {
qCDebug(LOG_AW) << "Notification source" << source << "with current value" qCDebug(LOG_AW) << "Notification source" << _source << "with current value" << _current << "and received one"
<< current << "and received one" << received; << _received;
if ((m_enablePopup) && (current != received) && (!received.isEmpty())) if ((m_enablePopup) && (_current != _received) && (!_received.isEmpty()))
return AWActions::sendNotification(QString("event"), return AWActions::sendNotification("event", notificationText(_source, _received));
notificationText(source, received));
} }
@ -211,7 +183,7 @@ void AWDataAggregator::initScene()
{ {
m_toolTipScene = new QGraphicsScene(nullptr); m_toolTipScene = new QGraphicsScene(nullptr);
m_toolTipView = new QGraphicsView(m_toolTipScene); m_toolTipView = new QGraphicsView(m_toolTipScene);
m_toolTipView->setStyleSheet(QString("background: transparent")); m_toolTipView->setStyleSheet("background: transparent");
m_toolTipView->setContentsMargins(0, 0, 0, 0); m_toolTipView->setContentsMargins(0, 0, 0, 0);
m_toolTipView->setFrameShape(QFrame::NoFrame); m_toolTipView->setFrameShape(QFrame::NoFrame);
m_toolTipView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_toolTipView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
@ -219,105 +191,90 @@ void AWDataAggregator::initScene()
} }
QString AWDataAggregator::notificationText(const QString source, QString AWDataAggregator::notificationText(const QString &_source, const float _value)
const float value) const
{ {
qCDebug(LOG_AW) << "Notification source" << source << "with value" << value; qCDebug(LOG_AW) << "Notification source" << _source << "with value" << _value;
QString output; QString output;
if (source == QString("batTooltip")) if (_source == "batTooltip")
output = value > 0.0 ? i18n("AC online") : i18n("AC offline"); output = _value > 0.0 ? i18n("AC online") : i18n("AC offline");
else if (source == QString("cpuTooltip")) else if (_source == "cpuTooltip")
output = i18n("High CPU load"); output = i18n("High CPU load");
else if (source == QString("memTooltip")) else if (_source == "memTooltip")
output = i18n("High memory usage"); output = i18n("High memory usage");
else if (source == QString("swapTooltip")) else if (_source == "swapTooltip")
output = i18n("Swap is used"); output = i18n("Swap is used");
else if (source == QString("gpu")) else if (_source == "gpu")
output = i18n("High GPU load"); output = i18n("High GPU load");
return output; return output;
} }
QString AWDataAggregator::notificationText(const QString source, QString AWDataAggregator::notificationText(const QString &_source, const QString &_value)
const QString value) const
{ {
qCDebug(LOG_AW) << "Notification source" << source << "with value" << value; qCDebug(LOG_AW) << "Notification source" << _source << "with value" << _value;
QString output; QString output;
if (source == QString("netdev")) if (_source == "netdev")
output = i18n("Network device has been changed to %1", value); output = i18n("Network device has been changed to %1", _value);
return output; return output;
} }
void AWDataAggregator::setData(const QVariantHash &values) void AWDataAggregator::setData(const QVariantHash &_values)
{ {
// do not log these arguments // do not log these arguments
// battery update requires info is AC online or not // battery update requires info is AC online or not
setData(values[QString("ac")].toString() setData(_values["ac"].toString() == m_configuration["acOnline"], "batTooltip", _values["bat"].toFloat());
== m_configuration[QString("acOnline")],
QString("batTooltip"), values[QString("bat")].toFloat());
// usual case // usual case
setData(QString("cpuTooltip"), values[QString("cpu")].toFloat(), 90.0); setData("cpuTooltip", _values["cpu"].toFloat(), 90.0);
setData(QString("cpuclTooltip"), values[QString("cpucl")].toFloat()); setData("cpuclTooltip", _values["cpucl"].toFloat());
setData(QString("memTooltip"), values[QString("mem")].toFloat(), 80.0); setData("memTooltip", _values["mem"].toFloat(), 80.0);
setData(QString("swapTooltip"), values[QString("swap")].toFloat(), 0.0); setData("swapTooltip", _values["swap"].toFloat(), 0.0);
setData(QString("downkbTooltip"), values[QString("downkb")].toFloat()); setData("downkbTooltip", _values["downkb"].toFloat());
setData(QString("upkbTooltip"), values[QString("upkb")].toFloat()); setData("upkbTooltip", _values["upkb"].toFloat());
// additional check for network device // additional check for network device
[this](const QString value) { [this](const QString &value) {
checkValue(QString("netdev"), m_currentNetworkDevice, value); checkValue("netdev", m_currentNetworkDevice, value);
m_currentNetworkDevice = value; m_currentNetworkDevice = value;
}(values[QString("netdev")].toString()); }(_values["netdev"].toString());
// additional check for GPU load // additional check for GPU load
[this](const float value) { [this](const float value) { checkValue("gpu", value, 90.0); }(_values["gpu"].toFloat());
checkValue(QString("gpu"), value, 90.0);
m_currentGPULoad = value;
}(values[QString("gpu")].toFloat());
} }
void AWDataAggregator::setData(const QString &source, float value, void AWDataAggregator::setData(const QString &_source, float _value, const float _extremum)
const float extremum)
{ {
qCDebug(LOG_AW) << "Source" << source << "to value" << value qCDebug(LOG_AW) << "Source" << _source << "to value" << _value << "with extremum" << _extremum;
<< "with extremum" << extremum;
if (m_values[source].count() == 0) if (m_values[_source].count() == 0)
m_values[source].append(0.0); m_values[_source].append(0.0);
else if (m_values[source].count() else if (m_values[_source].count() > m_configuration["tooltipNumber"].toInt())
> m_configuration[QString("tooltipNumber")].toInt()) m_values[_source].removeFirst();
m_values[source].removeFirst(); if (std::isnan(_value))
if (std::isnan(value)) _value = 0.0;
value = 0.0;
// notifications // notifications
checkValue(source, value, extremum); checkValue(_source, _value, _extremum);
m_values[source].append(value); m_values[_source].append(_value);
if (source == QString("downkbTooltip")) { if (_source == "downkbTooltip") {
QList<float> netValues = m_values[QString("downkbTooltip")] QList<float> netValues = m_values["downkbTooltip"] + m_values["upkbTooltip"];
+ m_values[QString("upkbTooltip")];
// to avoid inf value of normY // to avoid inf value of normY
netValues << 1.0; netValues << 1.0;
m_boundaries[QString("downkbTooltip")] m_boundaries["downkbTooltip"] = 1.2f * *std::max_element(netValues.cbegin(), netValues.cend());
= 1.2f * *std::max_element(netValues.cbegin(), netValues.cend()); m_boundaries["upkbTooltip"] = m_boundaries["downkbTooltip"];
m_boundaries[QString("upkbTooltip")]
= m_boundaries[QString("downkbTooltip")];
} }
} }
void AWDataAggregator::setData(const bool dontInvert, const QString &source, void AWDataAggregator::setData(const bool _dontInvert, const QString &_source, float _value)
float value)
{ {
qCDebug(LOG_AW) << "Do not invert" << dontInvert << "value" << value qCDebug(LOG_AW) << "Do not invert" << _dontInvert << "value" << _value << "for source" << _source;
<< "for source" << source;
// invert values for different battery colours // invert values for different battery colours
value = dontInvert ? value : -value; _value = _dontInvert ? _value : -_value;
return setData(source, value, 0.0); return setData(_source, _value, 0.0);
} }

View File

@ -33,42 +33,36 @@ class AWDataAggregator : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit AWDataAggregator(QObject *parent = nullptr); explicit AWDataAggregator(QObject *_parent = nullptr);
virtual ~AWDataAggregator(); ~AWDataAggregator() override;
QList<float> getData(const QString key) const; static QString htmlImage(const QPixmap &_source);
QString htmlImage(const QPixmap &source) const; void setParameters(const QVariantMap &_settings);
void setParameters(QVariantMap settings);
QPixmap tooltipImage(); QPixmap tooltipImage();
signals: public slots:
void updateData(const QVariantHash &values); void dataUpdate(const QVariantHash &_values);
void toolTipPainted(const QString image) const;
private slots: signals:
void dataUpdate(const QVariantHash &values); void toolTipPainted(const QString &_image) const;
private: private:
// ui // ui
QGraphicsScene *m_toolTipScene = nullptr; QGraphicsScene *m_toolTipScene = nullptr;
QGraphicsView *m_toolTipView = nullptr; QGraphicsView *m_toolTipView = nullptr;
void checkValue(const QString source, const float value, void checkValue(const QString &_source, float _value, float _extremum) const;
const float extremum) const; void checkValue(const QString &_source, const QString &_current, const QString &_received) const;
void checkValue(const QString source, const QString current,
const QString received) const;
void initScene(); void initScene();
QString notificationText(const QString source, const float value) const; static QString notificationText(const QString &_source, float _value);
QString notificationText(const QString source, const QString value) const; static QString notificationText(const QString &_source, const QString &_value);
// main method // main method
void setData(const QVariantHash &values); void setData(const QVariantHash &_values);
void setData(const QString &source, float value, void setData(const QString &_source, float _value, float _extremum = -1.0f);
const float extremum = -1.0f);
// different signature for battery device // different signature for battery device
void setData(const bool dontInvert, const QString &source, float value); void setData(bool _dontInvert, const QString &_source, float _value);
// variables // variables
int m_counts = 0; int m_counts = 0;
QVariantHash m_configuration; QVariantHash m_configuration;
float m_currentGPULoad = 0.0; QString m_currentNetworkDevice = "lo";
QString m_currentNetworkDevice = QString("lo");
QHash<QString, float> m_boundaries; QHash<QString, float> m_boundaries;
QHash<QString, QList<float>> m_values; QHash<QString, QList<float>> m_values;
bool m_enablePopup = false; bool m_enablePopup = false;

View File

@ -17,14 +17,35 @@
#include "awdataengineaggregator.h" #include "awdataengineaggregator.h"
#include <ksysguard/formatter/Unit.h>
#include <ksysguard/systemstats/DBusInterface.h>
#include <QDBusConnection>
#include "awdebug.h" #include "awdebug.h"
#include "awkeys.h"
AWDataEngineAggregator::AWDataEngineAggregator(QObject *parent) AWDataEngineAggregator::AWDataEngineAggregator(QObject *_parent)
: QObject(parent) : QObject(_parent)
, m_interface(new KSysGuard::SystemStats::DBusInterface())
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
qDBusRegisterMetaType<KSysGuard::SensorData>();
qDBusRegisterMetaType<KSysGuard::SensorInfo>();
qDBusRegisterMetaType<KSysGuard::SensorDataList>();
qDBusRegisterMetaType<QHash<QString, KSysGuard::SensorInfo>>();
connect(m_interface, &KSysGuard::SystemStats::DBusInterface::newSensorData, this,
&AWDataEngineAggregator::updateData);
connect(m_interface, &KSysGuard::SystemStats::DBusInterface::sensorMetaDataChanged, this,
&AWDataEngineAggregator::updateSensors);
connect(m_interface, &KSysGuard::SystemStats::DBusInterface::sensorAdded, this,
&AWDataEngineAggregator::sensorAdded);
connect(m_interface, &KSysGuard::SystemStats::DBusInterface::sensorRemoved, this,
&AWDataEngineAggregator::sensorRemoved);
loadSources();
} }
@ -32,70 +53,97 @@ AWDataEngineAggregator::~AWDataEngineAggregator()
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
clear(); disconnectSources();
m_interface->deleteLater();
} }
void AWDataEngineAggregator::clear() void AWDataEngineAggregator::connectSources()
{ {
// disconnect sources first auto keys = m_sensors.keys();
disconnectSources(); auto newKeys = QSet(keys.cbegin(), keys.cend()) - m_subscribed;
m_dataEngines.clear();
delete m_consumer; m_interface->subscribe(newKeys.values()).waitForFinished();
m_subscribed.unite(newKeys);
} }
void AWDataEngineAggregator::disconnectSources() void AWDataEngineAggregator::disconnectSources()
{ {
for (auto dataengine : m_dataEngines.values()) m_interface->unsubscribe(m_subscribed.values()).waitForFinished();
for (auto source : dataengine->sources()) m_subscribed.clear();
dataengine->disconnectSource(source, parent());
} }
void AWDataEngineAggregator::initDataEngines(const int interval) bool AWDataEngineAggregator::isValidSensor(const KSysGuard::SensorInfo &_sensor)
{ {
qCDebug(LOG_AW) << "Init dataengines with interval" << interval; return _sensor.unit != KSysGuard::UnitInvalid;
m_consumer = new Plasma::DataEngineConsumer();
m_dataEngines[QString("systemmonitor")]
= m_consumer->dataEngine(QString("systemmonitor"));
m_dataEngines[QString("extsysmon")]
= m_consumer->dataEngine(QString("extsysmon"));
m_dataEngines[QString("time")] = m_consumer->dataEngine(QString("time"));
// additional method required by systemmonitor structure
connect(m_dataEngines[QString("systemmonitor")],
&Plasma::DataEngine::sourceAdded,
[this, interval](const QString source) {
emit(deviceAdded(source));
m_dataEngines[QString("systemmonitor")]->connectSource(
source, parent(), interval);
});
return reconnectSources(interval);
} }
void AWDataEngineAggregator::dropSource(const QString source) void AWDataEngineAggregator::loadSources()
{ {
qCDebug(LOG_AW) << "Source" << source; auto response = m_interface->allSensors();
response.waitForFinished();
// HACK there is no possibility to check to which dataengine source auto sensors = response.value();
// connected we will try to disconnect it from systemmonitor and extsysmon updateSensors(sensors);
m_dataEngines[QString("systemmonitor")]->disconnectSource(source, parent()); connectSources();
m_dataEngines[QString("extsysmon")]->disconnectSource(source, parent());
m_dataEngines[QString("time")]->disconnectSource(source, parent());
} }
void AWDataEngineAggregator::reconnectSources(const int interval) void AWDataEngineAggregator::dropSource(const QString &_source)
{ {
qCDebug(LOG_AW) << "Reconnect sources with interval" << interval; qCDebug(LOG_AW) << "Disconnect sensor" << _source;
m_dataEngines[QString("systemmonitor")]->connectAllSources(parent(), if (m_subscribed.contains(_source)) {
interval); m_interface->unsubscribe({_source}).waitForFinished();
m_dataEngines[QString("extsysmon")]->connectAllSources(parent(), interval); m_subscribed.remove(_source);
m_dataEngines[QString("time")]->connectSource(QString("Local"), parent(), }
1000); }
void AWDataEngineAggregator::sensorAdded(const QString &_sensor)
{
qCDebug(LOG_AW) << "New sensor added" << _sensor;
// check if sensor is actually valid
auto response = m_interface->sensors({_sensor});
response.waitForFinished();
auto info = response.value().value(_sensor);
if (!isValidSensor(info))
return;
m_sensors[_sensor] = info;
dropSource(_sensor); // force reconnect
if (!m_subscribed.contains(_sensor)) {
m_interface->subscribe({_sensor}).waitForFinished();
m_subscribed.insert(_sensor);
}
}
void AWDataEngineAggregator::sensorRemoved(const QString &_sensor)
{
qCDebug(LOG_AW) << "Sensor" << _sensor << "has been removed";
m_sensors.remove(_sensor);
dropSource(_sensor);
}
void AWDataEngineAggregator::updateData(KSysGuard::SensorDataList _data)
{
emit(dataUpdated(m_sensors, _data));
}
void AWDataEngineAggregator::updateSensors(const QHash<QString, KSysGuard::SensorInfo> &_sensors)
{
for (auto sensor = _sensors.cbegin(); sensor != _sensors.cend(); ++sensor) {
if (!isValidSensor(sensor.value()))
continue;
m_sensors.insert(sensor.key(), sensor.value());
}
} }

View File

@ -15,38 +15,45 @@
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/ ***************************************************************************/
#pragma once
#ifndef AWDATAENGINEAGGREGATOR_H #include <ksysguard/systemstats/SensorInfo.h>
#define AWDATAENGINEAGGREGATOR_H
#include <Plasma/DataEngine>
#include <Plasma/DataEngineConsumer>
#include <QHash>
#include <QObject> #include <QObject>
#include <QSet>
namespace KSysGuard::SystemStats
{
class DBusInterface;
}
class AWDataEngineAggregator : public QObject class AWDataEngineAggregator : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AWDataEngineAggregator(QObject *parent = nullptr); explicit AWDataEngineAggregator(QObject *_parent = nullptr);
virtual ~AWDataEngineAggregator(); ~AWDataEngineAggregator() override;
void clear(); void connectSources();
void disconnectSources(); void disconnectSources();
void initDataEngines(const int interval); [[nodiscard]] static bool isValidSensor(const KSysGuard::SensorInfo &_sensor);
void loadSources();
signals: signals:
void deviceAdded(const QString &source); void dataUpdated(const QHash<QString, KSysGuard::SensorInfo> &_sensors, const KSysGuard::SensorDataList &_data);
void deviceAdded(const QString &_source);
public slots: public slots:
void dropSource(const QString source); void dropSource(const QString &_source);
void reconnectSources(const int interval); void sensorAdded(const QString &_sensor);
void sensorRemoved(const QString &_sensor);
void updateData(KSysGuard::SensorDataList _data);
void updateSensors(const QHash<QString, KSysGuard::SensorInfo> &_sensors);
private: private:
Plasma::DataEngineConsumer *m_consumer = nullptr; KSysGuard::SystemStats::DBusInterface *m_interface = nullptr;
QHash<QString, Plasma::DataEngine *> m_dataEngines; QHash<QString, KSysGuard::SensorInfo> m_sensors;
QSet<QString> m_subscribed;
}; };
#endif /* AWDATAENGINEAGGREGATOR_H */

View File

@ -0,0 +1,448 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#include "awdataenginemapper.h"
#include <QRegularExpression>
#include "awdebug.h"
#include "awformatterhelper.h"
AWDataEngineMapper::AWDataEngineMapper(QObject *_parent, AWFormatterHelper *_custom)
: QObject(_parent)
, m_customFormatters(_custom)
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
// default formatters
// memory
m_formatter["mem"] = AWKeysAggregator::FormatterType::Float;
m_formatter["memtotmb"] = AWKeysAggregator::FormatterType::MemMBFormat;
m_formatter["memtotgb"] = AWKeysAggregator::FormatterType::MemGBFormat;
// network
m_formatter["down"] = AWKeysAggregator::FormatterType::NetSmartFormat;
m_formatter["downkb"] = AWKeysAggregator::FormatterType::Integer;
m_formatter["downtot"] = AWKeysAggregator::FormatterType::MemMBFormat;
m_formatter["downtotkb"] = AWKeysAggregator::FormatterType::Integer;
m_formatter["downunits"] = AWKeysAggregator::FormatterType::NetSmartUnits;
m_formatter["up"] = AWKeysAggregator::FormatterType::NetSmartFormat;
m_formatter["upkb"] = AWKeysAggregator::FormatterType::Integer;
m_formatter["uptot"] = AWKeysAggregator::FormatterType::MemMBFormat;
m_formatter["uptotkb"] = AWKeysAggregator::FormatterType::Integer;
m_formatter["upunits"] = AWKeysAggregator::FormatterType::NetSmartUnits;
// swap
m_formatter["swap"] = AWKeysAggregator::FormatterType::Float;
m_formatter["swaptotmb"] = AWKeysAggregator::FormatterType::MemMBFormat;
m_formatter["swaptotgb"] = AWKeysAggregator::FormatterType::MemGBFormat;
}
AWDataEngineMapper::~AWDataEngineMapper()
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
}
AWKeysAggregator::FormatterType AWDataEngineMapper::formatter(const QString &_key) const
{
qCDebug(LOG_AW) << "Get formatter for key" << _key;
return m_formatter.value(_key, AWKeysAggregator::FormatterType::NoFormat);
}
QStringList AWDataEngineMapper::keysFromSource(const QString &_source) const
{
qCDebug(LOG_AW) << "Search for source" << _source;
return m_map.values(_source);
}
// HACK units required to define should the value be calculated as temperature
// or fan data
QStringList AWDataEngineMapper::registerSource(const QString &_source, const KSysGuard::Unit _units,
const QStringList &_keys)
{
qCDebug(LOG_AW) << "Source" << _source << "with units" << _units;
// regular expressions
auto cpuRegExp = QRegularExpression("^cpu/cpu.*/usage$");
auto cpuclRegExp = QRegularExpression("^cpu/cpu.*/frequency$");
auto cpuTempRegExp = QRegularExpression("^cpu/cpu.*/temperature$");
auto hddrRegExp = QRegularExpression("^disk/.*/read$");
auto hddwRegExp = QRegularExpression("^disk/.*/write$");
auto mountFillRegExp = QRegularExpression("^disk/.*/usedPercent$");
auto mountFreeRegExp = QRegularExpression("^disk/.*/free$");
auto mountUsedRegExp = QRegularExpression("^disk/.*/used$");
auto netRegExp = QRegularExpression("^network/.*/(download|upload)$");
auto netTotalRegExp = QRegularExpression("^network/.*/(totalDownload|totalUpload)$");
if (_source == "extsysmon/battery/ac") {
// AC
m_map.insert(_source, "ac");
m_formatter["ac"] = AWKeysAggregator::FormatterType::ACFormat;
} else if (_source.startsWith("extsysmon/battery/")) {
// battery stats
QString key = _source;
key.remove("extsysmon/battery/");
m_map.insert(_source, key);
m_formatter[key] = _source.contains("rate") ? AWKeysAggregator::FormatterType::Float
: AWKeysAggregator::FormatterType::IntegerThree;
} else if (_source == "cpu/all/usage") {
// cpu
m_map.insert(_source, "cpu");
m_formatter["cpu"] = AWKeysAggregator::FormatterType::Float;
} else if (_source.contains(cpuRegExp)) {
// cpus
QString key = _source;
key.remove("cpu/").remove("/usage");
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::Float;
} else if (_source == "cpu/all/averageFrequency") {
// cpucl
m_map.insert(_source, "cpucl");
m_formatter["cpucl"] = AWKeysAggregator::FormatterType::Integer;
} else if (_source.contains(cpuclRegExp)) {
// cpucls
QString key = _source;
key.remove("cpu/cpu").remove("/frequency");
key = QString("cpucl%1").arg(key);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::Integer;
} else if (_source.startsWith("extsysmon/custom")) {
// custom
QString key = _source;
key.remove("extsysmon/custom/");
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::NoFormat;
} else if (_source == "extsysmon/desktop/name") {
// current desktop name
m_map.insert(_source, "desktop");
m_formatter["desktop"] = AWKeysAggregator::FormatterType::NoFormat;
} else if (_source == "extsysmon/desktop/number") {
// current desktop number
m_map.insert(_source, "ndesktop");
m_formatter["ndesktop"] = AWKeysAggregator::FormatterType::NoFormat;
} else if (_source == "extsysmon/desktop/count") {
// desktop count
m_map.insert(_source, "tdesktops");
m_formatter["tdesktops"] = AWKeysAggregator::FormatterType::NoFormat;
} else if (_source.contains(hddrRegExp)) {
// read speed
QString device = _source;
device.remove("disk/").remove("/read");
int index = m_devices["disk"].indexOf(device);
if (index > -1) {
QString key = QString("hddr%1").arg(index);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::Integer;
}
} else if (_source.contains(hddwRegExp)) {
// write speed
QString device = _source;
device.remove("disk/").remove("/write");
int index = m_devices["disk"].indexOf(device);
if (index > -1) {
QString key = QString("hddw%1").arg(index);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::Integer;
}
} else if (_source == "extsysmon/gpuload/load") {
// gpu load
m_map.insert(_source, "gpu");
m_formatter["gpu"] = AWKeysAggregator::FormatterType::Float;
} else if (_source == "extsysmon/gputemp/temperature") {
// gpu temperature
m_map.insert(_source, "gputemp");
m_formatter["gputemp"] = AWKeysAggregator::FormatterType::Temperature;
} else if (_source.contains(mountFillRegExp)) {
// fill level
QString device = _source;
device.remove("disk/").remove("/usedPercent");
int index = m_devices["mount"].indexOf(device);
if (index > -1) {
QString key = QString("hdd%1").arg(index);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::Float;
// additional keys
m_formatter[QString("hddtotmb%1").arg(index)] = AWKeysAggregator::FormatterType::MemMBFormat;
m_formatter[QString("hddtotgb%1").arg(index)] = AWKeysAggregator::FormatterType::MemGBFormat;
}
} else if (_source.contains(mountFreeRegExp)) {
// free space
QString device = _source;
device.remove("disk/").remove("/free");
int index = m_devices["mount"].indexOf(device);
if (index > -1) {
// mb
QString key = QString("hddfreemb%1").arg(index);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::MemMBFormat;
// gb
key = QString("hddfreegb%1").arg(index);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::MemGBFormat;
}
} else if (_source.contains(mountUsedRegExp)) {
// used
QString device = _source;
device.remove("disk/").remove("/used");
int index = m_devices["mount"].indexOf(device);
if (index > -1) {
// mb
QString key = QString("hddmb%1").arg(index);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::MemMBFormat;
// gb
key = QString("hddgb%1").arg(index);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::MemGBFormat;
}
} else if (_source.startsWith("extsysmon/hdd/temperature")) {
// hdd temperature
QString device = _source;
device.remove("extsysmon/hdd/temperature");
int index = m_devices["hdd"].indexOf(device);
if (index > -1) {
QString key = QString("hddtemp%1").arg(index);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::Temperature;
}
} else if (_source.startsWith("cpu/loadaverages/loadaverage")) {
// load average
QString time = _source;
time.remove("cpu/loadaverages/loadaverage");
QString key = QString("la%1").arg(time);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::FloatTwoSymbols;
} else if (_source == "memory/physical/application") {
// app memory
// mb
m_map.insert(_source, "memmb");
m_formatter["memmb"] = AWKeysAggregator::FormatterType::MemMBFormat;
// gb
m_map.insert(_source, "memgb");
m_formatter["memgb"] = AWKeysAggregator::FormatterType::MemGBFormat;
} else if (_source == "memory/physical/free") {
// free memory
// mb
m_map.insert(_source, "memfreemb");
m_formatter["memfreemb"] = AWKeysAggregator::FormatterType::MemMBFormat;
// gb
m_map.insert(_source, "memfreegb");
m_formatter["memfreegb"] = AWKeysAggregator::FormatterType::MemGBFormat;
} else if (_source == "memory/physical/used") {
// used memory
// mb
m_map.insert(_source, "memusedmb");
m_formatter["memusedmb"] = AWKeysAggregator::FormatterType::MemMBFormat;
// gb
m_map.insert(_source, "memusedgb");
m_formatter["memusedgb"] = AWKeysAggregator::FormatterType::MemGBFormat;
} else if (_source == "extsysmon/network/device") {
// network device
m_map.insert(_source, "netdev");
m_formatter["netdev"] = AWKeysAggregator::FormatterType::NoFormat;
} else if (_source == "extsysmon/network/ssid") {
// current ssid
m_map.insert(_source, "ssid");
m_formatter["ssid"] = AWKeysAggregator::FormatterType::NoFormat;
} else if (_source.startsWith("extsysmon/requests/response")) {
// network response
QString key = _source;
key.remove("extsysmon/requests/");
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::NoFormat;
} else if (_source.contains(netRegExp)) {
// network speed
QString type = _source.contains("download") ? "down" : "up";
int index = m_devices["net"].indexOf(_source.split('/')[2]);
if (index > -1) {
// kb
QString key = QString("%1kb%2").arg(type).arg(index);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::Integer;
// smart
key = QString("%1%2").arg(type).arg(index);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::NetSmartFormat;
// units
key = QString("%1units%2").arg(type).arg(index);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::NetSmartUnits;
}
} else if (_source.contains(netTotalRegExp)) {
// network data total
QString type = _source.contains("download") ? "down" : "up";
int index = m_devices["net"].indexOf(_source.split('/')[2]);
if (index > -1) {
// kb
QString key = QString("%1totkb%2").arg(type).arg(index);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::Integer;
// mb
key = QString("%1tot%2").arg(type).arg(index);
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::MemMBFormat;
}
} else if (_source.startsWith("extsysmon/upgrade")) {
// package manager
QString key = _source;
key.remove("extsysmon/upgrade/");
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::IntegerThree;
} else if (_source.startsWith("extsysmon/player")) {
// player
QString key = _source;
key.remove("extsysmon/player/");
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::NoFormat;
} else if (_source == "extsysmon/ps/running") {
// running processes count
m_map.insert(_source, "pscount");
m_formatter["pscount"] = AWKeysAggregator::FormatterType::NoFormat;
} else if (_source == "extsysmon/ps/list") {
// list of running processes
m_map.insert(_source, "ps");
m_formatter["ps"] = AWKeysAggregator::FormatterType::List;
} else if (_source == "extsysmon/ps/count") {
// total processes count
m_map.insert(_source, "pstot");
m_formatter["pstot"] = AWKeysAggregator::FormatterType::NoFormat;
} else if (_source.startsWith("extsysmon/quotes")) {
// quotes
QString key = _source;
key.remove("extsysmon/quotes/");
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::Quotes;
} else if (_source == "memory/swap/free") {
// free swap
// mb
m_map.insert(_source, "swapfreemb");
m_formatter["swapfreemb"] = AWKeysAggregator::FormatterType::MemMBFormat;
// gb
m_map.insert(_source, "swapfreegb");
m_formatter["swapfreegb"] = AWKeysAggregator::FormatterType::MemGBFormat;
} else if (_source == "memory/swap/used") {
// used swap
// mb
m_map.insert(_source, "swapmb");
m_formatter["swapmb"] = AWKeysAggregator::FormatterType::MemMBFormat;
// gb
m_map.insert(_source, "swapgb");
m_formatter["swapgb"] = AWKeysAggregator::FormatterType::MemGBFormat;
} else if (_source.startsWith("lmsensors/") || _source.contains(cpuTempRegExp)
|| _source == "cpu/all/averageTemperature") {
// temperature
auto index = m_devices["temp"].indexOf(_source);
// HACK on DE initialization there are no units key
if (_units == KSysGuard::UnitInvalid)
return QStringList({QString("temp%1").arg(index)});
if (index > -1) {
QString key = QString("temp%1").arg(index);
m_map.insert(_source, key);
m_formatter[key] = _units == KSysGuard::UnitCelsius ? AWKeysAggregator::FormatterType::Temperature
: AWKeysAggregator::FormatterType::Integer;
}
} else if (_source == "extsysmon/time/now") {
// time
m_map.insert(_source, "time");
m_formatter["time"] = AWKeysAggregator::FormatterType::Time;
// custom time
m_map.insert(_source, "ctime");
m_formatter["ctime"] = AWKeysAggregator::FormatterType::TimeCustom;
// ISO time
m_map.insert(_source, "isotime");
m_formatter["isotime"] = AWKeysAggregator::FormatterType::TimeISO;
// long time
m_map.insert(_source, "longtime");
m_formatter["longtime"] = AWKeysAggregator::FormatterType::TimeLong;
// short time
m_map.insert(_source, "shorttime");
m_formatter["shorttime"] = AWKeysAggregator::FormatterType::TimeShort;
// timestamp
m_map.insert(_source, "tstime");
m_formatter["tstime"] = AWKeysAggregator::FormatterType::Timestamp;
} else if (_source == "extsysmon/system/brightness") {
m_map.insert(_source, "brightness");
m_formatter["brightness"] = AWKeysAggregator::FormatterType::IntegerThree;
} else if (_source == "extsysmon/system/volume") {
m_map.insert(_source, "volume");
m_formatter["volume"] = AWKeysAggregator::FormatterType::IntegerThree;
} else if (_source == "os/system/uptime") {
// uptime
m_map.insert(_source, "uptime");
m_formatter["uptime"] = AWKeysAggregator::FormatterType::Uptime;
// custom uptime
m_map.insert(_source, "cuptime");
m_formatter["cuptime"] = AWKeysAggregator::FormatterType::UptimeCustom;
} else if (_source.startsWith("extsysmon/weather/temperature")) {
// temperature
QString key = _source;
key.remove("extsysmon/weather/");
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::Temperature;
} else if (_source.startsWith("extsysmon/weather/")) {
// other weather
QString key = _source;
key.remove("extsysmon/weather/");
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::NoFormat;
} else if (_source.startsWith("extsysmon/load/load")) {
// load source
QString key = _source;
key.remove("extsysmon/load/");
m_map.insert(_source, key);
m_formatter[key] = AWKeysAggregator::FormatterType::Temperature;
}
auto foundKeys = keysFromSource(_source);
// rewrite formatters for custom ones
QStringList customFormattersKeys;
if (m_customFormatters)
customFormattersKeys = m_customFormatters->definedFormatters();
qCInfo(LOG_AW) << "Looking for formatters" << foundKeys << "in" << customFormattersKeys;
for (auto &key : foundKeys) {
if (!customFormattersKeys.contains(key))
continue;
m_formatter[key] = AWKeysAggregator::FormatterType::Custom;
}
// drop key from dictionary if no one user requested key required it
qCInfo(LOG_AW) << "Looking for keys" << foundKeys << "in" << _keys;
auto required = _keys.isEmpty() || std::any_of(foundKeys.cbegin(), foundKeys.cend(), [&_keys](const QString &key) {
return _keys.contains(key);
});
if (!required) {
m_map.remove(_source);
for (auto &key : foundKeys)
m_formatter.remove(key);
}
return keysFromSource(_source);
}
void AWDataEngineMapper::setDevices(const QHash<QString, QStringList> &_devices)
{
qCDebug(LOG_AW) << "Devices" << _devices;
m_devices = _devices;
}

View File

@ -0,0 +1,55 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#ifndef AWDATAENGINEMAPPER_H
#define AWDATAENGINEMAPPER_H
#include <ksysguard/formatter/Unit.h>
#include <QMultiHash>
#include <QObject>
#include "awkeysaggregator.h"
class AWFormatterHelper;
class AWDataEngineMapper : public QObject
{
Q_OBJECT
public:
explicit AWDataEngineMapper(QObject *_parent = nullptr, AWFormatterHelper *_custom = nullptr);
~AWDataEngineMapper() override;
// get methods
[[nodiscard]] AWKeysAggregator::FormatterType formatter(const QString &_key) const;
[[nodiscard]] QStringList keysFromSource(const QString &_source) const;
// set methods
QStringList registerSource(const QString &_source, const KSysGuard::Unit _units, const QStringList &_keys);
void setDevices(const QHash<QString, QStringList> &_devices);
private:
AWFormatterHelper *m_customFormatters = nullptr;
// variables
QHash<QString, QStringList> m_devices;
QHash<QString, AWKeysAggregator::FormatterType> m_formatter;
QMultiHash<QString, QString> m_map;
};
#endif /* AWDATAENGINEMAPPER_H */

View File

@ -0,0 +1,108 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#include "awdbusadaptor.h"
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include "awdebug.h"
#include "awkeys.h"
AWDBusAdaptor::AWDBusAdaptor(AWKeys *_parent)
: QDBusAbstractAdaptor(_parent)
, m_plugin(_parent)
{
qCDebug(LOG_DBUS) << __PRETTY_FUNCTION__;
}
AWDBusAdaptor::~AWDBusAdaptor()
{
qCDebug(LOG_DBUS) << __PRETTY_FUNCTION__;
}
QStringList AWDBusAdaptor::ActiveServices()
{
QDBusMessage listServices = QDBusConnection::sessionBus().interface()->call(QDBus::BlockWithGui, "ListNames");
if (listServices.arguments().isEmpty()) {
qCWarning(LOG_DBUS) << "Could not find any DBus service";
return {};
}
QStringList arguments = listServices.arguments().first().toStringList();
return std::accumulate(arguments.cbegin(), arguments.cend(), QStringList(),
[](QStringList source, const QString &service) {
if (service.startsWith(AWDBUS_SERVICE))
source.append(service);
return source;
});
}
QString AWDBusAdaptor::Info(const QString &key) const
{
return m_plugin->infoByKey(key);
}
QStringList AWDBusAdaptor::Keys(const QString &regexp) const
{
return m_plugin->dictKeys(true, regexp);
}
QString AWDBusAdaptor::Value(const QString &key) const
{
return m_plugin->valueByKey(key);
}
qlonglong AWDBusAdaptor::WhoAmI() const
{
return reinterpret_cast<qlonglong>(m_plugin);
}
void AWDBusAdaptor::SetLogLevel(const QString &what, const int level)
{
qCDebug(LOG_DBUS) << "Set log level" << level << "for" << what;
if (level >= m_logLevels.count()) {
qCDebug(LOG_DBUS) << "Invalid logging level" << level << "should be less than" << m_logLevels.count();
return;
}
for (auto &lev : m_logLevels)
SetLogLevel(what, lev, m_logLevels.indexOf(lev) >= level);
}
void AWDBusAdaptor::SetLogLevel(const QString &what, const QString &level, const bool enabled)
{
qCDebug(LOG_DBUS) << "Set log level" << level << "enabled" << enabled << "for" << what;
if (!m_logLevels.contains(level)) {
qCDebug(LOG_DBUS) << "Invalid logging level" << level << "should be in" << m_logLevels;
return;
}
QString state = enabled ? "true" : "false";
QLoggingCategory::setFilterRules(QString("%1.%2=%3").arg(what).arg(level).arg(state));
}

View File

@ -0,0 +1,55 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#ifndef AWDBUSADAPTOR_H
#define AWDBUSADAPTOR_H
#include <QDBusAbstractAdaptor>
#include "version.h"
class AWKeys;
class AWDBusAdaptor : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", AWDBUS_SERVICE_NAME)
public:
explicit AWDBusAdaptor(AWKeys *_parent = nullptr);
~AWDBusAdaptor() override;
public slots:
// get methods
[[nodiscard]] static QStringList ActiveServices();
[[nodiscard]] QString Info(const QString &key) const;
[[nodiscard]] QStringList Keys(const QString &regexp) const;
[[nodiscard]] QString Value(const QString &key) const;
[[nodiscard]] qlonglong WhoAmI() const;
// set methods
void SetLogLevel(const QString &what, int level);
void SetLogLevel(const QString &what, const QString &level, bool enabled);
private:
AWKeys *m_plugin = nullptr;
QStringList m_logLevels = {"debug", "info", "warning", "critical"};
};
#endif /* AWDBUSADAPTOR_H */

View File

@ -20,9 +20,11 @@
#include <QtQml> #include <QtQml>
#include "awactions.h" #include "awactions.h"
#include "awbugreporter.h"
#include "awconfighelper.h" #include "awconfighelper.h"
#include "awformatterconfigfactory.h"
#include "awkeys.h" #include "awkeys.h"
#include "awpairconfigfactory.h"
#include "awtelemetryhandler.h"
void AWPlugin::registerTypes(const char *uri) void AWPlugin::registerTypes(const char *uri)
@ -30,8 +32,9 @@ void AWPlugin::registerTypes(const char *uri)
Q_ASSERT(uri == QLatin1String("org.kde.plasma.private.awesomewidget")); Q_ASSERT(uri == QLatin1String("org.kde.plasma.private.awesomewidget"));
qmlRegisterType<AWActions>(uri, 1, 0, "AWActions"); qmlRegisterType<AWActions>(uri, 1, 0, "AWActions");
qmlRegisterType<AWBugReporter>(uri, 1, 0, "AWBugReporter");
qmlRegisterType<AWConfigHelper>(uri, 1, 0, "AWConfigHelper"); qmlRegisterType<AWConfigHelper>(uri, 1, 0, "AWConfigHelper");
qmlRegisterType<AWFormatterConfigFactory>(uri, 1, 0, qmlRegisterType<AWPairConfigFactory>(uri, 1, 0, "AWPairConfigFactory");
"AWFormatterConfigFactory");
qmlRegisterType<AWKeys>(uri, 1, 0, "AWKeys"); qmlRegisterType<AWKeys>(uri, 1, 0, "AWKeys");
qmlRegisterType<AWTelemetryHandler>(uri, 1, 0, "AWTelemetryHandler");
} }

View File

@ -28,7 +28,7 @@ class AWPlugin : public QQmlExtensionPlugin
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
public: public:
void registerTypes(const char *uri); void registerTypes(const char *uri) override;
}; };

View File

@ -16,166 +16,22 @@
***************************************************************************/ ***************************************************************************/
#include "awformatterconfig.h" #include "awformatterconfig.h"
#include "ui_awformatterconfig.h"
#include <KI18n/KLocalizedString>
#include <QPushButton>
#include "awabstractselector.h"
#include "awdebug.h" #include "awdebug.h"
#include "awformatterhelper.h" #include "awformatterhelper.h"
AWFormatterConfig::AWFormatterConfig(QWidget *parent, const QStringList keys) AWFormatterConfig::AWFormatterConfig(QWidget *_parent, const QStringList &_keys)
: QDialog(parent) : AWAbstractPairConfig(_parent, true, _keys)
, ui(new Ui::AWFormatterConfig)
, m_keys(keys)
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
ui->setupUi(this); setEditable(false, false);
m_editButton initHelper<AWFormatterHelper>();
= ui->buttonBox->addButton(i18n("Edit"), QDialogButtonBox::ActionRole);
init();
connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
connect(m_editButton, SIGNAL(clicked(bool)), this, SLOT(editFormatters()));
} }
AWFormatterConfig::~AWFormatterConfig() AWFormatterConfig::~AWFormatterConfig()
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
clearSelectors();
delete m_helper;
delete ui;
}
void AWFormatterConfig::showDialog()
{
// update dialog
updateDialog();
// exec dialog
return execDialog();
}
void AWFormatterConfig::editFormatters()
{
m_helper->editItems();
updateDialog();
}
void AWFormatterConfig::updateUi()
{
QPair<QString, QString> current
= static_cast<AWAbstractSelector *>(sender())->current();
int index
= m_selectors.indexOf(static_cast<AWAbstractSelector *>(sender()));
if ((current.first.isEmpty()) && (current.second.isEmpty())) {
if (sender() == m_selectors.last())
return;
AWAbstractSelector *selector = m_selectors.takeAt(index);
ui->verticalLayout->removeWidget(selector);
selector->deleteLater();
} else {
if (sender() != m_selectors.last())
return;
auto keys = initKeys();
addSelector(keys.first, keys.second, QPair<QString, QString>());
}
}
void AWFormatterConfig::addSelector(const QStringList &keys,
const QStringList &values,
const QPair<QString, QString> &current)
{
qCDebug(LOG_AW) << "Add selector with keys" << keys << "values" << values
<< "and current ones" << current;
AWAbstractSelector *selector
= new AWAbstractSelector(ui->scrollAreaWidgetContents);
selector->init(keys, values, current);
ui->verticalLayout->insertWidget(ui->verticalLayout->count() - 1, selector);
connect(selector, SIGNAL(selectionChanged()), this, SLOT(updateUi()));
m_selectors.append(selector);
}
void AWFormatterConfig::clearSelectors()
{
for (auto selector : m_selectors) {
disconnect(selector, SIGNAL(selectionChanged()), this,
SLOT(updateUi()));
ui->verticalLayout->removeWidget(selector);
selector->deleteLater();
}
m_selectors.clear();
}
void AWFormatterConfig::execDialog()
{
int ret = exec();
QHash<QString, QString> data;
for (auto selector : m_selectors) {
QPair<QString, QString> select = selector->current();
if (select.first.isEmpty())
continue;
data[select.first] = select.second;
}
// save configuration if required
switch (ret) {
case 0:
break;
case 1:
default:
m_helper->writeFormatters(data);
m_helper->writeFormatters(data.keys());
break;
}
}
void AWFormatterConfig::init()
{
delete m_helper;
m_helper = new AWFormatterHelper(this);
}
QPair<QStringList, QStringList> AWFormatterConfig::initKeys() const
{
// we are adding empty string at the start
QStringList keys = QStringList() << QString("");
keys.append(m_keys);
keys.sort();
QStringList knownFormatters = QStringList() << QString("");
knownFormatters.append(m_helper->knownFormatters());
knownFormatters.sort();
return QPair<QStringList, QStringList>(keys, knownFormatters);
}
void AWFormatterConfig::updateDialog()
{
clearSelectors();
QHash<QString, QString> appliedFormatters = m_helper->getFormatters();
auto keys = initKeys();
for (auto key : appliedFormatters.keys())
addSelector(keys.first, keys.second,
QPair<QString, QString>(key, appliedFormatters[key]));
// empty one
addSelector(keys.first, keys.second, QPair<QString, QString>());
} }

View File

@ -19,45 +19,16 @@
#ifndef AWFORMATTERCONFIG_H #ifndef AWFORMATTERCONFIG_H
#define AWFORMATTERCONFIG_H #define AWFORMATTERCONFIG_H
#include <QDialog> #include "awabstractpairconfig.h"
class AWAbstractSelector; class AWFormatterConfig : public AWAbstractPairConfig
class AWFormatterHelper;
namespace Ui
{
class AWFormatterConfig;
}
class AWFormatterConfig : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AWFormatterConfig(QWidget *parent = nullptr, explicit AWFormatterConfig(QWidget *_parent = nullptr, const QStringList &_keys = QStringList());
const QStringList keys = QStringList()); ~AWFormatterConfig() override;
virtual ~AWFormatterConfig();
Q_INVOKABLE void showDialog();
private slots:
void editFormatters();
void updateUi();
private:
QPushButton *m_editButton = nullptr;
Ui::AWFormatterConfig *ui = nullptr;
AWFormatterHelper *m_helper = nullptr;
QList<AWAbstractSelector *> m_selectors;
// properties
QStringList m_keys;
// methods
void addSelector(const QStringList &keys, const QStringList &values,
const QPair<QString, QString> &current);
void clearSelectors();
void execDialog();
void init();
QPair<QStringList, QStringList> initKeys() const;
void updateDialog();
}; };

View File

@ -26,18 +26,20 @@
#include "awdatetimeformatter.h" #include "awdatetimeformatter.h"
#include "awdebug.h" #include "awdebug.h"
#include "awfloatformatter.h" #include "awfloatformatter.h"
#include "awjsonformatter.h"
#include "awlistformatter.h" #include "awlistformatter.h"
#include "awnoformatter.h" #include "awnoformatter.h"
#include "awscriptformatter.h" #include "awscriptformatter.h"
#include "awstringformatter.h" #include "awstringformatter.h"
AWFormatterHelper::AWFormatterHelper(QWidget *parent) AWFormatterHelper::AWFormatterHelper(QWidget *_parent)
: AbstractExtItemAggregator(parent, QString("formatters")) : AbstractExtItemAggregator(_parent, "formatters")
, AWAbstractPairHelper("awesomewidgets/formatters/formatters.ini", "Formatters")
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
initItems(); AWFormatterHelper::initItems();
} }
@ -50,13 +52,29 @@ AWFormatterHelper::~AWFormatterHelper()
} }
QString AWFormatterHelper::convert(const QVariant &value, void AWFormatterHelper::initItems()
const QString &name) const
{ {
qCDebug(LOG_AW) << "Convert value" << value << "for" << name; initFormatters();
return m_formatters.contains(name) ? m_formatters[name]->convert(value) // assign internal storage
: value.toString(); m_formatters.clear();
for (auto &key : pairs().keys()) {
auto name = pairs()[key];
if (!m_formattersClasses.contains(name)) {
qCWarning(LOG_AW) << "Invalid formatter" << name << "found in" << key;
continue;
}
m_formatters[key] = m_formattersClasses[name];
}
}
QString AWFormatterHelper::convert(const QVariant &_value, const QString &_name) const
{
qCDebug(LOG_AW) << "Convert value" << _value << "for" << _name;
return m_formatters.contains(_name) ? m_formatters[_name]->convert(_value) : _value.toString();
} }
@ -66,108 +84,62 @@ QStringList AWFormatterHelper::definedFormatters() const
} }
QHash<QString, QString> AWFormatterHelper::getFormatters() const
{
QHash<QString, QString> map;
for (auto tag : m_formatters.keys())
map[tag] = m_formatters[tag]->name();
return map;
}
QList<AbstractExtItem *> AWFormatterHelper::items() const QList<AbstractExtItem *> AWFormatterHelper::items() const
{ {
QList<AbstractExtItem *> converted; QList<AbstractExtItem *> converted;
for (auto item : m_formattersClasses.values()) for (auto &item : m_formattersClasses.values())
converted.append(item); converted.append(item);
return converted; return converted;
} }
QStringList AWFormatterHelper::knownFormatters() const void AWFormatterHelper::editPairs()
{
return editItems();
}
QStringList AWFormatterHelper::leftKeys()
{
return {};
}
QStringList AWFormatterHelper::rightKeys()
{ {
return m_formattersClasses.keys(); return m_formattersClasses.keys();
} }
bool AWFormatterHelper::writeFormatters(const QStringList keys) const
{
qCDebug(LOG_AW) << "Remove formatters" << keys;
QString fileName = QString("%1/awesomewidgets/formatters/formatters.ini")
.arg(QStandardPaths::writableLocation(
QStandardPaths::GenericDataLocation));
QSettings settings(fileName, QSettings::IniFormat);
qCInfo(LOG_AW) << "Configuration file" << fileName;
settings.beginGroup(QString("Formatters"));
QStringList foundKeys = settings.childKeys();
for (auto key : foundKeys) {
if (keys.contains(key))
continue;
settings.remove(key);
}
settings.endGroup();
settings.sync();
return (settings.status() == QSettings::NoError);
}
bool AWFormatterHelper::writeFormatters(
const QHash<QString, QString> configuration) const
{
qCDebug(LOG_AW) << "Write configuration" << configuration;
QString fileName = QString("%1/awesomewidgets/formatters/formatters.ini")
.arg(QStandardPaths::writableLocation(
QStandardPaths::GenericDataLocation));
QSettings settings(fileName, QSettings::IniFormat);
qCInfo(LOG_AW) << "Configuration file" << fileName;
settings.beginGroup(QString("Formatters"));
for (auto key : configuration.keys())
settings.setValue(key, configuration[key]);
settings.endGroup();
settings.sync();
return (settings.status() == QSettings::NoError);
}
void AWFormatterHelper::editItems() void AWFormatterHelper::editItems()
{ {
repaintList(); auto ret = exec();
int ret = exec();
qCInfo(LOG_AW) << "Dialog returns" << ret; qCInfo(LOG_AW) << "Dialog returns" << ret;
} }
AWAbstractFormatter::FormatterClass AWAbstractFormatter::FormatterClass AWFormatterHelper::defineFormatterClass(const QString &_stringType)
AWFormatterHelper::defineFormatterClass(const QString stringType) const
{ {
qCDebug(LOG_AW) << "Define formatter class for" << stringType; qCDebug(LOG_AW) << "Define formatter class for" << _stringType;
AWAbstractFormatter::FormatterClass formatter AWAbstractFormatter::FormatterClass formatter = AWAbstractFormatter::FormatterClass::NoFormat;
= AWAbstractFormatter::FormatterClass::NoFormat; if (_stringType == "DateTime")
if (stringType == QString("DateTime"))
formatter = AWAbstractFormatter::FormatterClass::DateTime; formatter = AWAbstractFormatter::FormatterClass::DateTime;
else if (stringType == QString("Float")) else if (_stringType == "Float")
formatter = AWAbstractFormatter::FormatterClass::Float; formatter = AWAbstractFormatter::FormatterClass::Float;
else if (stringType == QString("List")) else if (_stringType == "List")
formatter = AWAbstractFormatter::FormatterClass::List; formatter = AWAbstractFormatter::FormatterClass::List;
else if (stringType == QString("NoFormat")) else if (_stringType == "NoFormat")
; ;
else if (stringType == QString("Script")) else if (_stringType == "Script")
formatter = AWAbstractFormatter::FormatterClass::Script; formatter = AWAbstractFormatter::FormatterClass::Script;
else if (stringType == QString("String")) else if (_stringType == "String")
formatter = AWAbstractFormatter::FormatterClass::String; formatter = AWAbstractFormatter::FormatterClass::String;
else if (_stringType == "Json")
formatter = AWAbstractFormatter::FormatterClass::Json;
else else
qCWarning(LOG_AW) << "Unknown formatter" << stringType; qCWarning(LOG_AW) << "Unknown formatter" << _stringType;
return formatter; return formatter;
} }
@ -177,44 +149,43 @@ void AWFormatterHelper::initFormatters()
{ {
m_formattersClasses.clear(); m_formattersClasses.clear();
for (int i = m_directories.count() - 1; i >= 0; i--) { auto dirs = directories();
QStringList files for (auto &dir : dirs) {
= QDir(m_directories.at(i)).entryList(QDir::Files, QDir::Name); QStringList files = QDir(dir).entryList(QDir::Files, QDir::Name);
for (auto file : files) { for (auto &file : files) {
if (!file.endsWith(QString(".desktop"))) // check filename
if (!file.endsWith(".desktop"))
continue; continue;
qCInfo(LOG_AW) << "Found file" << file << "in" qCInfo(LOG_AW) << "Found file" << file << "in" << dir;
<< m_directories.at(i); QString filePath = QString("%1/%2").arg(dir).arg(file);
QString filePath // check if already exists
= QString("%1/%2").arg(m_directories.at(i)).arg(file); auto values = m_formattersClasses.values();
if (std::any_of(values.cbegin(), values.cend(),
[&filePath](const AWAbstractFormatter *item) { return (item->fileName() == filePath); }))
continue;
auto metadata = readMetadata(filePath); auto metadata = readMetadata(filePath);
QString name = metadata.first;
if (m_formattersClasses.contains(name))
continue;
switch (metadata.second) { switch (metadata.second) {
case AWAbstractFormatter::FormatterClass::DateTime: case AWAbstractFormatter::FormatterClass::DateTime:
m_formattersClasses[name] m_formattersClasses[metadata.first] = new AWDateTimeFormatter(this, filePath);
= new AWDateTimeFormatter(this, filePath);
break; break;
case AWAbstractFormatter::FormatterClass::Float: case AWAbstractFormatter::FormatterClass::Float:
m_formattersClasses[name] m_formattersClasses[metadata.first] = new AWFloatFormatter(this, filePath);
= new AWFloatFormatter(this, filePath);
break; break;
case AWAbstractFormatter::FormatterClass::List: case AWAbstractFormatter::FormatterClass::List:
m_formattersClasses[name] = new AWListFormatter(this, filePath); m_formattersClasses[metadata.first] = new AWListFormatter(this, filePath);
break; break;
case AWAbstractFormatter::FormatterClass::Script: case AWAbstractFormatter::FormatterClass::Script:
m_formattersClasses[name] m_formattersClasses[metadata.first] = new AWScriptFormatter(this, filePath);
= new AWScriptFormatter(this, filePath);
break; break;
case AWAbstractFormatter::FormatterClass::String: case AWAbstractFormatter::FormatterClass::String:
m_formattersClasses[name] m_formattersClasses[metadata.first] = new AWStringFormatter(this, filePath);
= new AWStringFormatter(this, filePath); break;
case AWAbstractFormatter::FormatterClass::Json:
m_formattersClasses[metadata.first] = new AWJsonFormatter(this, filePath);
break; break;
case AWAbstractFormatter::FormatterClass::NoFormat: case AWAbstractFormatter::FormatterClass::NoFormat:
m_formattersClasses[name] = new AWNoFormatter(this, filePath); m_formattersClasses[metadata.first] = new AWNoFormatter(this, filePath);
break; break;
} }
} }
@ -222,110 +193,47 @@ void AWFormatterHelper::initFormatters()
} }
void AWFormatterHelper::initKeys() QPair<QString, AWAbstractFormatter::FormatterClass> AWFormatterHelper::readMetadata(const QString &_filePath)
{ {
m_formatters.clear(); qCDebug(LOG_AW) << "Read initial parameters from" << _filePath;
QStringList configs = QStandardPaths::locateAll( QSettings settings(_filePath, QSettings::IniFormat);
QStandardPaths::GenericDataLocation, settings.beginGroup("Desktop Entry");
QString("awesomewidgets/formatters/formatters.ini")); auto name = settings.value("Name", _filePath).toString();
auto type = settings.value("X-AW-Type", "NoFormat").toString();
for (auto fileName : configs) { auto formatter = defineFormatterClass(type);
QSettings settings(fileName, QSettings::IniFormat);
qCInfo(LOG_AW) << "Configuration file" << settings.fileName();
settings.beginGroup(QString("Formatters"));
QStringList keys = settings.childKeys();
for (auto key : keys) {
QString name = settings.value(key).toString();
qCInfo(LOG_AW) << "Found formatter" << name << "for key" << key
<< "in" << settings.fileName();
if (name.isEmpty()) {
qCInfo(LOG_AW) << "Skip empty formatter for" << key;
continue;
}
if (!m_formattersClasses.contains(name)) {
qCWarning(LOG_AW) << "Invalid formatter" << name << "found in"
<< key;
continue;
}
m_formatters[key] = m_formattersClasses[name];
}
settings.endGroup();
}
}
void AWFormatterHelper::installDirectories()
{
// create directory at $HOME
QString localDir = QString("%1/awesomewidgets/formatters")
.arg(QStandardPaths::writableLocation(
QStandardPaths::GenericDataLocation));
QDir localDirectory;
if (localDirectory.mkpath(localDir))
qCInfo(LOG_AW) << "Created directory" << localDir;
m_directories = QStandardPaths::locateAll(
QStandardPaths::GenericDataLocation,
QString("awesomewidgets/formatters"), QStandardPaths::LocateDirectory);
}
QPair<QString, AWAbstractFormatter::FormatterClass>
AWFormatterHelper::readMetadata(const QString filePath) const
{
qCDebug(LOG_AW) << "Read initial parameters from" << filePath;
QSettings settings(filePath, QSettings::IniFormat);
settings.beginGroup(QString("Desktop Entry"));
QString name = settings.value(QString("Name"), filePath).toString();
QString type
= settings.value(QString("X-AW-Type"), QString("NoFormat")).toString();
AWAbstractFormatter::FormatterClass formatter = defineFormatterClass(type);
settings.endGroup(); settings.endGroup();
return QPair<QString, AWAbstractFormatter::FormatterClass>(name, formatter); return QPair<QString, AWAbstractFormatter::FormatterClass>(name, formatter);
} }
void AWFormatterHelper::doCreateItem() void AWFormatterHelper::doCreateItem(QListWidget *_widget)
{ {
QStringList selection = QStringList() QStringList selection = {"NoFormat", "DateTime", "Float", "List", "Script", "String", "Json"};
<< QString("NoFormat") << QString("DateTime")
<< QString("Float") << QString("List")
<< QString("Script") << QString("String");
bool ok; bool ok;
QString select = QInputDialog::getItem( auto select = QInputDialog::getItem(nullptr, i18n("Select type"), i18n("Type:"), selection, 0, false, &ok);
this, i18n("Select type"), i18n("Type:"), selection, 0, false, &ok);
if (!ok) { if (!ok) {
qCWarning(LOG_AW) << "No type selected"; qCWarning(LOG_AW) << "No type selected";
return; return;
} }
qCInfo(LOG_AW) << "Selected type" << select; qCInfo(LOG_AW) << "Selected type" << select;
AWAbstractFormatter::FormatterClass formatter AWAbstractFormatter::FormatterClass formatter = defineFormatterClass(select);
= defineFormatterClass(select);
switch (formatter) { switch (formatter) {
case AWAbstractFormatter::FormatterClass::DateTime: case AWAbstractFormatter::FormatterClass::DateTime:
return createItem<AWDateTimeFormatter>(); return createItem<AWDateTimeFormatter>(_widget);
case AWAbstractFormatter::FormatterClass::Float: case AWAbstractFormatter::FormatterClass::Float:
return createItem<AWFloatFormatter>(); return createItem<AWFloatFormatter>(_widget);
case AWAbstractFormatter::FormatterClass::List: case AWAbstractFormatter::FormatterClass::List:
return createItem<AWListFormatter>(); return createItem<AWListFormatter>(_widget);
case AWAbstractFormatter::FormatterClass::Script: case AWAbstractFormatter::FormatterClass::Script:
return createItem<AWScriptFormatter>(); return createItem<AWScriptFormatter>(_widget);
case AWAbstractFormatter::FormatterClass::String: case AWAbstractFormatter::FormatterClass::String:
return createItem<AWStringFormatter>(); return createItem<AWStringFormatter>(_widget);
case AWAbstractFormatter::FormatterClass::Json:
return createItem<AWJsonFormatter>(_widget);
case AWAbstractFormatter::FormatterClass::NoFormat: case AWAbstractFormatter::FormatterClass::NoFormat:
return createItem<AWNoFormatter>(); return createItem<AWNoFormatter>(_widget);
} }
} }
void AWFormatterHelper::initItems()
{
installDirectories();
initFormatters();
initKeys();
}

View File

@ -20,44 +20,39 @@
#define AWFORMATTERHELPER_H #define AWFORMATTERHELPER_H
#include "abstractextitemaggregator.h" #include "abstractextitemaggregator.h"
#include "awabstractformatter.h" #include "awabstractformatter.h"
#include "awabstractpairhelper.h"
class AWAbstractFormatter; class AWFormatterHelper : public AbstractExtItemAggregator, public AWAbstractPairHelper
class AWFormatterHelper : public AbstractExtItemAggregator
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AWFormatterHelper(QWidget *parent = nullptr); explicit AWFormatterHelper(QWidget *_parent = nullptr);
virtual ~AWFormatterHelper(); ~AWFormatterHelper() override;
QString convert(const QVariant &value, const QString &name) const; // read-write methods
QStringList definedFormatters() const; void initItems() override;
QHash<QString, QString> getFormatters() const; // methods
QList<AbstractExtItem *> items() const; [[nodiscard]] QString convert(const QVariant &_value, const QString &_name) const;
QStringList knownFormatters() const; [[nodiscard]] QStringList definedFormatters() const;
bool writeFormatters(const QStringList keys) const; [[nodiscard]] QList<AbstractExtItem *> items() const override;
bool writeFormatters(const QHash<QString, QString> configuration) const; // configuration related
void editPairs() override;
QStringList leftKeys() override;
QStringList rightKeys() override;
public slots: public slots:
void editItems(); void editItems();
private: private:
// methods // methods
AWAbstractFormatter::FormatterClass static AWAbstractFormatter::FormatterClass defineFormatterClass(const QString &_stringType);
defineFormatterClass(const QString stringType) const;
void initFormatters(); void initFormatters();
void initKeys(); [[nodiscard]] static QPair<QString, AWAbstractFormatter::FormatterClass> readMetadata(const QString &_filePath);
void installDirectories();
QPair<QString, AWAbstractFormatter::FormatterClass>
readMetadata(const QString filePath) const;
// parent methods // parent methods
void doCreateItem(); void doCreateItem(QListWidget *_widget) override;
void initItems();
// properties // properties
QStringList m_directories;
QHash<QString, AWAbstractFormatter *> m_formatters; QHash<QString, AWAbstractFormatter *> m_formatters;
QHash<QString, AWAbstractFormatter *> m_formattersClasses; QHash<QString, AWAbstractFormatter *> m_formattersClasses;
}; };

View File

@ -15,66 +15,58 @@
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/ ***************************************************************************/
#include "awkeycache.h" #include "awkeycache.h"
#include <QDir> #include <QDir>
#include <QNetworkInterface> #include <QNetworkInterface>
#include <QRegExp> #include <QRegularExpression>
#include <QSettings> #include <QSettings>
#include <QStandardPaths> #include <QStandardPaths>
#include "awdebug.h" #include "awdebug.h"
bool AWKeyCache::addKeyToCache(const QString type, const QString key) bool AWKeyCache::addKeyToCache(const QString &_type, const QString &_key)
{ {
qCDebug(LOG_AW) << "Key" << key << "with type" << type; qCDebug(LOG_AW) << "Key" << _key << "with type" << _type;
QString fileName = QString("%1/awesomewidgets.ndx") QString fileName
.arg(QStandardPaths::writableLocation( = QString("%1/awesomewidgets.ndx").arg(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation));
QStandardPaths::GenericCacheLocation));
qCInfo(LOG_AW) << "Cache file" << fileName; qCInfo(LOG_AW) << "Cache file" << fileName;
QSettings cache(fileName, QSettings::IniFormat); QSettings cache(fileName, QSettings::IniFormat);
cache.beginGroup(type); cache.beginGroup(_type);
QStringList cachedValues; QStringList cachedValues;
for (auto number : cache.allKeys()) for (auto &number : cache.allKeys())
cachedValues.append(cache.value(number).toString()); cachedValues.append(cache.value(number).toString());
if (type == QString("hdd")) { if (_type == "hdd") {
QStringList allDevices QStringList allDevices = QDir("/dev").entryList(QDir::System, QDir::Name);
= QDir(QString("/dev")).entryList(QDir::System, QDir::Name); QStringList devices = allDevices.filter(QRegularExpression("^[hms]d[a-z]$"));
QStringList devices for (auto &dev : devices) {
= allDevices.filter(QRegExp(QString("^[hms]d[a-z]$")));
for (auto dev : devices) {
QString device = QString("/dev/%1").arg(dev); QString device = QString("/dev/%1").arg(dev);
if (cachedValues.contains(device)) if (cachedValues.contains(device))
continue; continue;
qCInfo(LOG_AW) << "Found new key" << device << "for type" << type; qCInfo(LOG_AW) << "Found new key" << device << "for type" << _type;
cachedValues.append(device); cachedValues.append(device);
cache.setValue( cache.setValue(QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')), device);
QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')),
device);
} }
} else if (type == QString("net")) { } else if (_type == "net") {
QList<QNetworkInterface> rawInterfaceList QList<QNetworkInterface> rawInterfaceList = QNetworkInterface::allInterfaces();
= QNetworkInterface::allInterfaces(); for (auto &interface : rawInterfaceList) {
for (auto interface : rawInterfaceList) {
QString device = interface.name(); QString device = interface.name();
if (cachedValues.contains(device)) if (cachedValues.contains(device))
continue; continue;
qCInfo(LOG_AW) << "Found new key" << device << "for type" << type; qCInfo(LOG_AW) << "Found new key" << device << "for type" << _type;
cachedValues.append(device); cachedValues.append(device);
cache.setValue( cache.setValue(QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')), device);
QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')),
device);
} }
} else { } else {
if (cachedValues.contains(key)) if (cachedValues.contains(_key))
return false; return false;
qCInfo(LOG_AW) << "Found new key" << key << "for type" << type; qCInfo(LOG_AW) << "Found new key" << _key << "for type" << _type;
cache.setValue( cache.setValue(QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')), _key);
QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')), key);
} }
cache.endGroup(); cache.endGroup();
@ -83,103 +75,98 @@ bool AWKeyCache::addKeyToCache(const QString type, const QString key)
} }
QStringList AWKeyCache::getRequiredKeys(const QStringList &keys, QStringList AWKeyCache::getRequiredKeys(const QStringList &_keys, const QStringList &_bars, const QVariantMap &_tooltip,
const QStringList &bars, const QStringList &_userKeys, const QStringList &_allKeys)
const QVariantMap &tooltip,
const QStringList &allKeys)
{ {
qCDebug(LOG_AW) << "Looking for required keys in" << keys << bars qCDebug(LOG_AW) << "Looking for required keys in" << _keys << _bars << "using tooltip settings" << _tooltip;
<< "using tooltip settings" << tooltip;
// initial copy // initial copy
QSet<QString> used = QSet<QString>::fromList(keys); QSet<QString> used(_keys.cbegin(), _keys.cend());
used.unite(QSet<QString>::fromList(bars)); used.unite(QSet(_bars.cbegin(), _bars.cend()));
used.unite(QSet(_userKeys.cbegin(), _userKeys.cend()));
// insert keys from tooltip // insert keys from tooltip
for (auto key : tooltip.keys()) { for (auto &key : _tooltip.keys()) {
if ((key.endsWith(QString("Tooltip"))) && (tooltip[key].toBool())) { if ((key.endsWith("Tooltip")) && (_tooltip[key].toBool())) {
key.remove(QString("Tooltip")); key.remove("Tooltip");
used << key; used << key;
} }
} }
// insert depending keys, refer to AWKeys::calculateValues() // insert depending keys, refer to AWKeys::calculateValues()
// hddtotmb* // hddtotmb*
for (auto key : allKeys.filter(QRegExp(QString("^hddtotmb")))) { for (auto &key : _allKeys.filter(QRegularExpression("^hddtotmb"))) {
if (!used.contains(key)) if (!used.contains(key))
continue; continue;
key.remove(QString("hddtotmb")); key.remove("hddtotmb");
int index = key.toInt(); int index = key.toInt();
used << QString("hddfreemb%1").arg(index) used << QString("hddfreemb%1").arg(index) << QString("hddmb%1").arg(index);
<< QString("hddmb%1").arg(index);
} }
// hddtotgb* // hddtotgb*
for (auto key : allKeys.filter(QRegExp(QString("^hddtotgb")))) { for (auto &key : _allKeys.filter(QRegularExpression("^hddtotgb"))) {
if (!used.contains(key)) if (!used.contains(key))
continue; continue;
key.remove(QString("hddtotgb")); key.remove("hddtotgb");
int index = key.toInt(); int index = key.toInt();
used << QString("hddfreegb%1").arg(index) used << QString("hddfreegb%1").arg(index) << QString("hddgb%1").arg(index);
<< QString("hddgb%1").arg(index);
} }
// mem // mem
if (used.contains(QString("mem"))) if (used.contains("mem"))
used << QString("memmb") << QString("memtotmb"); used << "memmb"
<< "memtotmb";
// memtotmb // memtotmb
if (used.contains(QString("memtotmb"))) if (used.contains("memtotmb"))
used << QString("memusedmb") << QString("memfreemb"); used << "memusedmb"
<< "memfreemb";
// memtotgb // memtotgb
if (used.contains(QString("memtotgb"))) if (used.contains("memtotgb"))
used << QString("memusedgb") << QString("memfreegb"); used << "memusedgb"
<< "memfreegb";
// swap // swap
if (used.contains(QString("swap"))) if (used.contains("swap"))
used << QString("swapmb") << QString("swaptotmb"); used << "swapmb"
<< "swaptotmb";
// swaptotmb // swaptotmb
if (used.contains(QString("swaptotmb"))) if (used.contains("swaptotmb"))
used << QString("swapmb") << QString("swapfreemb"); used << "swapmb"
<< "swapfreemb";
// memtotgb // memtotgb
if (used.contains(QString("swaptotgb"))) if (used.contains("swaptotgb"))
used << QString("swapgb") << QString("swapfreegb"); used << "swapgb"
<< "swapfreegb";
// network keys // network keys
QStringList netKeys(QStringList() QStringList netKeys(
<< QString("up") << QString("upkb") {"up", "upkb", "uptot", "uptotkb", "upunits", "down", "downkb", "downtot", "downtotkb", "downunits"});
<< QString("uptotal") << QString("uptotalkb") for (auto &key : netKeys) {
<< QString("upunits") << QString("down")
<< QString("downkb") << QString("downtotal")
<< QString("downtotalkb") << QString("downunits"));
for (auto key : netKeys) {
if (!used.contains(key)) if (!used.contains(key))
continue; continue;
QStringList filt QStringList filt = _allKeys.filter(QRegularExpression(QString("^%1[0-9]{1,}").arg(key)));
= allKeys.filter(QRegExp(QString("^%1[0-9]{1,}").arg(key))); for (auto &filtered : filt)
for (auto filtered : filt)
used << filtered; used << filtered;
} }
// netdev key // netdev key
if (std::any_of(netKeys.cbegin(), netKeys.cend(), if (std::any_of(netKeys.cbegin(), netKeys.cend(), [&used](const QString &key) { return used.contains(key); }))
[&used](const QString &key) { return used.contains(key); })) used << "netdev";
used << QString("netdev");
// HACK append dummy if there are no other keys. This hack is required // HACK append dummy if there are no other keys. This hack is required
// because empty list leads to the same behaviour as skip checking // because empty list leads to the same behaviour as skip checking
if (used.isEmpty()) if (used.isEmpty())
used << QString("dummy"); used << "dummy";
return used.toList(); return used.values();
} }
QHash<QString, QStringList> AWKeyCache::loadKeysFromCache() QHash<QString, QStringList> AWKeyCache::loadKeysFromCache()
{ {
QString fileName = QString("%1/awesomewidgets.ndx") QString fileName
.arg(QStandardPaths::writableLocation( = QString("%1/awesomewidgets.ndx").arg(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation));
QStandardPaths::GenericCacheLocation));
qCInfo(LOG_AW) << "Cache file" << fileName; qCInfo(LOG_AW) << "Cache file" << fileName;
QSettings cache(fileName, QSettings::IniFormat); QSettings cache(fileName, QSettings::IniFormat);
QHash<QString, QStringList> devices; QHash<QString, QStringList> devices;
for (auto group : cache.childGroups()) { for (auto &group : cache.childGroups()) {
cache.beginGroup(group); cache.beginGroup(group);
for (auto key : cache.allKeys()) for (auto &key : cache.allKeys())
devices[group].append(cache.value(key).toString()); devices[group].append(cache.value(key).toString());
cache.endGroup(); cache.endGroup();
} }

View File

@ -26,12 +26,11 @@
namespace AWKeyCache namespace AWKeyCache
{ {
bool addKeyToCache(const QString type, const QString key = QString("")); bool addKeyToCache(const QString &_type, const QString &_key = "");
QStringList getRequiredKeys(const QStringList &keys, const QStringList &bars, QStringList getRequiredKeys(const QStringList &_keys, const QStringList &_bars, const QVariantMap &_tooltip,
const QVariantMap &tooltip, const QStringList &_userKeys, const QStringList &_allKeys);
const QStringList &allKeys);
QHash<QString, QStringList> loadKeysFromCache(); QHash<QString, QStringList> loadKeysFromCache();
}; } // namespace AWKeyCache
#endif /* AWKEYCACHE_H */ #endif /* AWKEYCACHE_H */

View File

@ -18,14 +18,15 @@
#include "awkeyoperations.h" #include "awkeyoperations.h"
#include <QDir> #include <QDir>
#include <QJSEngine> #include <QRegularExpression>
#include <QRegExp>
#include <QThread> #include <QThread>
#include "awcustomkeyshelper.h"
#include "awdebug.h" #include "awdebug.h"
#include "awkeycache.h" #include "awkeycache.h"
#include "awpatternfunctions.h" #include "awpatternfunctions.h"
// extensions // extensions
#include "extnetworkrequest.h"
#include "extquotes.h" #include "extquotes.h"
#include "extscript.h" #include "extscript.h"
#include "extupgrade.h" #include "extupgrade.h"
@ -33,31 +34,32 @@
#include "graphicalitem.h" #include "graphicalitem.h"
AWKeyOperations::AWKeyOperations(QObject *parent) AWKeyOperations::AWKeyOperations(QObject *_parent)
: QObject(parent) : QObject(_parent)
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
m_customKeys = new AWCustomKeysHelper(this);
m_graphicalItems = new ExtItemAggregator<GraphicalItem>(nullptr, "desktops");
m_extNetRequest = new ExtItemAggregator<ExtNetworkRequest>(nullptr, "requests");
m_extQuotes = new ExtItemAggregator<ExtQuotes>(nullptr, "quotes");
m_extScripts = new ExtItemAggregator<ExtScript>(nullptr, "scripts");
m_extUpgrade = new ExtItemAggregator<ExtUpgrade>(nullptr, "upgrade");
m_extWeather = new ExtItemAggregator<ExtWeather>(nullptr, "weather");
} }
AWKeyOperations::~AWKeyOperations() AWKeyOperations::~AWKeyOperations()
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
// extensions
delete m_graphicalItems;
delete m_extQuotes;
delete m_extScripts;
delete m_extUpgrade;
delete m_extWeather;
} }
QStringList AWKeyOperations::devices(const QString type) const QStringList AWKeyOperations::devices(const QString &_type) const
{ {
qCDebug(LOG_AW) << "Looking for type" << type; qCDebug(LOG_AW) << "Looking for type" << _type;
return m_devices[type]; return m_devices[_type];
} }
@ -70,8 +72,8 @@ QHash<QString, QStringList> AWKeyOperations::devices() const
void AWKeyOperations::updateCache() void AWKeyOperations::updateCache()
{ {
// update network and hdd list // update network and hdd list
addKeyToCache(QString("hdd")); addKeyToCache("hdd");
addKeyToCache(QString("net")); addKeyToCache("net");
} }
@ -79,30 +81,24 @@ QStringList AWKeyOperations::dictKeys() const
{ {
QStringList allKeys; QStringList allKeys;
// weather // weather
for (int i = m_extWeather->activeItems().count() - 1; i >= 0; i--) { for (auto &item : m_extWeather->activeItems()) {
allKeys.append( allKeys.append(item->tag("weatherId"));
m_extWeather->activeItems().at(i)->tag(QString("weatherId"))); allKeys.append(item->tag("weather"));
allKeys.append( allKeys.append(item->tag("humidity"));
m_extWeather->activeItems().at(i)->tag(QString("weather"))); allKeys.append(item->tag("pressure"));
allKeys.append( allKeys.append(item->tag("temperature"));
m_extWeather->activeItems().at(i)->tag(QString("humidity"))); allKeys.append(item->tag("timestamp"));
allKeys.append(
m_extWeather->activeItems().at(i)->tag(QString("pressure")));
allKeys.append(
m_extWeather->activeItems().at(i)->tag(QString("temperature")));
allKeys.append(
m_extWeather->activeItems().at(i)->tag(QString("timestamp")));
} }
// cpuclock & cpu // cpuclock & cpu
for (int i = QThread::idealThreadCount() - 1; i >= 0; i--) { for (int i = 0; i < QThread::idealThreadCount(); i++) {
allKeys.append(QString("cpucl%1").arg(i)); allKeys.append(QString("cpucl%1").arg(i));
allKeys.append(QString("cpu%1").arg(i)); allKeys.append(QString("cpu%1").arg(i));
} }
// temperature // temperature
for (int i = m_devices[QString("temp")].count() - 1; i >= 0; i--) for (int i = 0; i < m_devices["temp"].count(); i++)
allKeys.append(QString("temp%1").arg(i)); allKeys.append(QString("temp%1").arg(i));
// hdd // hdd
for (int i = m_devices[QString("mount")].count() - 1; i >= 0; i--) { for (int i = 0; i < m_devices["mount"].count(); i++) {
allKeys.append(QString("hddmb%1").arg(i)); allKeys.append(QString("hddmb%1").arg(i));
allKeys.append(QString("hddgb%1").arg(i)); allKeys.append(QString("hddgb%1").arg(i));
allKeys.append(QString("hddfreemb%1").arg(i)); allKeys.append(QString("hddfreemb%1").arg(i));
@ -112,67 +108,66 @@ QStringList AWKeyOperations::dictKeys() const
allKeys.append(QString("hdd%1").arg(i)); allKeys.append(QString("hdd%1").arg(i));
} }
// hdd speed // hdd speed
for (int i = m_devices[QString("disk")].count() - 1; i >= 0; i--) { for (int i = 0; i < m_devices["disk"].count(); i++) {
allKeys.append(QString("hddr%1").arg(i)); allKeys.append(QString("hddr%1").arg(i));
allKeys.append(QString("hddw%1").arg(i)); allKeys.append(QString("hddw%1").arg(i));
} }
// hdd temp // hdd temp
for (int i = m_devices[QString("hdd")].count() - 1; i >= 0; i--) for (int i = 0; i < m_devices["hdd"].count(); i++)
allKeys.append(QString("hddtemp%1").arg(i)); allKeys.append(QString("hddtemp%1").arg(i));
// network // network
for (int i = m_devices[QString("net")].count() - 1; i >= 0; i--) { for (int i = 0; i < m_devices["net"].count(); i++) {
allKeys.append(QString("downunits%1").arg(i)); allKeys.append(QString("downunits%1").arg(i));
allKeys.append(QString("upunits%1").arg(i)); allKeys.append(QString("upunits%1").arg(i));
allKeys.append(QString("downtotalkb%1").arg(i)); allKeys.append(QString("downtotkb%1").arg(i));
allKeys.append(QString("downtotal%1").arg(i)); allKeys.append(QString("downtot%1").arg(i));
allKeys.append(QString("downkb%1").arg(i)); allKeys.append(QString("downkb%1").arg(i));
allKeys.append(QString("down%1").arg(i)); allKeys.append(QString("down%1").arg(i));
allKeys.append(QString("uptotalkb%1").arg(i)); allKeys.append(QString("uptotkb%1").arg(i));
allKeys.append(QString("uptotal%1").arg(i)); allKeys.append(QString("uptot%1").arg(i));
allKeys.append(QString("upkb%1").arg(i)); allKeys.append(QString("upkb%1").arg(i));
allKeys.append(QString("up%1").arg(i)); allKeys.append(QString("up%1").arg(i));
} }
// battery // battery
QStringList allBatteryDevices QStringList allBatteryDevices
= QDir(QString("/sys/class/power_supply")) = QDir("/sys/class/power_supply")
.entryList(QStringList() << QString("BAT*"), .entryList(QStringList({"BAT*"}), QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); for (int i = 0; i < allBatteryDevices.count(); i++) {
for (int i = allBatteryDevices.count() - 1; i >= 0; i--)
allKeys.append(QString("bat%1").arg(i)); allKeys.append(QString("bat%1").arg(i));
allKeys.append(QString("batleft%1").arg(i));
allKeys.append(QString("batnow%1").arg(i));
allKeys.append(QString("batrate%1").arg(i));
allKeys.append(QString("battotal%1").arg(i));
}
// package manager // package manager
for (int i = m_extUpgrade->activeItems().count() - 1; i >= 0; i--) for (auto &item : m_extUpgrade->activeItems())
allKeys.append( allKeys.append(item->tag("pkgcount"));
m_extUpgrade->activeItems().at(i)->tag(QString("pkgcount")));
// quotes // quotes
for (int i = m_extQuotes->activeItems().count() - 1; i >= 0; i--) { for (auto &item : m_extQuotes->activeItems()) {
allKeys.append(m_extQuotes->activeItems().at(i)->tag(QString("ask"))); allKeys.append(item->tag("price"));
allKeys.append( allKeys.append(item->tag("pricechg"));
m_extQuotes->activeItems().at(i)->tag(QString("askchg"))); allKeys.append(item->tag("percpricechg"));
allKeys.append( allKeys.append(item->tag("volume"));
m_extQuotes->activeItems().at(i)->tag(QString("percaskchg"))); allKeys.append(item->tag("volumechg"));
allKeys.append(m_extQuotes->activeItems().at(i)->tag(QString("bid"))); allKeys.append(item->tag("percvolumechg"));
allKeys.append(
m_extQuotes->activeItems().at(i)->tag(QString("bidchg")));
allKeys.append(
m_extQuotes->activeItems().at(i)->tag(QString("percbidchg")));
allKeys.append(m_extQuotes->activeItems().at(i)->tag(QString("price")));
allKeys.append(
m_extQuotes->activeItems().at(i)->tag(QString("pricechg")));
allKeys.append(
m_extQuotes->activeItems().at(i)->tag(QString("percpricechg")));
} }
// custom // custom
for (int i = m_extScripts->activeItems().count() - 1; i >= 0; i--) for (auto &item : m_extScripts->activeItems())
allKeys.append( allKeys.append(item->tag("custom"));
m_extScripts->activeItems().at(i)->tag(QString("custom"))); // network requests
for (auto &item : m_extNetRequest->activeItems())
allKeys.append(item->tag("response"));
// bars // bars
for (int i = m_graphicalItems->activeItems().count() - 1; i >= 0; i--) for (auto &item : m_graphicalItems->activeItems())
allKeys.append( allKeys.append(item->tag("bar"));
m_graphicalItems->activeItems().at(i)->tag(QString("bar"))); // user defined keys
allKeys.append(m_customKeys->keys());
// static keys // static keys
QStringList staticKeys = QString(STATIC_KEYS).split(QChar(',')); allKeys.append(QString(STATIC_KEYS).split(','));
std::for_each(staticKeys.cbegin(), staticKeys.cend(),
[&allKeys](const QString &key) { allKeys.append(key); }); // sort in valid order
allKeys.sort();
std::reverse(allKeys.begin(), allKeys.end());
return allKeys; return allKeys;
} }
@ -180,66 +175,86 @@ QStringList AWKeyOperations::dictKeys() const
// this method is required to provide GraphicalItem functions (e.g. paint()) to // this method is required to provide GraphicalItem functions (e.g. paint()) to
// parent classes // parent classes
GraphicalItem *AWKeyOperations::giByKey(const QString key) const GraphicalItem *AWKeyOperations::giByKey(const QString &_key) const
{ {
qCDebug(LOG_AW) << "Looking for item" << key; qCDebug(LOG_AW) << "Looking for item" << _key;
return m_graphicalItems->itemByTag(key, QString("bar")); return m_graphicalItems->itemByTag(_key, "bar");
} }
QString AWKeyOperations::infoByKey(QString key) const QStringList AWKeyOperations::requiredUserKeys() const
{ {
qCDebug(LOG_AW) << "Requested key" << key; return m_customKeys->refinedSources();
}
QString stripped = key;
stripped.remove(QRegExp(QString("\\d+"))); QStringList AWKeyOperations::userKeys() const
{
return m_customKeys->keys();
}
QString AWKeyOperations::userKeySource(const QString &_key) const
{
return m_customKeys->source(_key);
}
QString AWKeyOperations::infoByKey(const QString &_key) const
{
qCDebug(LOG_AW) << "Requested key" << _key;
QString stripped = _key;
stripped.remove(QRegularExpression("\\d+"));
QString output; QString output;
if (key.startsWith(QString("bar"))) { if (_key.startsWith("bar")) {
AbstractExtItem *item = m_graphicalItems->itemByTag(key, stripped); AbstractExtItem *item = m_graphicalItems->itemByTag(_key, stripped);
if (item) if (item)
output = item->uniq(); output = item->uniq();
} else if (key.startsWith(QString("custom"))) { } else if (_key.startsWith("custom")) {
AbstractExtItem *item = m_extScripts->itemByTag(key, stripped); AbstractExtItem *item = m_extScripts->itemByTag(_key, stripped);
if (item) if (item)
output = item->uniq(); output = item->uniq();
} else if (key.contains(QRegExp(QString("^hdd[rw]")))) { } else if (_key.contains(QRegularExpression("^hdd[rw]"))) {
output = m_devices[QString("disk")] QString index = _key;
[key.remove(QRegExp(QString("hdd[rw]"))).toInt()]; index.remove(QRegularExpression("hdd[rw]"));
} else if (key.contains(QRegExp( output = m_devices["disk"][index.toInt()];
QString("^hdd([0-9]|mb|gb|freemb|freegb|totmb|totgb)")))) { } else if (_key.contains(QRegularExpression("^hdd([0-9]|mb|gb|freemb|freegb|totmb|totgb)"))) {
output QString index = _key;
= m_devices[QString("mount")] index.remove(QRegularExpression("^hdd(|mb|gb|freemb|freegb|totmb|totgb)"));
[key output = m_devices["mount"][index.toInt()];
.remove(QRegExp(QString( } else if (_key.startsWith("hddtemp")) {
"^hdd([0-9]|mb|gb|freemb|freegb|totmb|totgb)"))) QString index = _key;
.toInt()]; index.remove("hddtemp");
} else if (key.startsWith(QString("hddtemp"))) { output = m_devices["hdd"][index.toInt()];
output } else if (_key.contains(QRegularExpression("^(down|up)[0-9]"))) {
= m_devices[QString("hdd")][key.remove(QString("hddtemp")).toInt()]; QString index = _key;
} else if (key.contains(QRegExp(QString("^(down|up)[0-9]")))) { index.remove(QRegularExpression("^(down|up)"));
output = m_devices[QString("net")] output = m_devices["net"][index.toInt()];
[key.remove(QRegExp(QString("^(down|up)"))).toInt()]; } else if (_key.startsWith("pkgcount")) {
} else if (key.startsWith(QString("pkgcount"))) { AbstractExtItem *item = m_extUpgrade->itemByTag(_key, stripped);
AbstractExtItem *item = m_extUpgrade->itemByTag(key, stripped);
if (item) if (item)
output = item->uniq(); output = item->uniq();
} else if (key.contains( } else if (_key.contains(QRegularExpression("(^|perc)(ask|bid|price)(chg|)"))) {
QRegExp(QString("(^|perc)(ask|bid|price)(chg|)")))) { AbstractExtItem *item = m_extQuotes->itemByTag(_key, stripped);
AbstractExtItem *item = m_extQuotes->itemByTag(key, stripped);
if (item) if (item)
output = item->uniq(); output = item->uniq();
} else if (key.contains(QRegExp(QString( } else if (_key.contains(QRegularExpression("(weather|weatherId|humidity|pressure|temperature)"))) {
"(weather|weatherId|humidity|pressure|temperature)")))) { AbstractExtItem *item = m_extWeather->itemByTag(_key, stripped);
AbstractExtItem *item = m_extWeather->itemByTag(key, stripped); if (item)
output = item->uniq();
} else if (_key.startsWith("temp")) {
QString index = _key;
index.remove("temp");
output = m_devices["temp"][index.toInt()];
} else if (_key.startsWith("response")) {
AbstractExtItem *item = m_extNetRequest->itemByTag(_key, stripped);
if (item) if (item)
output = item->uniq(); output = item->uniq();
} else if (key.startsWith(QString("temp"))) {
output
= m_devices[QString("temp")][key.remove(QString("temp")).toInt()];
} else { } else {
output = QString("(none)"); output = "(none)";
} }
return output; return output;
@ -252,63 +267,65 @@ QString AWKeyOperations::pattern() const
} }
void AWKeyOperations::setPattern(const QString currentPattern) void AWKeyOperations::setPattern(const QString &_currentPattern)
{ {
qCDebug(LOG_AW) << "Set pattern" << currentPattern; qCDebug(LOG_AW) << "Set pattern" << _currentPattern;
m_pattern = currentPattern; m_pattern = _currentPattern;
} }
void AWKeyOperations::editItem(const QString type) void AWKeyOperations::editItem(const QString &_type)
{ {
qCDebug(LOG_AW) << "Item type" << type; qCDebug(LOG_AW) << "Item type" << _type;
if (type == QString("graphicalitem")) { if (_type == "graphicalitem") {
QStringList keys = dictKeys().filter(QRegExp( QStringList keys = dictKeys().filter(QRegularExpression("^(cpu(?!cl).*|gpu$|mem$|swap$|hdd[0-9].*|bat.*)"));
QString("^(cpu(?!cl).*|gpu$|mem$|swap$|hdd[0-9].*|bat.*)")));
keys.sort(); keys.sort();
m_graphicalItems->setConfigArgs(keys); m_graphicalItems->setConfigArgs(keys);
return m_graphicalItems->editItems(); return m_graphicalItems->editItems();
} else if (type == QString("extquotes")) { } else if (_type == "extnetworkrequest") {
return m_extNetRequest->editItems();
} else if (_type == "extquotes") {
return m_extQuotes->editItems(); return m_extQuotes->editItems();
} else if (type == QString("extscript")) { } else if (_type == "extscript") {
return m_extScripts->editItems(); return m_extScripts->editItems();
} else if (type == QString("extupgrade")) { } else if (_type == "extupgrade") {
return m_extUpgrade->editItems(); return m_extUpgrade->editItems();
} else if (type == QString("extweather")) { } else if (_type == "extweather") {
return m_extWeather->editItems(); return m_extWeather->editItems();
} }
} }
void AWKeyOperations::addDevice(const QString &source) void AWKeyOperations::addDevice(const QString &_source)
{ {
qCDebug(LOG_AW) << "Source" << source; qCDebug(LOG_AW) << "Source" << _source;
QRegExp diskRegexp auto diskRegexp = QRegularExpression("disk/.*/read");
= QRegExp(QString("disk/(?:md|sd|hd)[a-z|0-9]_.*/Rate/(?:rblk)")); auto mountRegexp = QRegularExpression("disk/.*/usedPercent");
QRegExp mountRegexp = QRegExp(QString("partitions/.*/filllevel")); auto cpuTempRegExp = QRegularExpression("^cpu/cpu.*/temperature$");
if (source.contains(diskRegexp)) { if (_source.contains(diskRegexp)) {
QString device = source; auto device = _source;
device.remove(QString("/Rate/rblk")); device.remove("disk/").remove("/read");
addKeyToCache(QString("disk"), device); addKeyToCache("disk", device);
} else if (source.contains(mountRegexp)) { } else if (_source.contains(mountRegexp)) {
QString device = source; auto device = _source;
device.remove(QString("partitions")).remove(QString("/filllevel")); device.remove("disk/").remove("/usedPercent");
addKeyToCache(QString("mount"), device); addKeyToCache("mount", device);
} else if (source.startsWith(QString("lmsensors"))) { } else if (_source.startsWith("lmsensors") || _source.contains(cpuTempRegExp)
addKeyToCache(QString("temp"), source); || _source == "cpu/all/averageTemperature") {
addKeyToCache("temp", _source);
} }
} }
void AWKeyOperations::addKeyToCache(const QString type, const QString key) void AWKeyOperations::addKeyToCache(const QString &_type, const QString &_key)
{ {
qCDebug(LOG_AW) << "Key" << key << "with type" << type; qCDebug(LOG_AW) << "Key" << _key << "with type" << _type;
if (AWKeyCache::addKeyToCache(type, key)) { if (AWKeyCache::addKeyToCache(_type, _key)) {
m_devices = AWKeyCache::loadKeysFromCache(); m_devices = AWKeyCache::loadKeysFromCache();
reinitKeys(); reinitKeys();
} }
@ -317,28 +334,13 @@ void AWKeyOperations::addKeyToCache(const QString type, const QString key)
void AWKeyOperations::reinitKeys() void AWKeyOperations::reinitKeys()
{ {
// renew extensions m_customKeys->initItems();
// delete them if any m_graphicalItems->initItems();
delete m_graphicalItems; m_extNetRequest->initItems();
m_graphicalItems = nullptr; m_extQuotes->initItems();
delete m_extQuotes; m_extScripts->initItems();
m_extQuotes = nullptr; m_extUpgrade->initItems();
delete m_extScripts; m_extWeather->initItems();
m_extScripts = nullptr;
delete m_extUpgrade;
m_extUpgrade = nullptr;
delete m_extWeather;
m_extWeather = nullptr;
// create
m_graphicalItems
= new ExtItemAggregator<GraphicalItem>(nullptr, QString("desktops"));
m_extQuotes = new ExtItemAggregator<ExtQuotes>(nullptr, QString("quotes"));
m_extScripts
= new ExtItemAggregator<ExtScript>(nullptr, QString("scripts"));
m_extUpgrade
= new ExtItemAggregator<ExtUpgrade>(nullptr, QString("upgrade"));
m_extWeather
= new ExtItemAggregator<ExtWeather>(nullptr, QString("weather"));
// init // init
QStringList allKeys = dictKeys(); QStringList allKeys = dictKeys();

View File

@ -19,23 +19,18 @@
#ifndef AWKEYOPERATIONS_H #ifndef AWKEYOPERATIONS_H
#define AWKEYOPERATIONS_H #define AWKEYOPERATIONS_H
#include <Plasma/DataEngine>
#include <QMutex>
#include <QObject> #include <QObject>
#include "extitemaggregator.h" #include "extitemaggregator.h"
class AWDataAggregator; class AWCustomKeysHelper;
class AWDataEngineAggregator; class ExtNetworkRequest;
class AWKeysAggregator;
class ExtQuotes; class ExtQuotes;
class ExtScript; class ExtScript;
class ExtUpgrade; class ExtUpgrade;
class ExtWeather; class ExtWeather;
class GraphicalItem; class GraphicalItem;
class QThreadPool;
class AWKeyOperations : public QObject class AWKeyOperations : public QObject
{ {
@ -43,33 +38,38 @@ class AWKeyOperations : public QObject
Q_PROPERTY(QString pattern READ pattern WRITE setPattern) Q_PROPERTY(QString pattern READ pattern WRITE setPattern)
public: public:
explicit AWKeyOperations(QObject *parent = nullptr); explicit AWKeyOperations(QObject *_parent = nullptr);
virtual ~AWKeyOperations(); ~AWKeyOperations() override;
QStringList devices(const QString type) const; [[nodiscard]] QStringList devices(const QString &_type) const;
QHash<QString, QStringList> devices() const; [[nodiscard]] QHash<QString, QStringList> devices() const;
void updateCache(); void updateCache();
// keys // keys
QStringList dictKeys() const; [[nodiscard]] QStringList dictKeys() const;
GraphicalItem *giByKey(const QString key) const; [[nodiscard]] GraphicalItem *giByKey(const QString &_key) const;
[[nodiscard]] QStringList requiredUserKeys() const;
[[nodiscard]] QStringList userKeys() const;
[[nodiscard]] QString userKeySource(const QString &_key) const;
// values // values
QString infoByKey(QString key) const; [[nodiscard]] QString infoByKey(const QString &_key) const;
QString pattern() const; [[nodiscard]] QString pattern() const;
void setPattern(const QString currentPattern); void setPattern(const QString &_currentPattern);
// configuration // configuration
void editItem(const QString type); void editItem(const QString &_type);
signals: signals:
void updateKeys(const QStringList currentKeys); void updateKeys(const QStringList &_currentKeys);
public slots: public slots:
void addDevice(const QString &source); void addDevice(const QString &_source);
private: private:
// methods // methods
void addKeyToCache(const QString type, const QString key = QString("")); void addKeyToCache(const QString &_type, const QString &_key = "");
void reinitKeys(); void reinitKeys();
// objects // objects
AWCustomKeysHelper *m_customKeys = nullptr;
ExtItemAggregator<GraphicalItem> *m_graphicalItems = nullptr; ExtItemAggregator<GraphicalItem> *m_graphicalItems = nullptr;
ExtItemAggregator<ExtNetworkRequest> *m_extNetRequest = nullptr;
ExtItemAggregator<ExtQuotes> *m_extQuotes = nullptr; ExtItemAggregator<ExtQuotes> *m_extQuotes = nullptr;
ExtItemAggregator<ExtScript> *m_extScripts = nullptr; ExtItemAggregator<ExtScript> *m_extScripts = nullptr;
ExtItemAggregator<ExtUpgrade> *m_extUpgrade = nullptr; ExtItemAggregator<ExtUpgrade> *m_extUpgrade = nullptr;

View File

@ -17,14 +17,15 @@
#include "awkeys.h" #include "awkeys.h"
#include <QJSEngine> #include <QDBusConnection>
#include <QRegExp> #include <QDBusError>
#include <QThread> #include <QThread>
#include <QTimer> #include <QTimer>
#include <QtConcurrent/QtConcurrent> #include <QtConcurrent/QtConcurrent>
#include "awdataaggregator.h" #include "awdataaggregator.h"
#include "awdataengineaggregator.h" #include "awdataengineaggregator.h"
#include "awdbusadaptor.h"
#include "awdebug.h" #include "awdebug.h"
#include "awkeycache.h" #include "awkeycache.h"
#include "awkeyoperations.h" #include "awkeyoperations.h"
@ -33,12 +34,12 @@
#include "graphicalitem.h" #include "graphicalitem.h"
AWKeys::AWKeys(QObject *parent) AWKeys::AWKeys(QObject *_parent)
: QObject(parent) : QObject(_parent)
{ {
qSetMessagePattern(LOG_FORMAT); qSetMessagePattern(AWDebug::LOG_FORMAT);
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
for (auto metadata : getBuildData()) for (auto &metadata : AWDebug::getBuildData())
qCDebug(LOG_AW) << metadata; qCDebug(LOG_AW) << metadata;
// thread pool // thread pool
@ -52,18 +53,20 @@ AWKeys::AWKeys(QObject *parent)
m_timer = new QTimer(this); m_timer = new QTimer(this);
m_timer->setSingleShot(false); m_timer->setSingleShot(false);
createDBusInterface();
// update key data if required // update key data if required
connect(m_keyOperator, SIGNAL(updateKeys(QStringList)), this, connect(m_keyOperator, &AWKeyOperations::updateKeys, this, &AWKeys::reinitKeys);
SLOT(reinitKeys(QStringList))); connect(m_timer, &QTimer::timeout, this, &AWKeys::updateTextData);
connect(m_timer, SIGNAL(timeout()), this, SLOT(updateTextData()));
// transfer signal from AWDataAggregator object to QML ui // transfer signal from AWDataAggregator object to QML ui
connect(m_dataAggregator, SIGNAL(toolTipPainted(const QString)), this, connect(m_dataAggregator, &AWDataAggregator::toolTipPainted,
SIGNAL(needToolTipToBeUpdated(const QString))); [this](const QString &_tooltip) { emit(needToolTipToBeUpdated(_tooltip)); });
connect(this, SIGNAL(dropSourceFromDataengine(QString)),
m_dataEngineAggregator, SLOT(dropSource(QString))); connect(this, &AWKeys::dropSourceFromDataengine, m_dataEngineAggregator, &AWDataEngineAggregator::dropSource);
connect(m_dataEngineAggregator, &AWDataEngineAggregator::dataUpdated, this, &AWKeys::dataUpdated);
// transfer signal from dataengine to update source list // transfer signal from dataengine to update source list
connect(m_dataEngineAggregator, SIGNAL(deviceAdded(const QString &)), connect(m_dataEngineAggregator, &AWDataEngineAggregator::deviceAdded, m_keyOperator, &AWKeyOperations::addDevice);
m_keyOperator, SLOT(addDevice(const QString &)));
} }
@ -72,64 +75,54 @@ AWKeys::~AWKeys()
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
m_timer->stop(); m_timer->stop();
delete m_timer; // delete dbus session
auto id = reinterpret_cast<qlonglong>(this);
// core QDBusConnection::sessionBus().unregisterObject(QString("/%1").arg(id));
delete m_dataEngineAggregator;
delete m_threadPool;
delete m_aggregator;
delete m_dataAggregator;
delete m_keyOperator;
} }
void AWKeys::initDataAggregator(const QVariantMap tooltipParams) void AWKeys::initDataAggregator(const QVariantMap &_tooltipParams)
{ {
qCDebug(LOG_AW) << "Tooltip parameters" << tooltipParams; qCDebug(LOG_AW) << "Tooltip parameters" << _tooltipParams;
// store parameters to generate m_requiredKeys // store parameters to generate m_requiredKeys
m_tooltipParams = tooltipParams; m_tooltipParams = _tooltipParams;
m_dataAggregator->setParameters(m_tooltipParams); m_dataAggregator->setParameters(m_tooltipParams);
} }
void AWKeys::initKeys(const QString currentPattern, const int interval, void AWKeys::initKeys(const QString &_currentPattern, const int _interval, const int _limit, const bool _optimize)
const int limit, const bool optimize)
{ {
qCDebug(LOG_AW) << "Pattern" << currentPattern << "with interval" qCDebug(LOG_AW) << "Pattern" << _currentPattern << "with interval" << _interval << "and queue limit" << _limit
<< interval << "and queue limit" << limit << "with optimization" << _optimize;
<< "with optimization" << optimize;
// init // init
m_optimize = optimize; m_optimize = _optimize;
m_threadPool->setMaxThreadCount(limit == 0 ? QThread::idealThreadCount() m_threadPool->setMaxThreadCount(_limit == 0 ? QThread::idealThreadCount() : _limit);
: limit);
// child objects // child objects
m_aggregator->initFormatters(); m_aggregator->initFormatters();
m_keyOperator->setPattern(currentPattern); m_keyOperator->setPattern(_currentPattern);
m_keyOperator->updateCache(); m_keyOperator->updateCache();
m_dataEngineAggregator->clear();
m_dataEngineAggregator->initDataEngines(interval);
// timer // timer
m_timer->setInterval(interval); m_timer->setInterval(_interval);
m_timer->start(); m_timer->start();
} }
void AWKeys::setAggregatorProperty(const QString key, const QVariant value) void AWKeys::setAggregatorProperty(const QString &_key, const QVariant &_value)
{ {
qCDebug(LOG_AW) << "Key" << key << "with value" << value; qCDebug(LOG_AW) << "Key" << _key << "with value" << _value;
m_aggregator->setProperty(key.toUtf8().constData(), value); m_aggregator->setProperty(_key.toUtf8().constData(), _value);
} }
void AWKeys::setWrapNewLines(const bool wrap) void AWKeys::setWrapNewLines(const bool _wrap)
{ {
qCDebug(LOG_AW) << "Is wrapping enabled" << wrap; qCDebug(LOG_AW) << "Is wrapping enabled" << _wrap;
m_wrapNewLines = wrap; m_wrapNewLines = _wrap;
} }
@ -139,94 +132,107 @@ void AWKeys::updateCache()
} }
QStringList AWKeys::dictKeys(const bool sorted, const QString regexp) const QStringList AWKeys::dictKeys(const bool _sorted, const QString &_regexp) const
{ {
qCDebug(LOG_AW) << "Should be sorted" << sorted << "and filter applied" qCDebug(LOG_AW) << "Should be sorted" << _sorted << "and filter applied" << _regexp;
<< regexp;
// check if functions asked
if (_regexp == "functions")
return QString(STATIC_FUNCTIONS).split(',');
// check if user defined keys asked
if (_regexp == "userdefined")
return m_keyOperator->userKeys();
QStringList allKeys = m_keyOperator->dictKeys(); QStringList allKeys = m_keyOperator->dictKeys();
// sort if required // sort if required
if (sorted) if (_sorted)
allKeys.sort(); allKeys.sort();
return allKeys.filter(QRegExp(regexp)); return allKeys.filter(QRegularExpression(_regexp));
} }
QStringList AWKeys::getHddDevices() const QVariantList AWKeys::getHddDevices() const
{ {
QStringList devices = m_keyOperator->devices(QString("hdd")); QStringList hddDevices = m_keyOperator->devices("hdd");
// required by selector in the UI // required by selector in the UI
devices.insert(0, QString("disable")); hddDevices.insert(0, "disable");
devices.insert(0, QString("auto")); hddDevices.insert(0, "auto");
// build model
QVariantList devices;
for (auto &device : hddDevices) {
QVariantMap model;
model["label"] = device;
model["name"] = device;
devices.append(model);
}
return devices; return devices;
} }
QString AWKeys::infoByKey(QString key) const QString AWKeys::infoByKey(const QString &_key) const
{ {
qCDebug(LOG_AW) << "Requested info for key" << key; qCDebug(LOG_AW) << "Requested info for key" << _key;
return m_keyOperator->infoByKey(key); return m_keyOperator->infoByKey(_key);
} }
// HACK this method requires to define tag value from bar from UI interface // HACK this method requires to define tag value from bar from UI interface
QString AWKeys::valueByKey(QString key) const QString AWKeys::valueByKey(const QString &_key) const
{ {
qCDebug(LOG_AW) << "Requested value for key" << key; qCDebug(LOG_AW) << "Requested value for key" << _key;
QString trueKey auto realKey = _key.startsWith("bar") ? m_keyOperator->infoByKey(_key) : _key;
= key.startsWith(QString("bar")) ? m_keyOperator->infoByKey(key) : key;
return m_aggregator->formatter(m_values[trueKey], trueKey); return m_aggregator->formatter(m_values[realKey], realKey, true);
} }
void AWKeys::editItem(const QString type) void AWKeys::editItem(const QString &_type)
{ {
qCDebug(LOG_AW) << "Item type" << type; qCDebug(LOG_AW) << "Item type" << _type;
return m_keyOperator->editItem(type); return m_keyOperator->editItem(_type);
} }
void AWKeys::dataUpdated(const QString &sourceName, void AWKeys::dataUpdated(const QHash<QString, KSysGuard::SensorInfo> &_sensors, const KSysGuard::SensorDataList &_data)
const Plasma::DataEngine::Data &data)
{ {
// run concurrent data update for (auto &single : _data) {
QtConcurrent::run(m_threadPool, this, &AWKeys::setDataBySource, sourceName, if (_sensors.contains(single.sensorProperty)) {
data); setDataBySource(single.sensorProperty, _sensors.value(single.sensorProperty), single);
}
// TODO use QtConcurrent::map or something like that
// QtConcurrent::run(m_threadPool, this, &AWKeys::setDataBySource, "ss", sensor);
}
} }
void AWKeys::reinitKeys(const QStringList currentKeys) void AWKeys::reinitKeys(const QStringList &_currentKeys)
{ {
qCDebug(LOG_AW) << "Update found keys by using list" << currentKeys; qCDebug(LOG_AW) << "Update found keys by using list" << _currentKeys;
// append lists // append lists
m_foundBars = AWPatternFunctions::findKeys(m_keyOperator->pattern(), m_foundBars = AWPatternFunctions::findKeys(m_keyOperator->pattern(), _currentKeys, true);
currentKeys, true); m_foundKeys = AWPatternFunctions::findKeys(m_keyOperator->pattern(), _currentKeys, false);
m_foundKeys = AWPatternFunctions::findKeys(m_keyOperator->pattern(),
currentKeys, false);
m_foundLambdas = AWPatternFunctions::findLambdas(m_keyOperator->pattern()); m_foundLambdas = AWPatternFunctions::findLambdas(m_keyOperator->pattern());
// generate list of required keys for bars // generate list of required keys for bars
QStringList barKeys; QStringList barKeys;
for (auto bar : m_foundBars) { for (auto &bar : m_foundBars) {
GraphicalItem *item = m_keyOperator->giByKey(bar); GraphicalItem *item = m_keyOperator->giByKey(bar);
if (item->isCustom()) if (item->isCustom())
item->setUsedKeys( item->setUsedKeys(AWPatternFunctions::findKeys(item->bar(), _currentKeys, false));
AWPatternFunctions::findKeys(item->bar(), currentKeys, false));
else else
item->setUsedKeys(QStringList() << item->bar()); item->setUsedKeys(QStringList() << item->bar());
barKeys.append(item->usedKeys()); barKeys.append(item->usedKeys());
} }
// get required keys // get required keys
m_requiredKeys m_requiredKeys = m_optimize ? AWKeyCache::getRequiredKeys(m_foundKeys, barKeys, m_tooltipParams,
= m_optimize ? AWKeyCache::getRequiredKeys(m_foundKeys, barKeys, m_keyOperator->requiredUserKeys(), _currentKeys)
m_tooltipParams, currentKeys) : QStringList();
: QStringList();
// set key data to m_aggregator // set key data to m_aggregator
m_aggregator->setDevices(m_keyOperator->devices()); m_aggregator->setDevices(m_keyOperator->devices());
@ -238,11 +244,12 @@ void AWKeys::updateTextData()
// do not do it in parallel to avoid race condition // do not do it in parallel to avoid race condition
m_mutex.lock(); m_mutex.lock();
calculateValues(); calculateValues();
QString text = parsePattern(m_keyOperator->pattern()); auto text = parsePattern(m_keyOperator->pattern());
// update tooltip values under lock
m_dataAggregator->dataUpdate(m_values);
m_mutex.unlock(); m_mutex.unlock();
emit(needTextToBeUpdated(text)); emit(needTextToBeUpdated(text));
emit(m_dataAggregator->updateData(m_values));
} }
@ -251,124 +258,121 @@ void AWKeys::updateTextData()
void AWKeys::calculateValues() void AWKeys::calculateValues()
{ {
// hddtot* // hddtot*
QStringList mountDevices = m_keyOperator->devices(QString("mount")); QStringList mountDevices = m_keyOperator->devices("mount");
for (auto device : mountDevices) { for (auto &device : mountDevices) {
int index = mountDevices.indexOf(device); int index = mountDevices.indexOf(device);
m_values[QString("hddtotmb%1").arg(index)] m_values[QString("hddtotmb%1").arg(index)] = m_values[QString("hddfreemb%1").arg(index)].toDouble()
= m_values[QString("hddfreemb%1").arg(index)].toFloat() + m_values[QString("hddmb%1").arg(index)].toDouble();
+ m_values[QString("hddmb%1").arg(index)].toFloat(); m_values[QString("hddtotgb%1").arg(index)] = m_values[QString("hddfreegb%1").arg(index)].toDouble()
m_values[QString("hddtotgb%1").arg(index)] + m_values[QString("hddgb%1").arg(index)].toDouble();
= m_values[QString("hddfreegb%1").arg(index)].toFloat()
+ m_values[QString("hddgb%1").arg(index)].toFloat();
} }
// memtot* // memtot*
m_values[QString("memtotmb")] = m_values[QString("memusedmb")].toInt() m_values["memtotmb"] = m_values["memusedmb"].toLongLong() + m_values["memfreemb"].toLongLong();
+ m_values[QString("memfreemb")].toInt(); m_values["memtotgb"] = m_values["memusedgb"].toDouble() + m_values["memfreegb"].toDouble();
m_values[QString("memtotgb")] = m_values[QString("memusedgb")].toFloat()
+ m_values[QString("memfreegb")].toFloat();
// mem // mem
m_values[QString("mem")] = 100.0f * m_values[QString("memmb")].toFloat() m_values["mem"] = 100.0f * m_values["memmb"].toDouble() / m_values["memtotmb"].toDouble();
/ m_values[QString("memtotmb")].toFloat();
// up, down, upkb, downkb, upunits, downunits // up, down, upkb, downkb, upunits, downunits
int netIndex = m_keyOperator->devices(QString("net")) int netIndex = m_keyOperator->devices("net").indexOf(m_values["netdev"].toString());
.indexOf(m_values[QString("netdev")].toString()); m_values["down"] = m_values[QString("down%1").arg(netIndex)];
m_values[QString("down")] = m_values[QString("down%1").arg(netIndex)]; m_values["downkb"] = m_values[QString("downkb%1").arg(netIndex)];
m_values[QString("downkb")] = m_values[QString("downkb%1").arg(netIndex)]; m_values["downtot"] = m_values[QString("downtot%1").arg(netIndex)];
m_values[QString("downtotal")] m_values["downtotkb"] = m_values[QString("downtotkb%1").arg(netIndex)];
= m_values[QString("downtotal%1").arg(netIndex)]; m_values["downunits"] = m_values[QString("downunits%1").arg(netIndex)];
m_values[QString("downtotalkb")] m_values["up"] = m_values[QString("up%1").arg(netIndex)];
= m_values[QString("downtotalkb%1").arg(netIndex)]; m_values["upkb"] = m_values[QString("upkb%1").arg(netIndex)];
m_values[QString("downunits")] m_values["uptot"] = m_values[QString("uptot%1").arg(netIndex)];
= m_values[QString("downunits%1").arg(netIndex)]; m_values["uptotkb"] = m_values[QString("uptotkb%1").arg(netIndex)];
m_values[QString("up")] = m_values[QString("up%1").arg(netIndex)]; m_values["upunits"] = m_values[QString("upunits%1").arg(netIndex)];
m_values[QString("upkb")] = m_values[QString("upkb%1").arg(netIndex)];
m_values[QString("uptotal")] = m_values[QString("uptotal%1").arg(netIndex)];
m_values[QString("uptotalkb")]
= m_values[QString("uptotalkb%1").arg(netIndex)];
m_values[QString("upunits")] = m_values[QString("upunits%1").arg(netIndex)];
// swaptot* // swaptot*
m_values[QString("swaptotmb")] = m_values[QString("swapmb")].toInt() m_values["swaptotmb"] = m_values["swapmb"].toLongLong() + m_values["swapfreemb"].toLongLong();
+ m_values[QString("swapfreemb")].toInt(); m_values["swaptotgb"] = m_values["swapgb"].toDouble() + m_values["swapfreegb"].toDouble();
m_values[QString("swaptotgb")]
= m_values[QString("swapgb")].toFloat()
+ m_values[QString("swapfreegb")].toFloat();
// swap // swap
m_values[QString("swap")] = 100.0f * m_values[QString("swapmb")].toFloat() m_values["swap"] = 100.0f * m_values["swapmb"].toDouble() / m_values["swaptotmb"].toDouble();
/ m_values[QString("swaptotmb")].toFloat();
// user defined keys
for (auto &key : m_keyOperator->userKeys())
m_values[key] = m_values[m_keyOperator->userKeySource(key)];
// lambdas // lambdas
for (auto key : m_foundLambdas) for (auto &key : m_foundLambdas)
m_values[key] = AWPatternFunctions::expandLambdas( m_values[key] = AWPatternFunctions::expandLambdas(key, m_aggregator, m_values, m_foundKeys);
key, m_aggregator, m_values, m_foundKeys);
} }
QString AWKeys::parsePattern(QString pattern) const void AWKeys::createDBusInterface()
{
// get this object id
auto id = reinterpret_cast<qlonglong>(this);
// create session
QDBusConnection instanceBus = QDBusConnection::sessionBus();
// HACK we are going to use different services because it binds to
// application
if (instanceBus.registerService(QString("%1.i%2").arg(AWDBUS_SERVICE).arg(id))) {
if (!instanceBus.registerObject(AWDBUS_PATH, new AWDBusAdaptor(this), QDBusConnection::ExportAllContents))
qCWarning(LOG_AW) << "Could not register DBus object, last error" << instanceBus.lastError().message();
} else {
qCWarning(LOG_AW) << "Could not register DBus service, last error" << instanceBus.lastError().message();
}
// and same instance but for id independent service
QDBusConnection commonBus = QDBusConnection::sessionBus();
if (commonBus.registerService(AWDBUS_SERVICE))
commonBus.registerObject(AWDBUS_PATH, new AWDBusAdaptor(this), QDBusConnection::ExportAllContents);
}
QString AWKeys::parsePattern(QString _pattern) const
{ {
// screen sign // screen sign
pattern.replace(QString("$$"), QString(0x1d)); _pattern.replace("$$", QChar(0x1d));
// lambdas // lambdas
for (auto key : m_foundLambdas) for (auto &key : m_foundLambdas)
pattern.replace(QString("${{%1}}").arg(key), m_values[key].toString()); _pattern.replace(QString("${{%1}}").arg(key), m_values[key].toString());
// main keys // main keys
for (auto key : m_foundKeys) for (auto &key : m_foundKeys)
pattern.replace(QString("$%1").arg(key), [this](const QString &tag, _pattern.replace(QString("$%1").arg(key), m_aggregator->formatter(m_values[key], key, true));
const QVariant &value) {
QString strValue = m_aggregator->formatter(value, tag);
if ((!tag.startsWith(QString("custom")))
&& (!tag.startsWith(QString("weather"))))
strValue.replace(QString(" "), QString("&nbsp;"));
return strValue;
}(key, m_values[key]));
// bars // bars
for (auto bar : m_foundBars) { for (auto &bar : m_foundBars) {
GraphicalItem *item = m_keyOperator->giByKey(bar); GraphicalItem *item = m_keyOperator->giByKey(bar);
QString image QString image = item->isCustom() ? item->image(
= item->isCustom() AWPatternFunctions::expandLambdas(item->bar(), m_aggregator, m_values, item->usedKeys()))
? item->image(AWPatternFunctions::expandLambdas( : item->image(m_values[item->bar()]);
item->bar(), m_aggregator, m_values, item->usedKeys())) _pattern.replace(QString("$%1").arg(bar), image);
: item->image(m_values[item->bar()]);
pattern.replace(QString("$%1").arg(bar), image);
} }
// prepare strings // prepare strings
pattern.replace(QString(0x1d), QString("$")); _pattern.replace(QChar(0x1d), "$");
if (m_wrapNewLines) if (m_wrapNewLines)
pattern.replace(QString("\n"), QString("<br>")); _pattern.replace("\n", "<br>");
return pattern; return _pattern;
} }
void AWKeys::setDataBySource(const QString &sourceName, const QVariantMap &data) void AWKeys::setDataBySource(const QString &_source, const KSysGuard::SensorInfo &_sensor,
const KSysGuard::SensorData &_data)
{ {
qCDebug(LOG_AW) << "Source" << sourceName << "with data" << data; qCDebug(LOG_AW) << "Source" << _source << _sensor.name << "with data" << _data.payload;
// first list init // first list init
QStringList tags = m_aggregator->keysFromSource(sourceName); auto tags = m_aggregator->keysFromSource(_source);
if (tags.isEmpty()) if (tags.isEmpty())
tags = m_aggregator->registerSource( tags = m_aggregator->registerSource(_source, _sensor.unit, m_requiredKeys);
sourceName, data[QString("units")].toString(), m_requiredKeys);
// update data or drop source if there are no matches and exit // update data or drop source if there are no matches and exit
if (tags.isEmpty()) { if (tags.isEmpty()) {
qCInfo(LOG_AW) << "Source" << sourceName << "not found"; qCInfo(LOG_AW) << "Sensor" << _source << "not found";
return emit(dropSourceFromDataengine(sourceName)); return emit(dropSourceFromDataengine(_source));
} }
m_mutex.lock(); m_mutex.lock();
// HACK workaround for time values which are stored in the different path std::for_each(tags.cbegin(), tags.cend(), [this, &_data](const QString &tag) { m_values[tag] = _data.payload; });
std::for_each(tags.cbegin(), tags.cend(),
[this, &data, &sourceName](const QString &tag) {
m_values[tag] = sourceName == QString("Local")
? data[QString("DateTime")]
: data[QString("value")];
});
m_mutex.unlock(); m_mutex.unlock();
} }

View File

@ -19,11 +19,11 @@
#ifndef AWKEYS_H #ifndef AWKEYS_H
#define AWKEYS_H #define AWKEYS_H
#include <Plasma/DataEngine>
#include <QMutex> #include <QMutex>
#include <QObject> #include <QObject>
#include <ksysguard/systemstats/SensorInfo.h>
class AWDataAggregator; class AWDataAggregator;
class AWDataEngineAggregator; class AWDataEngineAggregator;
@ -37,47 +37,43 @@ class AWKeys : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit AWKeys(QObject *parent = nullptr); explicit AWKeys(QObject *_parent = nullptr);
virtual ~AWKeys(); ~AWKeys() override;
Q_INVOKABLE void initDataAggregator(const QVariantMap tooltipParams); Q_INVOKABLE void initDataAggregator(const QVariantMap &_tooltipParams);
Q_INVOKABLE void initKeys(const QString currentPattern, const int interval, Q_INVOKABLE void initKeys(const QString &_currentPattern, int _interval, int _limit, bool _optimize);
const int limit, const bool optimize); Q_INVOKABLE void setAggregatorProperty(const QString &_key, const QVariant &_value);
Q_INVOKABLE void setAggregatorProperty(const QString key, Q_INVOKABLE void setWrapNewLines(bool _wrap);
const QVariant value);
Q_INVOKABLE void setWrapNewLines(const bool wrap = false);
// additional method to force load keys from Qml UI. Used in some // additional method to force load keys from Qml UI. Used in some
// configuration pages // configuration pages
Q_INVOKABLE void updateCache(); Q_INVOKABLE void updateCache();
// keys // keys
Q_INVOKABLE QStringList dictKeys(const bool sorted = false, Q_INVOKABLE [[nodiscard]] QStringList dictKeys(bool _sorted = false, const QString &_regexp = "") const;
const QString regexp = QString()) const; Q_INVOKABLE [[nodiscard]] QVariantList getHddDevices() const;
Q_INVOKABLE QStringList getHddDevices() const;
// values // values
Q_INVOKABLE QString infoByKey(QString key) const; Q_INVOKABLE [[nodiscard]] QString infoByKey(const QString &_key) const;
Q_INVOKABLE QString valueByKey(QString key) const; Q_INVOKABLE [[nodiscard]] QString valueByKey(const QString &_key) const;
// configuration // configuration
Q_INVOKABLE void editItem(const QString type); Q_INVOKABLE void editItem(const QString &_type);
public slots: public slots:
void dataUpdated(const QString &sourceName, void dataUpdated(const QHash<QString, KSysGuard::SensorInfo> &_sensors, const KSysGuard::SensorDataList &_data);
const Plasma::DataEngine::Data &data);
// dummy method required by DataEngine connections
void modelChanged(QString, QAbstractItemModel *){};
signals: signals:
void dropSourceFromDataengine(const QString source); void dropSourceFromDataengine(const QString &_source);
void needTextToBeUpdated(const QString newText) const; void needTextToBeUpdated(const QString &_newText) const;
void needToolTipToBeUpdated(const QString newText) const; void needToolTipToBeUpdated(const QString &_newText) const;
private slots: private slots:
void reinitKeys(const QStringList currentKeys); void reinitKeys(const QStringList &_currentKeys);
void updateTextData(); void updateTextData();
private: private:
// methods // methods
void calculateValues(); void calculateValues();
QString parsePattern(QString pattern) const; void createDBusInterface();
void setDataBySource(const QString &sourceName, const QVariantMap &data); [[nodiscard]] QString parsePattern(QString _pattern) const;
void setDataBySource(const QString &_source, const KSysGuard::SensorInfo &_sensor,
const KSysGuard::SensorData &_data);
// objects // objects
AWDataAggregator *m_dataAggregator = nullptr; AWDataAggregator *m_dataAggregator = nullptr;
AWDataEngineAggregator *m_dataEngineAggregator = nullptr; AWDataEngineAggregator *m_dataEngineAggregator = nullptr;

View File

@ -21,88 +21,74 @@
#include <QDateTime> #include <QDateTime>
#include <QLocale> #include <QLocale>
#include <QRegExp>
#include "awdataenginemapper.h"
#include "awdebug.h" #include "awdebug.h"
#include "awformatterhelper.h" #include "awformatterhelper.h"
#include "version.h"
AWKeysAggregator::AWKeysAggregator(QObject *parent) AWKeysAggregator::AWKeysAggregator(QObject *_parent)
: QObject(parent) : QObject(_parent)
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
// default formatters m_customFormatters = new AWFormatterHelper(nullptr);
// memory m_mapper = new AWDataEngineMapper(this, m_customFormatters);
m_formatter[QString("mem")] = FormatterType::Float;
m_formatter[QString("memtotmb")] = FormatterType::MemMBFormat; // sort time keys
m_formatter[QString("memtotgb")] = FormatterType::MemGBFormat; m_timeKeys = QString(TIME_KEYS).split(',');
// network m_timeKeys.sort();
m_formatter[QString("down")] = FormatterType::NetSmartFormat; std::reverse(m_timeKeys.begin(), m_timeKeys.end());
m_formatter[QString("downkb")] = FormatterType::Integer;
m_formatter[QString("downunits")] = FormatterType::NetSmartUnits;
m_formatter[QString("up")] = FormatterType::NetSmartFormat;
m_formatter[QString("upkb")] = FormatterType::Integer;
m_formatter[QString("upunits")] = FormatterType::NetSmartUnits;
// swap
m_formatter[QString("swap")] = FormatterType::Float;
m_formatter[QString("swaptotmb")] = FormatterType::MemMBFormat;
m_formatter[QString("swaptotgb")] = FormatterType::MemGBFormat;
} }
AWKeysAggregator::~AWKeysAggregator() AWKeysAggregator::~AWKeysAggregator()
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
delete m_customFormatters;
} }
void AWKeysAggregator::initFormatters() void AWKeysAggregator::initFormatters()
{ {
if (m_customFormatters) m_customFormatters->initItems();
delete m_customFormatters;
m_customFormatters = new AWFormatterHelper(nullptr);
} }
QString AWKeysAggregator::formatter(const QVariant &data, QString AWKeysAggregator::formatter(const QVariant &_data, const QString &_key, bool replaceSpace) const
const QString &key) const
{ {
qCDebug(LOG_AW) << "Data" << data << "for key" << key; qCDebug(LOG_AW) << "Data" << _data << "for key" << _key;
QString output; QString output;
QLocale loc = m_translate ? QLocale::system() : QLocale::c(); QLocale loc = m_translate ? QLocale::system() : QLocale::c();
// case block // case block
switch (m_formatter[key]) { switch (m_mapper->formatter(_key)) {
case FormatterType::Float: case FormatterType::Float:
output = QString("%1").arg(data.toFloat(), 5, 'f', 1); output = QString("%1").arg(_data.toDouble(), 5, 'f', 1);
break; break;
case FormatterType::FloatTwoSymbols: case FormatterType::FloatTwoSymbols:
output = QString("%1").arg(data.toFloat(), 5, 'f', 2); output = QString("%1").arg(_data.toDouble(), 5, 'f', 2);
break; break;
case FormatterType::Integer: case FormatterType::Integer:
output = QString("%1").arg(data.toFloat(), 4, 'f', 0); output = QString("%1").arg(_data.toDouble(), 4, 'f', 0);
break; break;
case FormatterType::IntegerFive: case FormatterType::IntegerFive:
output = QString("%1").arg(data.toFloat(), 5, 'f', 0); output = QString("%1").arg(_data.toDouble(), 5, 'f', 0);
break; break;
case FormatterType::IntegerThree: case FormatterType::IntegerThree:
output = QString("%1").arg(data.toFloat(), 3, 'f', 0); output = QString("%1").arg(_data.toDouble(), 3, 'f', 0);
break; break;
case FormatterType::List: case FormatterType::List:
output = data.toStringList().join(QChar(',')); output = _data.toStringList().join(',');
break; break;
case FormatterType::ACFormat: case FormatterType::ACFormat:
output = data.toBool() ? m_acOnline : m_acOffline; output = _data.toBool() ? m_acOnline : m_acOffline;
break; break;
case FormatterType::MemGBFormat: case FormatterType::MemGBFormat:
output output = QString("%1").arg(_data.toDouble() / (1024.0 * 1024.0), 5, 'f', 1);
= QString("%1").arg(data.toFloat() / (1024.0 * 1024.0), 5, 'f', 1);
break; break;
case FormatterType::MemMBFormat: case FormatterType::MemMBFormat:
output = QString("%1").arg(data.toFloat() / 1024.0, 5, 'f', 0); output = QString("%1").arg(_data.toDouble() / 1024.0, 5, 'f', 0);
break; break;
case FormatterType::NetSmartFormat: case FormatterType::NetSmartFormat:
output = [](const float value) { output = [](const float value) {
@ -110,44 +96,43 @@ QString AWKeysAggregator::formatter(const QVariant &data,
return QString("%1").arg(value / 1024.0, 4, 'f', 1); return QString("%1").arg(value / 1024.0, 4, 'f', 1);
else else
return QString("%1").arg(value, 4, 'f', 0); return QString("%1").arg(value, 4, 'f', 0);
}(data.toFloat()); }(_data.toDouble());
break; break;
case FormatterType::NetSmartUnits: case FormatterType::NetSmartUnits:
if (data.toFloat() > 1024.0) if (_data.toDouble() > 1024.0)
output = m_translate ? i18n("MB/s") : QString("MB/s"); output = m_translate ? i18n("MB/s") : "MB/s";
else else
output = m_translate ? i18n("KB/s") : QString("KB/s"); output = m_translate ? i18n("KB/s") : "KB/s";
break; break;
case FormatterType::Quotes: case FormatterType::Quotes:
// first cast // first cast
output = QString("%1").arg(data.toDouble(), 0, 'f'); output = QString("%1").arg(_data.toDouble(), 0, 'f');
output = output.rightJustified(8, QLatin1Char(' '), true); output = output.rightJustified(8, QLatin1Char(' '), true);
break; break;
case FormatterType::Temperature: case FormatterType::Temperature:
output = QString("%1").arg(temperature(data.toFloat()), 5, 'f', 1); output = QString("%1").arg(temperature(_data.toDouble()), 5, 'f', 1);
break; break;
case FormatterType::Time: case FormatterType::Time:
output = data.toDateTime().toString(); output = QDateTime::fromSecsSinceEpoch(_data.toLongLong()).toString();
break; break;
case FormatterType::TimeCustom: case FormatterType::TimeCustom:
output = m_customTime; output = m_customTime;
[&output, loc, this](const QDateTime dt) { [&output, loc, this](const QDateTime &dt) {
for (auto key : m_timeKeys) for (auto &key : m_timeKeys)
output.replace(QString("$%1").arg(key), loc.toString(dt, key)); output.replace(QString("$%1").arg(key), loc.toString(dt, key));
}(data.toDateTime()); }(QDateTime::fromSecsSinceEpoch(_data.toLongLong()));
break; break;
case FormatterType::TimeISO: case FormatterType::TimeISO:
output = data.toDateTime().toString(Qt::ISODate); output = QDateTime::fromSecsSinceEpoch(_data.toLongLong()).toString(Qt::ISODate);
break; break;
case FormatterType::TimeLong: case FormatterType::TimeLong:
output = loc.toString(data.toDateTime(), QLocale::LongFormat); output = loc.toString(QDateTime::fromSecsSinceEpoch(_data.toLongLong()), QLocale::LongFormat);
break; break;
case FormatterType::TimeShort: case FormatterType::TimeShort:
output = loc.toString(data.toDateTime(), QLocale::ShortFormat); output = loc.toString(QDateTime::fromSecsSinceEpoch(_data.toLongLong()), QLocale::ShortFormat);
break; break;
case FormatterType::Timestamp: case FormatterType::Timestamp:
output = QString("%1").arg( output = _data.toString();
data.toDateTime().toMSecsSinceEpoch() / 1000.0, 10, 'f', 0);
break; break;
case FormatterType::Uptime: case FormatterType::Uptime:
case FormatterType::UptimeCustom: case FormatterType::UptimeCustom:
@ -157,455 +142,104 @@ QString AWKeysAggregator::formatter(const QVariant &data,
int minutes = seconds / 60 % 60; int minutes = seconds / 60 % 60;
int hours = ((seconds / 60) - minutes) / 60 % 24; int hours = ((seconds / 60) - minutes) / 60 % 24;
int days = (((seconds / 60) - minutes) / 60 - hours) / 24; int days = (((seconds / 60) - minutes) / 60 - hours) / 24;
source.replace(QString("$dd"), source.replace("$dd", QString("%1").arg(days, 3, 10, QChar('0')));
QString("%1").arg(days, 3, 10, QChar('0'))); source.replace("$d", QString("%1").arg(days));
source.replace(QString("$d"), QString("%1").arg(days)); source.replace("$hh", QString("%1").arg(hours, 2, 10, QChar('0')));
source.replace(QString("$hh"), source.replace("$h", QString("%1").arg(hours));
QString("%1").arg(hours, 2, 10, QChar('0'))); source.replace("$mm", QString("%1").arg(minutes, 2, 10, QChar('0')));
source.replace(QString("$h"), QString("%1").arg(hours)); source.replace("$m", QString("%1").arg(minutes));
source.replace(QString("$mm"),
QString("%1").arg(minutes, 2, 10, QChar('0')));
source.replace(QString("$m"), QString("%1").arg(minutes));
return source; return source;
}(m_formatter[key] == FormatterType::Uptime }(m_mapper->formatter(_key) == FormatterType::Uptime ? "$ddd$hhh$mmm" : m_customUptime,
? QString("$ddd$hhh$mmm") static_cast<int>(_data.toDouble()));
: m_customUptime,
static_cast<int>(data.toFloat()));
break; break;
case FormatterType::NoFormat: case FormatterType::NoFormat:
output = data.toString(); output = _data.toString();
break; break;
case FormatterType::Custom: case FormatterType::Custom:
if (m_customFormatters) if (m_customFormatters)
output = m_customFormatters->convert(data, key); output = m_customFormatters->convert(_data, _key);
break; break;
} }
// replace spaces to non-breakable ones
replaceSpace &= (!_key.startsWith("custom") && (!_key.startsWith("weather")));
if (replaceSpace)
output.replace(" ", "&nbsp;");
return output; return output;
} }
QStringList AWKeysAggregator::keysFromSource(const QString &source) const QStringList AWKeysAggregator::keysFromSource(const QString &_source) const
{ {
qCDebug(LOG_AW) << "Search for source" << source; qCDebug(LOG_AW) << "Search for source" << _source;
return m_map.values(source); return m_mapper->keysFromSource(_source);
} }
void AWKeysAggregator::setAcOffline(const QString inactive) void AWKeysAggregator::setAcOffline(const QString &_inactive)
{ {
qCDebug(LOG_AW) << "Inactive AC string" << inactive; qCDebug(LOG_AW) << "Inactive AC string" << _inactive;
m_acOffline = inactive; m_acOffline = _inactive;
} }
void AWKeysAggregator::setAcOnline(const QString active) void AWKeysAggregator::setAcOnline(const QString &_active)
{ {
qCDebug(LOG_AW) << "Active AC string" << active; qCDebug(LOG_AW) << "Active AC string" << _active;
m_acOnline = active; m_acOnline = _active;
} }
void AWKeysAggregator::setCustomTime(const QString customTime) void AWKeysAggregator::setCustomTime(const QString &_customTime)
{ {
qCDebug(LOG_AW) << "Format" << customTime; qCDebug(LOG_AW) << "Format" << _customTime;
m_customTime = customTime; m_customTime = _customTime;
} }
void AWKeysAggregator::setCustomUptime(const QString customUptime) void AWKeysAggregator::setCustomUptime(const QString &_customUptime)
{ {
qCDebug(LOG_AW) << "Format" << customUptime; qCDebug(LOG_AW) << "Format" << _customUptime;
m_customUptime = customUptime; m_customUptime = _customUptime;
} }
void AWKeysAggregator::setDevices(const QHash<QString, QStringList> devices) void AWKeysAggregator::setDevices(const QHash<QString, QStringList> &_devices)
{ {
qCDebug(LOG_AW) << "Devices" << devices; qCDebug(LOG_AW) << "Devices" << _devices;
m_devices = devices; m_mapper->setDevices(_devices);
} }
void AWKeysAggregator::setTempUnits(const QString units) void AWKeysAggregator::setTempUnits(const QString &_units)
{ {
qCDebug(LOG_AW) << "Units" << units; qCDebug(LOG_AW) << "Units" << _units;
m_tempUnits = units; m_tempUnits = _units;
} }
void AWKeysAggregator::setTranslate(const bool translate) void AWKeysAggregator::setTranslate(const bool _translate)
{ {
qCDebug(LOG_AW) << "Translate" << translate; qCDebug(LOG_AW) << "Translate" << _translate;
m_translate = translate; m_translate = _translate;
} }
// HACK units required to define should the value be calculated as temperature QStringList AWKeysAggregator::registerSource(const QString &_source, const KSysGuard::Unit &_units,
// or fan data const QStringList &_keys)
QStringList AWKeysAggregator::registerSource(const QString &source,
const QString &units,
const QStringList &keys)
{ {
qCDebug(LOG_AW) << "Source" << source << "with units" << units; qCDebug(LOG_AW) << "Source" << _source << "with units" << _units;
// regular expressions return m_mapper->registerSource(_source, _units, _keys);
QRegExp cpuRegExp = QRegExp(QString("cpu/cpu.*/TotalLoad"));
QRegExp cpuclRegExp = QRegExp(QString("cpu/cpu.*/clock"));
QRegExp hddrRegExp = QRegExp(QString("disk/.*/Rate/rblk"));
QRegExp hddwRegExp = QRegExp(QString("disk/.*/Rate/wblk"));
QRegExp mountFillRegExp = QRegExp(QString("partitions/.*/filllevel"));
QRegExp mountFreeRegExp = QRegExp(QString("partitions/.*/freespace"));
QRegExp mountUsedRegExp = QRegExp(QString("partitions/.*/usedspace"));
QRegExp netRegExp = QRegExp(
QString("network/interfaces/.*/(receiver|transmitter)/data$"));
QRegExp netTotalRegExp = QRegExp(
QString("network/interfaces/.*/(receiver|transmitter)/dataTotal$"));
if (source == QString("battery/ac")) {
// AC
m_map[source] = QString("ac");
m_formatter[QString("ac")] = FormatterType::ACFormat;
} else if (source.startsWith(QString("battery/"))) {
// battery stats
QString key = source;
key.remove(QString("battery/"));
m_map[source] = key;
m_formatter[key] = FormatterType::IntegerThree;
} else if (source == QString("cpu/system/TotalLoad")) {
// cpu
m_map[source] = QString("cpu");
m_formatter[QString("cpu")] = FormatterType::Float;
} else if (source.contains(cpuRegExp)) {
// cpus
QString key = source;
key.remove(QString("cpu/")).remove(QString("/TotalLoad"));
m_map[source] = key;
m_formatter[key] = FormatterType::Float;
} else if (source == QString("cpu/system/AverageClock")) {
// cpucl
m_map[source] = QString("cpucl");
m_formatter[QString("cpucl")] = FormatterType::Integer;
} else if (source.contains(cpuclRegExp)) {
// cpucls
QString key = source;
key.remove(QString("cpu/cpu")).remove(QString("/clock"));
key = QString("cpucl%1").arg(key);
m_map[source] = key;
m_formatter[key] = FormatterType::Integer;
} else if (source.startsWith(QString("custom"))) {
// custom
QString key = source;
key.remove(QString("custom/"));
m_map[source] = key;
m_formatter[key] = FormatterType::NoFormat;
} else if (source == QString("desktop/current/name")) {
// current desktop name
m_map[source] = QString("desktop");
m_formatter[QString("desktop")] = FormatterType::NoFormat;
} else if (source == QString("desktop/current/number")) {
// current desktop number
m_map[source] = QString("ndesktop");
m_formatter[QString("ndesktop")] = FormatterType::NoFormat;
} else if (source == QString("desktop/total/number")) {
// desktop count
m_map[source] = QString("tdesktops");
m_formatter[QString("tdesktops")] = FormatterType::NoFormat;
} else if (source.contains(hddrRegExp)) {
// read speed
QString device = source;
device.remove(QString("/Rate/rblk"));
int index = m_devices[QString("disk")].indexOf(device);
if (index > -1) {
QString key = QString("hddr%1").arg(index);
m_map[source] = key;
m_formatter[key] = FormatterType::Integer;
}
} else if (source.contains(hddwRegExp)) {
// write speed
QString device = source;
device.remove(QString("/Rate/wblk"));
int index = m_devices[QString("disk")].indexOf(device);
if (index > -1) {
QString key = QString("hddw%1").arg(index);
m_map[source] = key;
m_formatter[key] = FormatterType::Integer;
}
} else if (source == QString("gpu/load")) {
// gpu load
m_map[source] = QString("gpu");
m_formatter[QString("gpu")] = FormatterType::Float;
} else if (source == QString("gpu/temperature")) {
// gpu temperature
m_map[source] = QString("gputemp");
m_formatter[QString("gputemp")] = FormatterType::Temperature;
} else if (source.contains(mountFillRegExp)) {
// fill level
QString device = source;
device.remove(QString("partitions")).remove(QString("/filllevel"));
int index = m_devices[QString("mount")].indexOf(device);
if (index > -1) {
QString key = QString("hdd%1").arg(index);
m_map[source] = key;
m_formatter[key] = FormatterType::Float;
// additional keys
m_formatter[QString("hddtotmb%1").arg(index)]
= FormatterType::MemMBFormat;
m_formatter[QString("hddtotgb%1").arg(index)]
= FormatterType::MemGBFormat;
}
} else if (source.contains(mountFreeRegExp)) {
// free space
QString device = source;
device.remove(QString("partitions")).remove(QString("/freespace"));
int index = m_devices[QString("mount")].indexOf(device);
if (index > -1) {
// mb
QString key = QString("hddfreemb%1").arg(index);
m_map[source] = key;
m_formatter[key] = FormatterType::MemMBFormat;
// gb
key = QString("hddfreegb%1").arg(index);
m_map.insertMulti(source, key);
m_formatter[key] = FormatterType::MemGBFormat;
}
} else if (source.contains(mountUsedRegExp)) {
// used
QString device = source;
device.remove(QString("partitions")).remove(QString("/usedspace"));
int index = m_devices[QString("mount")].indexOf(device);
if (index > -1) {
// mb
QString key = QString("hddmb%1").arg(index);
m_map[source] = key;
m_formatter[key] = FormatterType::MemMBFormat;
// gb
key = QString("hddgb%1").arg(index);
m_map.insertMulti(source, key);
m_formatter[key] = FormatterType::MemGBFormat;
}
} else if (source.startsWith(QString("hdd/temperature"))) {
// hdd temperature
QString device = source;
device.remove(QString("hdd/temperature"));
int index = m_devices[QString("hdd")].indexOf(device);
if (index > -1) {
QString key = QString("hddtemp%1").arg(index);
m_map[source] = key;
m_formatter[key] = FormatterType::Temperature;
}
} else if (source.startsWith(QString("cpu/system/loadavg"))) {
// load average
QString time = source;
time.remove(QString("cpu/system/loadavg"));
QString key = QString("la%1").arg(time);
m_map[source] = key;
m_formatter[key] = FormatterType::FloatTwoSymbols;
} else if (source == QString("mem/physical/application")) {
// app memory
// mb
m_map[source] = QString("memmb");
m_formatter[QString("memmb")] = FormatterType::MemMBFormat;
// gb
m_map.insertMulti(source, QString("memgb"));
m_formatter[QString("memgb")] = FormatterType::MemGBFormat;
} else if (source == QString("mem/physical/free")) {
// free memory
// mb
m_map[source] = QString("memfreemb");
m_formatter[QString("memfreemb")] = FormatterType::MemMBFormat;
// gb
m_map.insertMulti(source, QString("memfreegb"));
m_formatter[QString("memfreegb")] = FormatterType::MemGBFormat;
} else if (source == QString("mem/physical/used")) {
// used memory
// mb
m_map[source] = QString("memusedmb");
m_formatter[QString("memusedmb")] = FormatterType::MemMBFormat;
// gb
m_map.insertMulti(source, QString("memusedgb"));
m_formatter[QString("memusedgb")] = FormatterType::MemGBFormat;
} else if (source == QString("network/current/name")) {
// network device
m_map[source] = QString("netdev");
m_formatter[QString("netdev")] = FormatterType::NoFormat;
} else if (source.contains(netRegExp)) {
// network speed
QString type = source.contains(QString("receiver")) ? QString("down")
: QString("up");
int index
= m_devices[QString("net")].indexOf(source.split(QChar('/'))[2]);
if (index > -1) {
// kb
QString key = QString("%1kb%2").arg(type).arg(index);
m_map[source] = key;
m_formatter[key] = FormatterType::Integer;
// smart
key = QString("%1%2").arg(type).arg(index);
m_map.insertMulti(source, key);
m_formatter[key] = FormatterType::NetSmartFormat;
// units
key = QString("%1units%2").arg(type).arg(index);
m_map.insertMulti(source, key);
m_formatter[key] = FormatterType::NetSmartUnits;
}
} else if (source.contains(netTotalRegExp)) {
// network data total
QString type = source.contains(QString("receiver")) ? QString("down")
: QString("up");
int index
= m_devices[QString("net")].indexOf(source.split(QChar('/'))[2]);
if (index > -1) {
// kb
QString key = QString("%1totalkb%2").arg(type).arg(index);
m_map[source] = key;
m_formatter[key] = FormatterType::Integer;
// mb
key = QString("%1total%2").arg(type).arg(index);
m_map.insertMulti(source, key);
m_formatter[key] = FormatterType::MemMBFormat;
}
} else if (source.startsWith(QString("upgrade"))) {
// package manager
QString key = source;
key.remove(QString("upgrade/"));
m_map[source] = key;
m_formatter[key] = FormatterType::IntegerThree;
} else if (source.startsWith(QString("player"))) {
// player
QString key = source;
key.remove(QString("player/"));
m_map[source] = key;
m_formatter[key] = FormatterType::NoFormat;
} else if (source == QString("ps/running/count")) {
// running processes count
m_map[source] = QString("pscount");
m_formatter[QString("pscount")] = FormatterType::NoFormat;
} else if (source == QString("ps/running/list")) {
// list of running processes
m_map[source] = QString("ps");
m_formatter[QString("ps")] = FormatterType::List;
} else if (source == QString("ps/total/count")) {
// total processes count
m_map[source] = QString("pstotal");
m_formatter[QString("pstotal")] = FormatterType::NoFormat;
} else if (source.startsWith(QString("quotes"))) {
// quotes
QString key = source;
key.remove(QString("quotes/"));
m_map[source] = key;
m_formatter[key] = FormatterType::Quotes;
} else if (source == QString("mem/swap/free")) {
// free swap
// mb
m_map[source] = QString("swapfreemb");
m_formatter[QString("swapfreemb")] = FormatterType::MemMBFormat;
// gb
m_map.insertMulti(source, QString("swapfreegb"));
m_formatter[QString("swapfreegb")] = FormatterType::MemGBFormat;
} else if (source == QString("mem/swap/used")) {
// used swap
// mb
m_map[source] = QString("swapmb");
m_formatter[QString("swapmb")] = FormatterType::MemMBFormat;
// gb
m_map.insertMulti(source, QString("swapgb"));
m_formatter[QString("swapgb")] = FormatterType::MemGBFormat;
} else if (source.startsWith(QString("lmsensors/"))) {
// temperature
int index = m_devices[QString("temp")].indexOf(source);
// HACK on DE initialization there are no units key
if (units.isEmpty())
return QStringList() << QString("temp%1").arg(index);
if (index > -1) {
QString key = QString("temp%1").arg(index);
m_map[source] = key;
m_formatter[key] = units == QString("°C")
? FormatterType::Temperature
: FormatterType::Integer;
}
} else if (source == QString("Local")) {
// time
m_map[source] = QString("time");
m_formatter[QString("time")] = FormatterType::Time;
// custom time
m_map.insertMulti(source, QString("ctime"));
m_formatter[QString("ctime")] = FormatterType::TimeCustom;
// ISO time
m_map.insertMulti(source, QString("isotime"));
m_formatter[QString("isotime")] = FormatterType::TimeISO;
// long time
m_map.insertMulti(source, QString("longtime"));
m_formatter[QString("longtime")] = FormatterType::TimeLong;
// short time
m_map.insertMulti(source, QString("shorttime"));
m_formatter[QString("shorttime")] = FormatterType::TimeShort;
// timestamp
m_map.insertMulti(source, QString("tstime"));
m_formatter[QString("tstime")] = FormatterType::Timestamp;
} else if (source == QString("system/uptime")) {
// uptime
m_map[source] = QString("uptime");
m_formatter[QString("uptime")] = FormatterType::Uptime;
// custom uptime
m_map.insertMulti(source, QString("cuptime"));
m_formatter[QString("cuptime")] = FormatterType::UptimeCustom;
} else if (source.startsWith(QString("weather/temperature"))) {
// temperature
QString key = source;
key.remove(QString("weather/"));
m_map[source] = key;
m_formatter[key] = FormatterType::Temperature;
} else if (source.startsWith(QString("weather/"))) {
// other weather
QString key = source;
key.remove(QString("weather/"));
m_map[source] = key;
m_formatter[key] = FormatterType::NoFormat;
} else if (source.startsWith(QString("load/load"))) {
// load source
QString key = source;
key.remove(QString("load/"));
m_map[source] = key;
m_formatter[key] = FormatterType::Temperature;
}
QStringList foundKeys = keysFromSource(source);
// rewrite formatters for custom ones
QStringList customFormattersKeys;
if (m_customFormatters)
customFormattersKeys = m_customFormatters->definedFormatters();
qCInfo(LOG_AW) << "Looking for fprmatters" << foundKeys << "in"
<< customFormattersKeys;
for (auto key : foundKeys) {
if (!customFormattersKeys.contains(key))
continue;
m_formatter[key] = FormatterType::Custom;
}
// drop key from dictionary if no one user requested key required it
qCInfo(LOG_AW) << "Looking for keys" << foundKeys << "in" << keys;
bool required
= keys.isEmpty() || std::any_of(foundKeys.cbegin(), foundKeys.cend(),
[&keys](const QString &key) {
return keys.contains(key);
});
if (!required) {
m_map.remove(source);
for (auto key : foundKeys)
m_formatter.remove(key);
}
return keysFromSource(source);
} }
@ -614,18 +248,18 @@ float AWKeysAggregator::temperature(const float temp) const
qCDebug(LOG_AW) << "Temperature value" << temp; qCDebug(LOG_AW) << "Temperature value" << temp;
float converted = temp; float converted = temp;
if (m_tempUnits == QString("Celsius")) { if (m_tempUnits == "Celsius") {
} else if (m_tempUnits == QString("Fahrenheit")) { } else if (m_tempUnits == "Fahrenheit") {
converted = temp * 9.0f / 5.0f + 32.0f; converted = temp * 9.0f / 5.0f + 32.0f;
} else if (m_tempUnits == QString("Kelvin")) { } else if (m_tempUnits == "Kelvin") {
converted = temp + 273.15f; converted = temp + 273.15f;
} else if (m_tempUnits == QString("Reaumur")) { } else if (m_tempUnits == "Reaumur") {
converted = temp * 0.8f; converted = temp * 0.8f;
} else if (m_tempUnits == QString("cm^-1")) { } else if (m_tempUnits == "cm^-1") {
converted = (temp + 273.15f) * 0.695f; converted = (temp + 273.15f) * 0.695f;
} else if (m_tempUnits == QString("kJ/mol")) { } else if (m_tempUnits == "kJ/mol") {
converted = (temp + 273.15f) * 8.31f; converted = (temp + 273.15f) * 8.31f;
} else if (m_tempUnits == QString("kcal/mol")) { } else if (m_tempUnits == "kcal/mol") {
converted = (temp + 273.15f) * 1.98f; converted = (temp + 273.15f) * 1.98f;
} else { } else {
qCWarning(LOG_AW) << "Invalid units" << m_tempUnits; qCWarning(LOG_AW) << "Invalid units" << m_tempUnits;

View File

@ -19,13 +19,14 @@
#ifndef AWKEYSAGGREGATOR_H #ifndef AWKEYSAGGREGATOR_H
#define AWKEYSAGGREGATOR_H #define AWKEYSAGGREGATOR_H
#include <ksysguard/formatter/Unit.h>
#include <QHash> #include <QHash>
#include <QObject> #include <QObject>
#include "version.h"
class AWFormatterHelper; class AWFormatterHelper;
class AWDataEngineMapper;
class AWKeysAggregator : public QObject class AWKeysAggregator : public QObject
{ {
@ -33,11 +34,11 @@ class AWKeysAggregator : public QObject
Q_PROPERTY(QString acOffline MEMBER m_acOffline WRITE setAcOffline); Q_PROPERTY(QString acOffline MEMBER m_acOffline WRITE setAcOffline);
Q_PROPERTY(QString acOnline MEMBER m_acOnline WRITE setAcOnline); Q_PROPERTY(QString acOnline MEMBER m_acOnline WRITE setAcOnline);
Q_PROPERTY(QString customTime MEMBER m_customTime WRITE setCustomTime); Q_PROPERTY(QString customTime MEMBER m_customTime WRITE setCustomTime);
Q_PROPERTY( Q_PROPERTY(QString customUptime MEMBER m_customUptime WRITE setCustomUptime);
QString customUptime MEMBER m_customUptime WRITE setCustomUptime);
Q_PROPERTY(QString tempUnits MEMBER m_tempUnits WRITE setTempUnits); Q_PROPERTY(QString tempUnits MEMBER m_tempUnits WRITE setTempUnits);
Q_PROPERTY(bool translate MEMBER m_translate WRITE setTranslate); Q_PROPERTY(bool translate MEMBER m_translate WRITE setTranslate);
public:
enum class FormatterType { enum class FormatterType {
// general formatters // general formatters
Custom, Custom,
@ -66,38 +67,34 @@ class AWKeysAggregator : public QObject
UptimeCustom UptimeCustom
}; };
public: explicit AWKeysAggregator(QObject *_parent = nullptr);
explicit AWKeysAggregator(QObject *parent = nullptr); ~AWKeysAggregator() override;
virtual ~AWKeysAggregator();
void initFormatters(); void initFormatters();
// get methods // get methods
QString formatter(const QVariant &data, const QString &key) const; [[nodiscard]] QString formatter(const QVariant &_data, const QString &_key, bool replaceSpace) const;
QStringList keysFromSource(const QString &source) const; [[nodiscard]] QStringList keysFromSource(const QString &_source) const;
// set methods // set methods
void setAcOffline(const QString inactive); void setAcOffline(const QString &_inactive);
void setAcOnline(const QString active); void setAcOnline(const QString &_active);
void setCustomTime(const QString customTime); void setCustomTime(const QString &_customTime);
void setCustomUptime(const QString customUptime); void setCustomUptime(const QString &_customUptime);
void setDevices(const QHash<QString, QStringList> devices); void setDevices(const QHash<QString, QStringList> &_devices);
void setTempUnits(const QString units); void setTempUnits(const QString &_units);
void setTranslate(const bool translate); void setTranslate(bool _translate);
public slots: public slots:
QStringList registerSource(const QString &source, const QString &units, QStringList registerSource(const QString &_source, const KSysGuard::Unit &_units, const QStringList &_keys);
const QStringList &keys);
private: private:
float temperature(const float temp) const; [[nodiscard]] float temperature(float temp) const;
AWFormatterHelper *m_customFormatters = nullptr; AWFormatterHelper *m_customFormatters = nullptr;
QStringList m_timeKeys = QString(TIME_KEYS).split(QChar(',')); AWDataEngineMapper *m_mapper = nullptr;
QStringList m_timeKeys;
// variables // variables
QString m_acOffline; QString m_acOffline;
QString m_acOnline; QString m_acOnline;
QString m_customTime; QString m_customTime;
QString m_customUptime; QString m_customUptime;
QHash<QString, QStringList> m_devices;
QHash<QString, FormatterType> m_formatter;
QHash<QString, QString> m_map;
QString m_tempUnits; QString m_tempUnits;
bool m_translate = false; bool m_translate = false;
}; };

View File

@ -0,0 +1,51 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#include "awpairconfigfactory.h"
#include "awcustomkeysconfig.h"
#include "awdebug.h"
#include "awformatterconfig.h"
AWPairConfigFactory::AWPairConfigFactory(QObject *_parent)
: QObject(_parent)
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
}
AWPairConfigFactory::~AWPairConfigFactory()
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
}
void AWPairConfigFactory::showFormatterDialog(const QStringList &_keys)
{
auto *config = new AWFormatterConfig(nullptr, _keys);
config->showDialog();
config->deleteLater();
}
void AWPairConfigFactory::showKeysDialog(const QStringList &_keys)
{
auto *config = new AWCustomKeysConfig(nullptr, _keys);
config->showDialog();
config->deleteLater();
}

View File

@ -0,0 +1,39 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#ifndef AWPAIRCONFIGFACTORY_H
#define AWPAIRCONFIGFACTORY_H
#include <QObject>
class AWPairConfigFactory : public QObject
{
Q_OBJECT
public:
explicit AWPairConfigFactory(QObject *_parent = nullptr);
~AWPairConfigFactory() override;
Q_INVOKABLE static void showFormatterDialog(const QStringList &_keys);
Q_INVOKABLE static void showKeysDialog(const QStringList &_keys);
private:
};
#endif /* AWPAIRCONFIGFACTORY_H */

View File

@ -24,73 +24,65 @@
#include "awkeysaggregator.h" #include "awkeysaggregator.h"
QString AWPatternFunctions::expandLambdas(QString code, QString AWPatternFunctions::expandLambdas(QString _code, AWKeysAggregator *_aggregator, const QVariantHash &_metadata,
AWKeysAggregator *aggregator, const QStringList &_usedKeys)
const QVariantHash &metadata,
const QStringList &usedKeys)
{ {
qCDebug(LOG_AW) << "Expand lamdas in" << code; qCDebug(LOG_AW) << "Expand lambdas in" << _code;
QJSEngine engine; QJSEngine engine;
// apply $this values // apply $this values
code.replace(QString("$this"), metadata[code].toString()); _code.replace("$this", _metadata[_code].toString());
// parsed values // parsed values
for (auto lambdaKey : usedKeys) for (auto &lambdaKey : _usedKeys)
code.replace(QString("$%1").arg(lambdaKey), _code.replace(QString("$%1").arg(lambdaKey), _aggregator->formatter(_metadata[lambdaKey], lambdaKey, false));
aggregator->formatter(metadata[lambdaKey], lambdaKey)); qCInfo(LOG_AW) << "Expression" << _code;
qCInfo(LOG_AW) << "Expression" << code; QJSValue result = engine.evaluate(_code);
QJSValue result = engine.evaluate(code);
if (result.isError()) { if (result.isError()) {
qCWarning(LOG_AW) << "Uncaught exception at line" qCWarning(LOG_AW) << "Uncaught exception at line" << result.property("lineNumber").toInt() << ":"
<< result.property("lineNumber").toInt() << ":"
<< result.toString(); << result.toString();
return QString(); return "";
} else { } else {
return result.toString(); return result.toString();
} }
} }
QString AWPatternFunctions::expandTemplates(QString code) QString AWPatternFunctions::expandTemplates(QString _code)
{ {
qCDebug(LOG_AW) << "Expand templates in" << code; qCDebug(LOG_AW) << "Expand templates in" << _code;
// match the following construction $template{{some code here}} // match the following construction $template{{some code here}}
QRegularExpression templatesRegexp( QRegularExpression templatesRegexp(R"(\$template\{\{(?<body>.*?)\}\})");
QString("\\$template\\{\\{(?<body>.*?)\\}\\}")); templatesRegexp.setPatternOptions(QRegularExpression::DotMatchesEverythingOption);
templatesRegexp.setPatternOptions(
QRegularExpression::DotMatchesEverythingOption);
QRegularExpressionMatchIterator it = templatesRegexp.globalMatch(code); QRegularExpressionMatchIterator it = templatesRegexp.globalMatch(_code);
while (it.hasNext()) { while (it.hasNext()) {
QRegularExpressionMatch match = it.next(); QRegularExpressionMatch match = it.next();
QString body = match.captured(QString("body")); QString body = match.captured("body");
QJSEngine engine; QJSEngine engine;
qCInfo(LOG_AW) << "Expression" << body; qCInfo(LOG_AW) << "Expression" << body;
QJSValue result = engine.evaluate(body); QJSValue result = engine.evaluate(body);
QString templateResult = QString(""); QString templateResult = "";
if (result.isError()) { if (result.isError()) {
qCWarning(LOG_AW) << "Uncaught exception at line" qCWarning(LOG_AW) << "Uncaught exception at line" << result.property("lineNumber").toInt() << ":"
<< result.property("lineNumber").toInt() << ":"
<< result.toString(); << result.toString();
} else { } else {
templateResult = result.toString(); templateResult = result.toString();
} }
// replace template // replace template
code.replace(match.captured(), templateResult); _code.replace(match.captured(), templateResult);
} }
return code; return _code;
} }
QList<AWPatternFunctions::AWFunction> QList<AWPatternFunctions::AWFunction> AWPatternFunctions::findFunctionCalls(const QString &_function,
AWPatternFunctions::findFunctionCalls(const QString function, const QString &_code)
const QString code)
{ {
qCDebug(LOG_AW) << "Looking for function" << function << "in" << code; qCDebug(LOG_AW) << "Looking for function" << _function << "in" << _code;
// I suggest the following regex for the internal functions // I suggest the following regex for the internal functions
// $aw_function_name<some args here if any>{{function body}} // $aw_function_name<some args here if any>{{function body}}
@ -98,36 +90,32 @@ AWPatternFunctions::findFunctionCalls(const QString function,
// in this field if they are not screened by $, i.e. '$,' // in this field if they are not screened by $, i.e. '$,'
// * body depends on the function name, double brackets should be screened // * body depends on the function name, double brackets should be screened
// by using $, e.g. ${ // by using $, e.g. ${
QRegularExpression regex( QRegularExpression regex(QString(R"(\$%1\<(?<args>.*?)\>\{\{(?<body>.*?)\}\})").arg(_function));
QString("\\$%1\\<(?<args>.*?)\\>\\{\\{(?<body>.*?)\\}\\}")
.arg(function));
regex.setPatternOptions(QRegularExpression::DotMatchesEverythingOption); regex.setPatternOptions(QRegularExpression::DotMatchesEverythingOption);
QList<AWPatternFunctions::AWFunction> foundFunctions; QList<AWPatternFunctions::AWFunction> foundFunctions;
QRegularExpressionMatchIterator it = regex.globalMatch(code); QRegularExpressionMatchIterator it = regex.globalMatch(_code);
while (it.hasNext()) { while (it.hasNext()) {
QRegularExpressionMatch match = it.next(); QRegularExpressionMatch match = it.next();
AWPatternFunctions::AWFunction metadata; AWPatternFunctions::AWFunction metadata;
// work with args // work with args
QString argsString = match.captured(QString("args")); QString argsString = match.captured("args");
if (argsString.isEmpty()) { if (argsString.isEmpty()) {
metadata.args = QStringList(); metadata.args = QStringList();
} else { } else {
// replace '$,' to 0x1d // replace '$,' to 0x1d
argsString.replace(QString("$,"), QString(0x1d)); argsString.replace("$,", QChar(0x1d));
QStringList args = argsString.split(QChar(',')); QStringList args = argsString.split(',');
std::for_each(args.begin(), args.end(), [](QString &arg) { std::for_each(args.begin(), args.end(), [](QString &arg) { arg.replace(QChar(0x1d), ","); });
arg.replace(QString(0x1d), QString(","));
});
metadata.args = args; metadata.args = args;
} }
// other variables // other variables
metadata.body = match.captured(QString("body")); metadata.body = match.captured("body");
metadata.what = match.captured(); metadata.what = match.captured();
// replace brackets // replace brackets
metadata.body.replace(QString("${"), QString("{")); metadata.body.replace("${", "{");
metadata.body.replace(QString("$}"), QString("}")); metadata.body.replace("$}", "}");
foundFunctions.append(metadata); foundFunctions.append(metadata);
} }
@ -135,93 +123,77 @@ AWPatternFunctions::findFunctionCalls(const QString function,
} }
QString AWPatternFunctions::insertAllKeys(QString code, const QStringList keys) QString AWPatternFunctions::insertAllKeys(QString _code, const QStringList &_keys)
{ {
qCDebug(LOG_AW) << "Looking for keys in code" << code << "using list" qCDebug(LOG_AW) << "Looking for keys in code" << _code << "using list" << _keys;
<< keys;
QList<AWPatternFunctions::AWFunction> found QList<AWPatternFunctions::AWFunction> found = AWPatternFunctions::findFunctionCalls("aw_all", _code);
= AWPatternFunctions::findFunctionCalls(QString("aw_all"), code); for (auto &function : found) {
for (auto function : found) { QString separator = function.args.isEmpty() ? "," : function.args.at(0);
QString separator QStringList required = _keys.filter(QRegularExpression(function.body));
= function.args.isEmpty() ? QString(",") : function.args.at(0); std::for_each(required.begin(), required.end(), [](QString &value) { value = QString("%1: $%1").arg(value); });
QStringList required = keys.filter(QRegExp(function.body));
std::for_each(required.begin(), required.end(), [](QString &value) {
value = QString("%1: $%1").arg(value);
});
code.replace(function.what, required.join(separator)); _code.replace(function.what, required.join(separator));
} }
return code; return _code;
} }
QString AWPatternFunctions::insertKeyCount(QString code, const QStringList keys) QString AWPatternFunctions::insertKeyCount(QString _code, const QStringList &_keys)
{ {
qCDebug(LOG_AW) << "Looking for count in code" << code << "using list" qCDebug(LOG_AW) << "Looking for count in code" << _code << "using list" << _keys;
<< keys;
QList<AWPatternFunctions::AWFunction> found QList<AWPatternFunctions::AWFunction> found = AWPatternFunctions::findFunctionCalls("aw_count", _code);
= AWPatternFunctions::findFunctionCalls(QString("aw_count"), code); for (auto &function : found) {
for (auto function : found) { int count = _keys.filter(QRegularExpression(function.body)).count();
int count = keys.filter(QRegExp(function.body)).count();
code.replace(function.what, QString::number(count)); _code.replace(function.what, QString::number(count));
} }
return code; return _code;
} }
QString AWPatternFunctions::insertKeyNames(QString code, const QStringList keys) QString AWPatternFunctions::insertKeyNames(QString _code, const QStringList &_keys)
{ {
qCDebug(LOG_AW) << "Looking for key names in code" << code << "using list" qCDebug(LOG_AW) << "Looking for key names in code" << _code << "using list" << _keys;
<< keys;
QList<AWPatternFunctions::AWFunction> found QList<AWPatternFunctions::AWFunction> found = AWPatternFunctions::findFunctionCalls("aw_names", _code);
= AWPatternFunctions::findFunctionCalls(QString("aw_names"), code); for (auto &function : found) {
for (auto function : found) { QString separator = function.args.isEmpty() ? "," : function.args.at(0);
QString separator QStringList required = _keys.filter(QRegularExpression(function.body));
= function.args.isEmpty() ? QString(",") : function.args.at(0);
QStringList required = keys.filter(QRegExp(function.body));
code.replace(function.what, required.join(separator)); _code.replace(function.what, required.join(separator));
} }
return code; return _code;
} }
QString AWPatternFunctions::insertKeys(QString code, const QStringList keys) QString AWPatternFunctions::insertKeys(QString _code, const QStringList &_keys)
{ {
qCDebug(LOG_AW) << "Looking for keys in code" << code << "using list" qCDebug(LOG_AW) << "Looking for keys in code" << _code << "using list" << _keys;
<< keys;
QList<AWPatternFunctions::AWFunction> found QList<AWPatternFunctions::AWFunction> found = AWPatternFunctions::findFunctionCalls("aw_keys", _code);
= AWPatternFunctions::findFunctionCalls(QString("aw_keys"), code); for (auto &function : found) {
for (auto function : found) { QString separator = function.args.isEmpty() ? "," : function.args.at(0);
QString separator QStringList required = _keys.filter(QRegularExpression(function.body));
= function.args.isEmpty() ? QString(",") : function.args.at(0); std::for_each(required.begin(), required.end(), [](QString &value) { value = QString("$%1").arg(value); });
QStringList required = keys.filter(QRegExp(function.body));
std::for_each(required.begin(), required.end(), [](QString &value) {
value = QString("$%1").arg(value);
});
code.replace(function.what, required.join(separator)); _code.replace(function.what, required.join(separator));
} }
return code; return _code;
} }
QString AWPatternFunctions::insertMacros(QString code) QString AWPatternFunctions::insertMacros(QString _code)
{ {
qCDebug(LOG_AW) << "Looking for macros in code" << code; qCDebug(LOG_AW) << "Looking for macros in code" << _code;
QList<AWPatternFunctions::AWFunction> found QList<AWPatternFunctions::AWFunction> found = AWPatternFunctions::findFunctionCalls("aw_macro", _code);
= AWPatternFunctions::findFunctionCalls(QString("aw_macro"), code); for (auto &macro : found) {
for (auto macro : found) {
// get macro params // get macro params
if (macro.args.isEmpty()) { if (macro.args.isEmpty()) {
qCWarning(LOG_AW) << "No macro name found for" << macro.what; qCWarning(LOG_AW) << "No macro name found for" << macro.what;
@ -230,49 +202,41 @@ QString AWPatternFunctions::insertMacros(QString code)
QString name = macro.args.takeFirst(); QString name = macro.args.takeFirst();
// find macro usage // find macro usage
QList<AWPatternFunctions::AWFunction> macroUsage QList<AWPatternFunctions::AWFunction> macroUsage
= AWPatternFunctions::findFunctionCalls( = AWPatternFunctions::findFunctionCalls(QString("aw_macro_%1").arg(name), _code);
QString("aw_macro_%1").arg(name), code); for (auto &function : macroUsage) {
for (auto function : macroUsage) {
if (function.args.count() != macro.args.count()) { if (function.args.count() != macro.args.count()) {
qCWarning(LOG_AW) << "Invalid args count found for call" qCWarning(LOG_AW) << "Invalid args count found for call" << function.what << "with macro" << macro.what;
<< function.what << "with macro"
<< macro.what;
continue; continue;
} }
// generate body to replace // generate body to replace
QString result = macro.body; QString result = macro.body;
std::for_each(macro.args.cbegin(), macro.args.cend(), std::for_each(macro.args.cbegin(), macro.args.cend(), [&result, macro, function](const QString &arg) {
[&result, macro, function](const QString &arg) { int index = macro.args.indexOf(arg);
int index = macro.args.indexOf(arg); result.replace(QString("$%1").arg(arg), function.args.at(index));
result.replace(QString("$%1").arg(arg), });
function.args.at(index));
});
// do replace // do replace
code.replace(function.what, result); _code.replace(function.what, result);
} }
// remove macro from source pattern // remove macro from source pattern
code.remove(macro.what); _code.remove(macro.what);
} }
return code; return _code;
} }
QStringList AWPatternFunctions::findKeys(const QString code, QStringList AWPatternFunctions::findKeys(const QString &_code, const QStringList &_keys, const bool _isBars)
const QStringList keys,
const bool isBars)
{ {
qCDebug(LOG_AW) << "Looking for keys in code" << code << "using list" qCDebug(LOG_AW) << "Looking for keys in code" << _code << "using list" << _keys;
<< keys;
QStringList selectedKeys; QStringList selectedKeys;
for (auto key : keys) QString replacedCode = _code;
if ((key.startsWith(QString("bar")) == isBars) for (auto &key : _keys)
&& (code.contains(QString("$%1").arg(key)))) { if ((key.startsWith("bar") == _isBars) && (replacedCode.contains(QString("$%1").arg(key)))) {
qCInfo(LOG_AW) << "Found key" << key << "with bar enabled" qCInfo(LOG_AW) << "Found key" << key << "with bar enabled" << _isBars;
<< isBars;
selectedKeys.append(key); selectedKeys.append(key);
replacedCode.replace(QString("$%1").arg(key), "");
} }
if (selectedKeys.isEmpty()) if (selectedKeys.isEmpty())
qCWarning(LOG_AW) << "No keys found"; qCWarning(LOG_AW) << "No keys found";
@ -281,20 +245,19 @@ QStringList AWPatternFunctions::findKeys(const QString code,
} }
QStringList AWPatternFunctions::findLambdas(const QString code) QStringList AWPatternFunctions::findLambdas(const QString &_code)
{ {
qCDebug(LOG_AW) << "Looking for lambdas in code" << code; qCDebug(LOG_AW) << "Looking for lambdas in code" << _code;
QStringList selectedKeys; QStringList selectedKeys;
// match the following construction ${{some code here}} // match the following construction ${{some code here}}
QRegularExpression lambdaRegexp(QString("\\$\\{\\{(?<body>.*?)\\}\\}")); QRegularExpression lambdaRegexp(R"(\$\{\{(?<body>.*?)\}\})");
lambdaRegexp.setPatternOptions( lambdaRegexp.setPatternOptions(QRegularExpression::DotMatchesEverythingOption);
QRegularExpression::DotMatchesEverythingOption);
QRegularExpressionMatchIterator it = lambdaRegexp.globalMatch(code); QRegularExpressionMatchIterator it = lambdaRegexp.globalMatch(_code);
while (it.hasNext()) { while (it.hasNext()) {
QRegularExpressionMatch match = it.next(); QRegularExpressionMatch match = it.next();
QString lambda = match.captured(QString("body")); QString lambda = match.captured("body");
// append // append
qCInfo(LOG_AW) << "Found lambda" << lambda; qCInfo(LOG_AW) << "Found lambda" << lambda;

View File

@ -34,21 +34,19 @@ typedef struct {
} AWFunction; } AWFunction;
// insert methods // insert methods
QString expandLambdas(QString code, AWKeysAggregator *aggregator, QString expandLambdas(QString _code, AWKeysAggregator *_aggregator, const QVariantHash &_metadata,
const QVariantHash &metadata, const QStringList &_usedKeys);
const QStringList &usedKeys); QString expandTemplates(QString _code);
QString expandTemplates(QString code); QList<AWFunction> findFunctionCalls(const QString &_function, const QString &_code);
QList<AWFunction> findFunctionCalls(const QString function, const QString code); QString insertAllKeys(QString _code, const QStringList &_keys);
QString insertAllKeys(QString code, const QStringList keys); QString insertKeyCount(QString _code, const QStringList &_keys);
QString insertKeyCount(QString code, const QStringList keys); QString insertKeyNames(QString _code, const QStringList &_keys);
QString insertKeyNames(QString code, const QStringList keys); QString insertKeys(QString _code, const QStringList &_keys);
QString insertKeys(QString code, const QStringList keys); QString insertMacros(QString _code);
QString insertMacros(QString code);
// find methods // find methods
QStringList findKeys(const QString code, const QStringList keys, QStringList findKeys(const QString &_code, const QStringList &_keys, bool _isBars);
const bool isBars); QStringList findLambdas(const QString &_code);
QStringList findLambdas(const QString code); } // namespace AWPatternFunctions
};
#endif /* AWPATTERNFUNCTIONS_H */ #endif /* AWPATTERNFUNCTIONS_H */

View File

@ -0,0 +1,179 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#include "awtelemetryhandler.h"
#include <QJsonDocument>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QSettings>
#include <QStandardPaths>
#include <QUuid>
#include "awdebug.h"
AWTelemetryHandler::AWTelemetryHandler(QObject *_parent, const QString &_clientId)
: QObject(_parent)
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
m_localFile = QString("%1/awesomewidgets/telemetry.ini")
.arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation));
// override client id if any
if (!_clientId.isEmpty())
m_clientId = _clientId;
}
AWTelemetryHandler::~AWTelemetryHandler()
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
}
QStringList AWTelemetryHandler::get(const QString &_group) const
{
qCDebug(LOG_AW) << "Get stored data for group" << _group;
QStringList values;
QSettings settings(m_localFile, QSettings::IniFormat);
settings.beginGroup(_group);
for (auto &key : settings.childKeys())
values.append(settings.value(key).toString());
settings.endGroup();
return values;
}
QString AWTelemetryHandler::getLast(const QString &_group) const
{
qCDebug(LOG_AW) << "Get last stored data for group" << _group;
return get(_group).last();
}
void AWTelemetryHandler::init(const int _count, const bool _enableRemote, const QString &_clientId)
{
qCDebug(LOG_AW) << "Init telemetry with count" << _count << "enable remote" << _enableRemote << "client ID"
<< _clientId;
m_storeCount = _count;
m_uploadEnabled = _enableRemote;
m_clientId = _clientId;
}
bool AWTelemetryHandler::put(const QString &_group, const QString &_value) const
{
qCDebug(LOG_AW) << "Store data with group" << _group << "and value" << _value;
QSettings settings(m_localFile, QSettings::IniFormat);
settings.beginGroup(_group);
// values will be stored as num=value inside specified group
// load all values to memory
QStringList saved;
for (auto &key : settings.childKeys())
saved.append(settings.value(key).toString());
// check if this value is already saved
if (saved.contains(_value)) {
qCInfo(LOG_AW) << "Configuration" << _value << "for group" << _group << "is already saved";
return false;
}
saved.append(_value);
// remove old ones
while (saved.count() > m_storeCount)
saved.takeFirst();
// clear group
settings.remove("");
// and save now
for (auto &val : saved) {
QString key = getKey(settings.childKeys().count());
settings.setValue(key, val);
}
// sync settings
settings.endGroup();
settings.sync();
// return status
return (settings.status() == QSettings::NoError);
}
void AWTelemetryHandler::uploadTelemetry(const QString &_group, const QString &_value)
{
qCDebug(LOG_AW) << "Upload data with group" << _group << "and value" << _value;
if (!m_uploadEnabled) {
qCInfo(LOG_AW) << "Upload disabled by configuration";
return;
}
auto *manager = new QNetworkAccessManager(nullptr);
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(telemetryReplyRecieved(QNetworkReply *)));
QUrl url(REMOTE_TELEMETRY_URL);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
// generate payload
QVariantMap payload;
payload["api"] = AW_TELEMETRY_API;
payload["client_id"] = m_clientId;
payload["metadata"] = _value;
payload["type"] = _group;
// convert to QByteArray to send request
QByteArray data = QJsonDocument::fromVariant(payload).toJson(QJsonDocument::Compact);
qCInfo(LOG_AW) << "Send request with body" << data.data() << "and size" << data.size();
manager->post(request, data);
}
void AWTelemetryHandler::telemetryReplyRecieved(QNetworkReply *_reply)
{
if (_reply->error() != QNetworkReply::NoError) {
qCWarning(LOG_AW) << "An error occurs" << _reply->error() << "with message" << _reply->errorString();
return;
}
QJsonParseError error{};
QJsonDocument jsonDoc = QJsonDocument::fromJson(_reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qCWarning(LOG_AW) << "Parse error" << error.errorString();
return;
}
_reply->deleteLater();
// convert to map
QVariantMap response = jsonDoc.toVariant().toMap();
QString message = response["message"].toString();
qCInfo(LOG_AW) << "Server reply on telemetry" << message;
return emit(replyReceived(message));
}
QString AWTelemetryHandler::getKey(const int _count)
{
qCDebug(LOG_AW) << "Get key for keys count" << _count;
return QString("%1").arg(_count, 3, 10, QChar('0'));
}

View File

@ -0,0 +1,57 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#ifndef AWTELEMETRYHANDLER_H
#define AWTELEMETRYHANDLER_H
#include <QObject>
class QNetworkReply;
class AWTelemetryHandler : public QObject
{
Q_OBJECT
public:
const char *REMOTE_TELEMETRY_URL = "https://arcanis.me/telemetry";
explicit AWTelemetryHandler(QObject *_parent = nullptr, const QString &_clientId = "");
~AWTelemetryHandler() override;
Q_INVOKABLE [[nodiscard]] QStringList get(const QString &_group) const;
Q_INVOKABLE [[nodiscard]] QString getLast(const QString &_group) const;
Q_INVOKABLE void init(int _count, bool _enableRemote, const QString &_clientId);
Q_INVOKABLE [[nodiscard]] bool put(const QString &_group, const QString &_value) const;
Q_INVOKABLE void uploadTelemetry(const QString &_group, const QString &_value);
signals:
void replyReceived(const QString &_message);
private slots:
void telemetryReplyRecieved(QNetworkReply *_reply);
private:
static QString getKey(int _count);
QString m_clientId;
QString m_localFile;
int m_storeCount = 0;
bool m_uploadEnabled = false;
};
#endif /* AWTELEMETRYHANDLER_H */

View File

@ -21,25 +21,22 @@
#include <QDesktopServices> #include <QDesktopServices>
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonParseError>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkReply> #include <QNetworkReply>
#include <QNetworkRequest>
#include <QSettings> #include <QSettings>
#include <QtConcurrent/QtConcurrent> #include <QStandardPaths>
#include "awdebug.h" #include "awdebug.h"
AWUpdateHelper::AWUpdateHelper(QObject *parent) AWUpdateHelper::AWUpdateHelper(QObject *_parent)
: QObject(parent) : QObject(_parent)
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
m_foundVersion = QVersionNumber::fromString(VERSION); m_foundVersion = QVersionNumber::fromString(VERSION);
m_genericConfig = QString("%1/awesomewidgets/general.ini") m_genericConfig = QString("%1/awesomewidgets/general.ini")
.arg(QStandardPaths::writableLocation( .arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation));
QStandardPaths::GenericDataLocation));
} }
@ -49,17 +46,15 @@ AWUpdateHelper::~AWUpdateHelper()
} }
void AWUpdateHelper::checkUpdates(const bool showAnyway) void AWUpdateHelper::checkUpdates(const bool _showAnyway)
{ {
qCDebug(LOG_AW) << "Show anyway" << showAnyway; qCDebug(LOG_AW) << "Show anyway" << _showAnyway;
// showAnyway options requires to show message if no updates found on direct // showAnyway options requires to show message if no updates found on direct
// request. In case of automatic check no message will be shown // request. In case of automatic check no message will be shown
QNetworkAccessManager *manager = new QNetworkAccessManager(nullptr); auto *manager = new QNetworkAccessManager(nullptr);
connect(manager, &QNetworkAccessManager::finished, connect(manager, &QNetworkAccessManager::finished,
[showAnyway, this](QNetworkReply *reply) { [_showAnyway, this](QNetworkReply *reply) { return versionReplyRecieved(reply, _showAnyway); });
return versionReplyRecieved(reply, showAnyway);
});
manager->get(QNetworkRequest(QUrl(VERSION_API))); manager->get(QNetworkRequest(QUrl(VERSION_API)));
} }
@ -68,18 +63,14 @@ void AWUpdateHelper::checkUpdates(const bool showAnyway)
bool AWUpdateHelper::checkVersion() bool AWUpdateHelper::checkVersion()
{ {
QSettings settings(m_genericConfig, QSettings::IniFormat); QSettings settings(m_genericConfig, QSettings::IniFormat);
QVersionNumber version = QVersionNumber::fromString( QVersionNumber version = QVersionNumber::fromString(settings.value("Version", QString(VERSION)).toString());
settings.value(QString("Version"), QString(VERSION)).toString());
// update version // update version
settings.setValue(QString("Version"), QString(VERSION)); settings.setValue("Version", QString(VERSION));
settings.sync(); settings.sync();
qCInfo(LOG_AW) << "Found version" << version << "actual one is" qCInfo(LOG_AW) << "Found version" << version << "actual one is" << m_foundVersion;
<< m_foundVersion;
if ((version != m_foundVersion) && (!QString(CHANGELOG).isEmpty())) { if ((version != m_foundVersion) && (!QString(CHANGELOG).isEmpty())) {
genMessageBox(i18n("Changelog of %1", QString(VERSION)), genMessageBox(i18nc("Changelog of %1", VERSION), QString(CHANGELOG).replace('@', '\n'), QMessageBox::Ok)
QString(CHANGELOG).replace(QChar('@'), QChar('\n')),
QMessageBox::Ok)
->open(); ->open();
return true; return true;
} else if (version != m_foundVersion) { } else if (version != m_foundVersion) {
@ -93,47 +84,40 @@ bool AWUpdateHelper::checkVersion()
} }
void AWUpdateHelper::showInfo(const QVersionNumber version) void AWUpdateHelper::showInfo(const QVersionNumber &_version)
{ {
qCDebug(LOG_AW) << "Version" << version; qCDebug(LOG_AW) << "Version" << _version;
QString text QString text = i18n("You are using the actual version %1", _version.toString());
= i18n("You are using the actual version %1", version.toString());
if (!QString(COMMIT_SHA).isEmpty()) if (!QString(COMMIT_SHA).isEmpty())
text += QString(" (%1)").arg(QString(COMMIT_SHA)); text += QString(" (%1)").arg(QString(COMMIT_SHA));
return genMessageBox(i18n("No new version found"), text, QMessageBox::Ok) return genMessageBox(i18n("No new version found"), text, QMessageBox::Ok)->open();
->open();
} }
void AWUpdateHelper::showUpdates(const QVersionNumber version) void AWUpdateHelper::showUpdates(const QVersionNumber &_version)
{ {
qCDebug(LOG_AW) << "Version" << version; qCDebug(LOG_AW) << "Version" << _version;
QString text; QString text;
text += i18n("Current version : %1", QString(VERSION)); text += i18nc("Current version : %1", VERSION);
text += QString(COMMIT_SHA).isEmpty() text += QString(COMMIT_SHA).isEmpty() ? "\n" : QString(" (%1)\n").arg(QString(COMMIT_SHA));
? QString("\n") text += i18n("New version : %1", _version.toString()) + "\n\n";
: QString(" (%1)\n").arg(QString(COMMIT_SHA));
text += i18n("New version : %1", version.toString()) + QString("\n\n");
text += i18n("Click \"Ok\" to download"); text += i18n("Click \"Ok\" to download");
genMessageBox(i18n("There are updates"), text, genMessageBox(i18n("There are updates"), text, QMessageBox::Ok | QMessageBox::Cancel)
QMessageBox::Ok | QMessageBox::Cancel)
->open(this, SLOT(userReplyOnUpdates(QAbstractButton *))); ->open(this, SLOT(userReplyOnUpdates(QAbstractButton *)));
} }
void AWUpdateHelper::userReplyOnUpdates(QAbstractButton *button) void AWUpdateHelper::userReplyOnUpdates(QAbstractButton *_button)
{ {
QMessageBox::ButtonRole ret QMessageBox::ButtonRole ret = dynamic_cast<QMessageBox *>(sender())->buttonRole(_button);
= static_cast<QMessageBox *>(sender())->buttonRole(button);
qCInfo(LOG_AW) << "User select" << ret; qCInfo(LOG_AW) << "User select" << ret;
switch (ret) { switch (ret) {
case QMessageBox::AcceptRole: case QMessageBox::AcceptRole:
QDesktopServices::openUrl(QString(RELEASES) QDesktopServices::openUrl(QString(RELEASES) + m_foundVersion.toString());
+ m_foundVersion.toString());
break; break;
case QMessageBox::RejectRole: case QMessageBox::RejectRole:
default: default:
@ -142,50 +126,49 @@ void AWUpdateHelper::userReplyOnUpdates(QAbstractButton *button)
} }
void AWUpdateHelper::versionReplyRecieved(QNetworkReply *reply, void AWUpdateHelper::versionReplyRecieved(QNetworkReply *_reply, const bool _showAnyway)
const bool showAnyway)
{ {
qCDebug(LOG_AW) << "Return code" << reply->error() << "with message" qCDebug(LOG_AW) << "Show message anyway" << _showAnyway;
<< reply->errorString() << "and show anyway" << showAnyway; if (_reply->error() != QNetworkReply::NoError) {
qCWarning(LOG_AW) << "An error occurs" << _reply->error() << "with message" << _reply->errorString();
return;
}
QJsonParseError error; QJsonParseError error = QJsonParseError();
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error); QJsonDocument jsonDoc = QJsonDocument::fromJson(_reply->readAll(), &error);
if ((reply->error() != QNetworkReply::NoError) if (error.error != QJsonParseError::NoError) {
|| (error.error != QJsonParseError::NoError)) {
qCWarning(LOG_AW) << "Parse error" << error.errorString(); qCWarning(LOG_AW) << "Parse error" << error.errorString();
return; return;
} }
reply->deleteLater(); _reply->deleteLater();
// convert to map // convert to map
QVariantMap firstRelease = jsonDoc.toVariant().toList().first().toMap(); QVariantMap firstRelease = jsonDoc.toVariant().toList().first().toMap();
QString version = firstRelease[QString("tag_name")].toString(); QString version = firstRelease["tag_name"].toString();
version.remove(QString("V.")); version.remove("V.");
m_foundVersion = QVersionNumber::fromString(version); m_foundVersion = QVersionNumber::fromString(version);
qCInfo(LOG_AW) << "Update found version to" << m_foundVersion; qCInfo(LOG_AW) << "Update found version to" << m_foundVersion;
QVersionNumber oldVersion = QVersionNumber::fromString(VERSION); QVersionNumber oldVersion = QVersionNumber::fromString(VERSION);
if (oldVersion < m_foundVersion) if (oldVersion < m_foundVersion)
return showUpdates(m_foundVersion); return showUpdates(m_foundVersion);
else if (showAnyway) else if (_showAnyway)
return showInfo(m_foundVersion); return showInfo(m_foundVersion);
} }
// additional method which is used to show message box which does not block UI // additional method which is used to show message box which does not block UI
QMessageBox * QMessageBox *AWUpdateHelper::genMessageBox(const QString &_title, const QString &_body,
AWUpdateHelper::genMessageBox(const QString title, const QString body, const QMessageBox::StandardButtons _buttons)
const QMessageBox::StandardButtons buttons)
{ {
qCDebug(LOG_AW) << "Construct message box with title" << title << "and body" qCDebug(LOG_AW) << "Construct message box with title" << _title << "and body" << _body;
<< body;
QMessageBox *msgBox = new QMessageBox(nullptr); auto *msgBox = new QMessageBox(nullptr);
msgBox->setAttribute(Qt::WA_DeleteOnClose); msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->setModal(false); msgBox->setModal(false);
msgBox->setWindowTitle(title); msgBox->setWindowTitle(_title);
msgBox->setText(body); msgBox->setText(_body);
msgBox->setStandardButtons(buttons); msgBox->setStandardButtons(_buttons);
msgBox->setIcon(QMessageBox::Information); msgBox->setIcon(QMessageBox::Information);
return msgBox; return msgBox;

View File

@ -31,20 +31,20 @@ class AWUpdateHelper : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit AWUpdateHelper(QObject *parent = nullptr); explicit AWUpdateHelper(QObject *_parent = nullptr);
virtual ~AWUpdateHelper(); ~AWUpdateHelper() override;
void checkUpdates(const bool showAnyway = false); void checkUpdates(bool _showAnyway = false);
bool checkVersion(); bool checkVersion();
private slots: private slots:
void showInfo(const QVersionNumber version); static void showInfo(const QVersionNumber &_version);
void showUpdates(const QVersionNumber version); void showUpdates(const QVersionNumber &_version);
void userReplyOnUpdates(QAbstractButton *button); void userReplyOnUpdates(QAbstractButton *_button);
void versionReplyRecieved(QNetworkReply *reply, const bool showAnyway); void versionReplyRecieved(QNetworkReply *_reply, bool _showAnyway);
private: private:
QMessageBox *genMessageBox(const QString title, const QString body, static QMessageBox *genMessageBox(const QString &_title, const QString &_body,
const QMessageBox::StandardButtons buttons); QMessageBox::StandardButtons _buttons);
QVersionNumber m_foundVersion; QVersionNumber m_foundVersion;
QString m_genericConfig; QString m_genericConfig;
}; };

View File

@ -7,7 +7,7 @@ include_directories(
${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}
${PROJECT_TRDPARTY_DIR} ${PROJECT_TRDPARTY_DIR}
${Qt_INCLUDE} ${Qt_INCLUDE}
${Kf5_INCLUDE} ${Kf6_INCLUDE}
) )
file(GLOB SUBPROJECT_SOURCE *.cpp ${PROJECT_TRDPARTY_DIR}/qreplytimeout/*.cpp ${CMAKE_SOURCE_DIR}/*.cpp) file(GLOB SUBPROJECT_SOURCE *.cpp ${PROJECT_TRDPARTY_DIR}/qreplytimeout/*.cpp ${CMAKE_SOURCE_DIR}/*.cpp)
@ -19,6 +19,7 @@ set(SUBPROJECT_FORMATTERS ${CMAKE_CURRENT_SOURCE_DIR}/formatters)
set(SUBPROJECT_GRAPHITEMS ${CMAKE_CURRENT_SOURCE_DIR}/desktops) set(SUBPROJECT_GRAPHITEMS ${CMAKE_CURRENT_SOURCE_DIR}/desktops)
set(SUBPROJECT_QUOTES ${CMAKE_CURRENT_SOURCE_DIR}/quotes) set(SUBPROJECT_QUOTES ${CMAKE_CURRENT_SOURCE_DIR}/quotes)
set(SUBPROJECT_SCRIPTS ${CMAKE_CURRENT_SOURCE_DIR}/scripts) set(SUBPROJECT_SCRIPTS ${CMAKE_CURRENT_SOURCE_DIR}/scripts)
set(SUBPROJECT_REQUESTS ${CMAKE_CURRENT_SOURCE_DIR}/requests)
set(SUBPROJECT_UPGRADE ${CMAKE_CURRENT_SOURCE_DIR}/upgrade) set(SUBPROJECT_UPGRADE ${CMAKE_CURRENT_SOURCE_DIR}/upgrade)
set(SUBPROJECT_WEATHER ${CMAKE_CURRENT_SOURCE_DIR}/weather) set(SUBPROJECT_WEATHER ${CMAKE_CURRENT_SOURCE_DIR}/weather)
file(GLOB SUBPROJECT_WEATHER_JSON_IN *.json) file(GLOB SUBPROJECT_WEATHER_JSON_IN *.json)
@ -27,17 +28,18 @@ file(RELATIVE_PATH SUBPROJECT_WEATHER_JSON ${CMAKE_SOURCE_DIR} ${SUBPROJECT_WEAT
# prepare # prepare
configure_file(${SUBPROJECT_WEATHER_JSON_IN} ${CMAKE_CURRENT_BINARY_DIR}/${SUBPROJECT_WEATHER_JSON}) configure_file(${SUBPROJECT_WEATHER_JSON_IN} ${CMAKE_CURRENT_BINARY_DIR}/${SUBPROJECT_WEATHER_JSON})
qt5_wrap_ui(SUBPROJECT_UI_HEADER ${SUBPROJECT_UI}) qt6_wrap_ui(SUBPROJECT_UI_HEADER ${SUBPROJECT_UI})
add_library(${SUBPROJECT} STATIC ${SUBPROJECT_SOURCE} ${SUBPROJECT_HEADER} ${SUBPROJECT_UI_HEADER}) add_library(${SUBPROJECT} STATIC ${SUBPROJECT_SOURCE} ${SUBPROJECT_HEADER} ${SUBPROJECT_UI_HEADER})
target_link_libraries(${SUBPROJECT} ${Qt_LIBRARIES} ${Kf5_LIBRARIES}) target_link_libraries(${SUBPROJECT} ${Qt_LIBRARIES} ${Kf6_LIBRARIES})
# install # install
install(DIRECTORY ${SUBPROJECT_CONFIGS} DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME}) install(DIRECTORY ${SUBPROJECT_CONFIGS} DESTINATION ${KDE_INSTALL_DATADIR}/${PROJECT_NAME})
install(DIRECTORY ${SUBPROJECT_FORMATTERS} DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME}) install(DIRECTORY ${SUBPROJECT_FORMATTERS} DESTINATION ${KDE_INSTALL_DATADIR}/${PROJECT_NAME})
install(DIRECTORY ${SUBPROJECT_GRAPHITEMS} DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME}) install(DIRECTORY ${SUBPROJECT_GRAPHITEMS} DESTINATION ${KDE_INSTALL_DATADIR}/${PROJECT_NAME})
install(DIRECTORY ${SUBPROJECT_QUOTES} DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME}) install(DIRECTORY ${SUBPROJECT_QUOTES} DESTINATION ${KDE_INSTALL_DATADIR}/${PROJECT_NAME})
install(DIRECTORY ${SUBPROJECT_SCRIPTS} DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME}) install(DIRECTORY ${SUBPROJECT_SCRIPTS} DESTINATION ${KDE_INSTALL_DATADIR}/${PROJECT_NAME})
install(DIRECTORY ${SUBPROJECT_UPGRADE} DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME}) install(DIRECTORY ${SUBPROJECT_REQUESTS} DESTINATION ${KDE_INSTALL_DATADIR}/${PROJECT_NAME})
install(DIRECTORY ${SUBPROJECT_WEATHER} DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME}) install(DIRECTORY ${SUBPROJECT_UPGRADE} DESTINATION ${KDE_INSTALL_DATADIR}/${PROJECT_NAME})
install(FILES ${SUBPROJECT_INI} DESTINATION ${CONFIG_INSTALL_DIR}) install(DIRECTORY ${SUBPROJECT_WEATHER} DESTINATION ${KDE_INSTALL_DATADIR}/${PROJECT_NAME})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${SUBPROJECT_WEATHER_JSON} DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME}/weather) install(FILES ${SUBPROJECT_INI} DESTINATION /${KDE_INSTALL_CONFDIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${SUBPROJECT_WEATHER_JSON} DESTINATION ${KDE_INSTALL_DATADIR}/${PROJECT_NAME}/weather)

View File

@ -18,21 +18,22 @@
#include "abstractextitem.h" #include "abstractextitem.h"
#include <QDir> #include <QDir>
#include <QLocalServer>
#include <QRandomGenerator>
#include <QSettings> #include <QSettings>
#include <QStandardPaths> #include <QStandardPaths>
#include <QTime>
#include "abstractextitemaggregator.h" #include "abstractextitemaggregator.h"
#include "awdebug.h" #include "qcronscheduler.h"
AbstractExtItem::AbstractExtItem(QWidget *parent, const QString filePath) AbstractExtItem::AbstractExtItem(QObject *_parent, const QString &_filePath)
: QDialog(parent) : QObject(_parent)
, m_fileName(filePath) , m_fileName(_filePath)
{ {
qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; qCDebug(LOG_LIB) << __PRETTY_FUNCTION__;
qCDebug(LOG_LIB) << "Desktop name" << filePath; qCDebug(LOG_LIB) << "Desktop name" << _filePath;
m_name = m_fileName; m_name = m_fileName;
} }
@ -41,6 +42,12 @@ AbstractExtItem::AbstractExtItem(QWidget *parent, const QString filePath)
AbstractExtItem::~AbstractExtItem() AbstractExtItem::~AbstractExtItem()
{ {
qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; qCDebug(LOG_LIB) << __PRETTY_FUNCTION__;
if (m_socket) {
m_socket->close();
QLocalServer::removeServer(socket());
m_socket->deleteLater();
}
} }
@ -50,8 +57,7 @@ void AbstractExtItem::bumpApi(const int _newVer)
// update for current API // update for current API
if ((apiVersion() > 0) && (apiVersion() < _newVer)) { if ((apiVersion() > 0) && (apiVersion() < _newVer)) {
qCWarning(LOG_LIB) << "Bump API version from" << apiVersion() << "to" qCWarning(LOG_LIB) << "Bump API version from" << apiVersion() << "to" << _newVer;
<< _newVer;
setApiVersion(_newVer); setApiVersion(_newVer);
writeConfiguration(); writeConfiguration();
} }
@ -63,23 +69,41 @@ void AbstractExtItem::copyDefaults(AbstractExtItem *_other) const
_other->setActive(isActive()); _other->setActive(isActive());
_other->setApiVersion(apiVersion()); _other->setApiVersion(apiVersion());
_other->setComment(comment()); _other->setComment(comment());
_other->setCron(cron());
_other->setInterval(interval()); _other->setInterval(interval());
_other->setName(name()); _other->setName(name());
_other->setSocket(socket());
}
void AbstractExtItem::startTimer()
{
if (!socket().isEmpty())
// check if there is active socket setup
return;
else if (!cron().isEmpty())
// check if there is active scheduler
return;
else if (m_times == 1)
// check if it is time to update
emit(requestDataUpdate());
// update counter value
if (m_times >= interval())
m_times = 0;
m_times++;
} }
QString AbstractExtItem::writtableConfig() const QString AbstractExtItem::writtableConfig() const
{ {
QString path = m_fileName; auto path = m_fileName;
QString name = QFileInfo(path).fileName(); auto name = QFileInfo(path).fileName();
path.remove(path.count() - name.count() - 1, name.count() + 1); path.remove(path.length() - name.length() - 1, name.length() + 1);
QString dir = QFileInfo(path).fileName(); auto dir = QFileInfo(path).fileName();
return QString("%1/awesomewidgets/%2/%3") return QString("%1/awesomewidgets/%2/%3")
.arg(QStandardPaths::writableLocation( .arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), dir, name);
QStandardPaths::GenericDataLocation))
.arg(dir)
.arg(name);
} }
@ -95,6 +119,12 @@ QString AbstractExtItem::comment() const
} }
QString AbstractExtItem::cron() const
{
return m_cron;
}
QString AbstractExtItem::fileName() const QString AbstractExtItem::fileName() const
{ {
return m_fileName; return m_fileName;
@ -125,7 +155,13 @@ int AbstractExtItem::number() const
} }
QString AbstractExtItem::tag(const QString _type) const QString AbstractExtItem::socket() const
{
return m_socketFile;
}
QString AbstractExtItem::tag(const QString &_type) const
{ {
qCDebug(LOG_LIB) << "Tag type" << _type; qCDebug(LOG_LIB) << "Tag type" << _type;
@ -149,7 +185,7 @@ void AbstractExtItem::setActive(const bool _state)
} }
void AbstractExtItem::setComment(const QString _comment) void AbstractExtItem::setComment(const QString &_comment)
{ {
qCDebug(LOG_LIB) << "Comment" << _comment; qCDebug(LOG_LIB) << "Comment" << _comment;
@ -157,6 +193,26 @@ void AbstractExtItem::setComment(const QString _comment)
} }
void AbstractExtItem::setCron(const QString &_cron)
{
qCDebug(LOG_LIB) << "Cron string" << _cron;
// deinit module first
if (m_scheduler) {
disconnect(m_scheduler, SIGNAL(activated()), this, SIGNAL(requestDataUpdate()));
delete m_scheduler;
}
m_cron = _cron;
if (cron().isEmpty())
return;
// init scheduler
m_scheduler = new QCronScheduler(this);
m_scheduler->parse(cron());
connect(m_scheduler, SIGNAL(activated()), this, SIGNAL(requestDataUpdate()));
}
void AbstractExtItem::setInterval(const int _interval) void AbstractExtItem::setInterval(const int _interval)
{ {
qCDebug(LOG_LIB) << "Interval" << _interval; qCDebug(LOG_LIB) << "Interval" << _interval;
@ -167,7 +223,7 @@ void AbstractExtItem::setInterval(const int _interval)
} }
void AbstractExtItem::setName(const QString _name) void AbstractExtItem::setName(const QString &_name)
{ {
qCDebug(LOG_LIB) << "Name" << _name; qCDebug(LOG_LIB) << "Name" << _name;
@ -182,9 +238,7 @@ void AbstractExtItem::setNumber(int _number)
if (generateNumber) { if (generateNumber) {
_number = []() { _number = []() {
qCWarning(LOG_LIB) << "Number is empty, generate new one"; qCWarning(LOG_LIB) << "Number is empty, generate new one";
// we suppose that currentTIme().msec() is always valid time auto n = QRandomGenerator::global()->generate() % 1000;
qsrand(static_cast<uint>(QTime::currentTime().msec()));
int n = qrand() % 1000;
qCInfo(LOG_LIB) << "Generated number is" << n; qCInfo(LOG_LIB) << "Generated number is" << n;
return n; return n;
}(); }();
@ -196,20 +250,53 @@ void AbstractExtItem::setNumber(int _number)
} }
void AbstractExtItem::setSocket(const QString &_socket)
{
qCDebug(LOG_LIB) << "Socket" << _socket;
// remove old socket first
deinitSocket();
m_socketFile = _socket;
}
void AbstractExtItem::deinitSocket()
{
if (!m_socket)
return;
m_socket->close();
QLocalServer::removeServer(socket());
disconnect(m_socket, SIGNAL(newConnection()), this, SLOT(newConnectionReceived()));
delete m_socket;
}
void AbstractExtItem::initSocket()
{
// remove old socket first
deinitSocket();
m_socket = new QLocalServer(this);
bool listening = m_socket->listen(socket());
qCInfo(LOG_LIB) << "Server listening on" << socket() << listening;
connect(m_socket, SIGNAL(newConnection()), this, SLOT(newConnectionReceived()));
}
void AbstractExtItem::readConfiguration() void AbstractExtItem::readConfiguration()
{ {
QSettings settings(m_fileName, QSettings::IniFormat); QSettings settings(m_fileName, QSettings::IniFormat);
settings.beginGroup(QString("Desktop Entry")); settings.beginGroup("Desktop Entry");
setName(settings.value(QString("Name"), name()).toString()); setName(settings.value("Name", name()).toString());
setComment(settings.value(QString("Comment"), comment()).toString()); setComment(settings.value("Comment", comment()).toString());
setApiVersion( setApiVersion(settings.value("X-AW-ApiVersion", apiVersion()).toInt());
settings.value(QString("X-AW-ApiVersion"), apiVersion()).toInt()); setActive(settings.value("X-AW-Active", isActive()).toBool());
setActive( setInterval(settings.value("X-AW-Interval", interval()).toInt());
settings.value(QString("X-AW-Active"), QVariant(isActive())).toString() setNumber(settings.value("X-AW-Number", number()).toInt());
== QString("true")); setCron(settings.value("X-AW-Schedule", cron()).toString());
setInterval(settings.value(QString("X-AW-Interval"), interval()).toInt()); setSocket(settings.value("X-AW-Socket", socket()).toString());
setNumber(settings.value(QString("X-AW-Number"), number()).toInt());
settings.endGroup(); settings.endGroup();
} }
@ -228,15 +315,23 @@ void AbstractExtItem::writeConfiguration() const
QSettings settings(writtableConfig(), QSettings::IniFormat); QSettings settings(writtableConfig(), QSettings::IniFormat);
qCInfo(LOG_LIB) << "Configuration file" << settings.fileName(); qCInfo(LOG_LIB) << "Configuration file" << settings.fileName();
settings.beginGroup(QString("Desktop Entry")); settings.beginGroup("Desktop Entry");
settings.setValue(QString("Encoding"), QString("UTF-8")); settings.setValue("Encoding", "UTF-8");
settings.setValue(QString("Name"), name()); settings.setValue("Name", name());
settings.setValue(QString("Comment"), comment()); settings.setValue("Comment", comment());
settings.setValue(QString("X-AW-ApiVersion"), apiVersion()); settings.setValue("X-AW-ApiVersion", apiVersion());
settings.setValue(QString("X-AW-Active"), QVariant(isActive()).toString()); settings.setValue("X-AW-Active", isActive());
settings.setValue(QString("X-AW-Interval"), interval()); settings.setValue("X-AW-Interval", interval());
settings.setValue(QString("X-AW-Number"), number()); settings.setValue("X-AW-Number", number());
settings.setValue("X-AW-Schedule", cron());
settings.setValue("X-AW-Socket", socket());
settings.endGroup(); settings.endGroup();
settings.sync(); settings.sync();
} }
void AbstractExtItem::newConnectionReceived()
{
emit(requestDataUpdate());
}

View File

@ -18,69 +18,89 @@
#ifndef ABSTRACTEXTITEM_H #ifndef ABSTRACTEXTITEM_H
#define ABSTRACTEXTITEM_H #define ABSTRACTEXTITEM_H
#include <QDialog>
#include <QVariant> #include <QVariant>
class AbstractExtItem : public QDialog class QCronScheduler;
class QLocalServer;
class QWidget;
class AbstractExtItem : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool active READ isActive WRITE setActive) Q_PROPERTY(bool active READ isActive WRITE setActive)
Q_PROPERTY(int apiVersion READ apiVersion WRITE setApiVersion) Q_PROPERTY(int apiVersion READ apiVersion WRITE setApiVersion)
Q_PROPERTY(QString comment READ comment WRITE setComment) Q_PROPERTY(QString comment READ comment WRITE setComment)
Q_PROPERTY(QString cron READ cron WRITE setCron)
Q_PROPERTY(QString fileName READ fileName) Q_PROPERTY(QString fileName READ fileName)
Q_PROPERTY(int interval READ interval WRITE setInterval) Q_PROPERTY(int interval READ interval WRITE setInterval)
Q_PROPERTY(QString name READ name WRITE setName) Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(int number READ number WRITE setNumber) Q_PROPERTY(int number READ number WRITE setNumber)
Q_PROPERTY(QString socket READ socket WRITE setSocket)
Q_PROPERTY(QString uniq READ uniq) Q_PROPERTY(QString uniq READ uniq)
public: public:
explicit AbstractExtItem(QWidget *parent, explicit AbstractExtItem(QObject *_parent = nullptr, const QString &_filePath = "");
const QString filePath = QString()); ~AbstractExtItem() override;
virtual ~AbstractExtItem(); virtual void bumpApi(int _newVer);
virtual void bumpApi(const int _newVer); virtual AbstractExtItem *copy(const QString &_fileName, int _number) = 0;
virtual AbstractExtItem *copy(const QString _fileName, const int _number)
= 0;
virtual void copyDefaults(AbstractExtItem *_other) const; virtual void copyDefaults(AbstractExtItem *_other) const;
QString writtableConfig() const; virtual void startTimer();
[[nodiscard]] QString writtableConfig() const;
// get methods // get methods
int apiVersion() const; [[nodiscard]] int apiVersion() const;
QString comment() const; [[nodiscard]] QString comment() const;
QString fileName() const; [[nodiscard]] QString cron() const;
int interval() const; [[nodiscard]] QString fileName() const;
bool isActive() const; [[nodiscard]] int interval() const;
QString name() const; [[nodiscard]] bool isActive() const;
int number() const; [[nodiscard]] QString name() const;
QString tag(const QString _type) const; [[nodiscard]] int number() const;
virtual QString uniq() const = 0; [[nodiscard]] QString socket() const;
[[nodiscard]] QString tag(const QString &_type) const;
[[nodiscard]] virtual QString uniq() const = 0;
// set methods // set methods
void setApiVersion(const int _apiVersion = 0); void setApiVersion(int _apiVersion);
void setActive(const bool _state = true); void setActive(bool _state);
void setComment(const QString _comment = QString("empty")); void setComment(const QString &_comment);
void setInterval(const int _interval = 1); void setCron(const QString &_cron);
void setName(const QString _name = QString("none")); void setInterval(int _interval);
void setNumber(int _number = -1); void setName(const QString &_name);
void setNumber(int _number);
void setSocket(const QString &_socket);
signals: signals:
void dataReceived(const QVariantHash &data); void dataReceived(const QVariantHash &_data);
void requestDataUpdate();
public slots: public slots:
virtual void deinitSocket();
virtual void initSocket();
virtual void readConfiguration(); virtual void readConfiguration();
virtual QVariantHash run() = 0; virtual QVariantHash run() = 0;
virtual int showConfiguration(const QVariant args = QVariant()) = 0; virtual int showConfiguration(QWidget *_parent, const QVariant &_args) = 0;
bool tryDelete() const; [[nodiscard]] virtual bool tryDelete() const;
virtual void writeConfiguration() const; virtual void writeConfiguration() const;
private slots:
void newConnectionReceived();
private: private:
QString m_fileName = QString("/dev/null"); QCronScheduler *m_scheduler = nullptr;
virtual void translate() = 0; QString m_fileName = "/dev/null";
int m_times = 0;
// FIXME find a better way to do it
virtual void translate(void *_ui) = 0;
// properties // properties
int m_apiVersion = 0; int m_apiVersion = 0;
bool m_active = true; bool m_active = true;
QString m_comment = QString("empty"); QString m_comment = "empty";
QString m_cron = "";
int m_interval = 1; int m_interval = 1;
QString m_name = QString("none"); QString m_name = "none";
int m_number = -1; int m_number = -1;
QLocalServer *m_socket = nullptr;
QString m_socketFile = "";
}; };

View File

@ -20,145 +20,157 @@
#include <KI18n/KLocalizedString> #include <KI18n/KLocalizedString>
#include <QFileInfo> #include <QDir>
#include <QInputDialog> #include <QInputDialog>
#include <QPushButton> #include <QPushButton>
#include <utility>
AbstractExtItemAggregator::AbstractExtItemAggregator(QWidget *parent, AbstractExtItemAggregator::AbstractExtItemAggregator(QObject *_parent, QString _type)
const QString type) : QObject(_parent)
: QDialog(parent) , m_type(std::move(_type))
, ui(new Ui::AbstractExtItemAggregator)
, m_type(type)
{ {
qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; qCDebug(LOG_LIB) << __PRETTY_FUNCTION__;
ui->setupUi(this); // create directory at $HOME
copyButton auto localDir = QString("%1/awesomewidgets/%2")
= ui->buttonBox->addButton(i18n("Copy"), QDialogButtonBox::ActionRole); .arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), type());
createButton = ui->buttonBox->addButton(i18n("Create"), QDir localDirectory;
QDialogButtonBox::ActionRole); if (localDirectory.mkpath(localDir))
deleteButton = ui->buttonBox->addButton(i18n("Remove"), qCInfo(LOG_LIB) << "Created directory" << localDir;
QDialogButtonBox::ActionRole);
connect(ui->buttonBox, SIGNAL(clicked(QAbstractButton *)), this,
SLOT(editItemButtonPressed(QAbstractButton *)));
connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
connect(ui->listWidget, SIGNAL(itemActivated(QListWidgetItem *)), this,
SLOT(editItemActivated(QListWidgetItem *)));
} }
AbstractExtItemAggregator::~AbstractExtItemAggregator() void AbstractExtItemAggregator::copyItem(QListWidget *_widget)
{ {
qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; auto source = itemFromWidget(_widget);
auto fileName = getName();
delete ui; auto number = uniqNumber();
} auto dir = QString("%1/awesomewidgets/%2")
.arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), m_type);
void AbstractExtItemAggregator::copyItem()
{
AbstractExtItem *source = itemFromWidget();
QString fileName = getName();
int number = uniqNumber();
QString dir = QString("%1/awesomewidgets/%2")
.arg(QStandardPaths::writableLocation(
QStandardPaths::GenericDataLocation))
.arg(m_type);
if ((!source) || (fileName.isEmpty())) { if ((!source) || (fileName.isEmpty())) {
qCWarning(LOG_LIB) << "Nothing to copy"; qCWarning(LOG_LIB) << "Nothing to copy";
return; return;
} }
QString filePath = QString("%1/%2").arg(dir).arg(fileName); auto filePath = QString("%1/%2").arg(dir, fileName);
AbstractExtItem *newItem = source->copy(filePath, number); auto newItem = source->copy(filePath, number);
if (newItem->showConfiguration(configArgs()) == 1) { if (newItem->showConfiguration(nullptr, configArgs()) == 1) {
initItems(); initItems();
repaintList(); repaintList(_widget);
} }
} }
void AbstractExtItemAggregator::deleteItem() void AbstractExtItemAggregator::deleteItem(QListWidget *_widget)
{ {
AbstractExtItem *source = itemFromWidget(); auto source = itemFromWidget(_widget);
if (!source) { if (!source) {
qCWarning(LOG_LIB) << "Nothing to delete"; qCWarning(LOG_LIB) << "Nothing to delete";
return; return;
}; }
if (source->tryDelete()) { if (source->tryDelete()) {
initItems(); initItems();
repaintList(); repaintList(_widget);
} }
} }
void AbstractExtItemAggregator::editItem() void AbstractExtItemAggregator::editItem(QListWidget *_widget)
{ {
AbstractExtItem *source = itemFromWidget(); auto source = itemFromWidget(_widget);
if (!source) { if (!source) {
qCWarning(LOG_LIB) << "Nothing to edit"; qCWarning(LOG_LIB) << "Nothing to edit";
return; return;
};
if (source->showConfiguration(configArgs()) == 1) {
initItems();
repaintList();
} }
if (source->showConfiguration(nullptr, configArgs()) == 1) {
initItems();
repaintList(_widget);
}
}
int AbstractExtItemAggregator::exec()
{
auto dialog = new QDialog();
auto ui = new Ui::AbstractExtItemAggregator();
ui->setupUi(dialog);
auto copyButton = ui->buttonBox->addButton(i18n("Copy"), QDialogButtonBox::ActionRole);
auto createButton = ui->buttonBox->addButton(i18n("Create"), QDialogButtonBox::ActionRole);
auto deleteButton = ui->buttonBox->addButton(i18n("Remove"), QDialogButtonBox::ActionRole);
connect(ui->buttonBox, &QDialogButtonBox::clicked, [&](QAbstractButton *_button) {
if (dynamic_cast<QPushButton *>(_button) == copyButton)
copyItem(ui->listWidget);
else if (dynamic_cast<QPushButton *>(_button) == createButton)
doCreateItem(ui->listWidget);
else if (dynamic_cast<QPushButton *>(_button) == deleteButton)
deleteItem(ui->listWidget);
else if (ui->buttonBox->buttonRole(_button) == QDialogButtonBox::AcceptRole)
editItem(ui->listWidget);
});
connect(ui->buttonBox, &QDialogButtonBox::rejected, [dialog]() { dialog->reject(); });
connect(ui->listWidget, &QListWidget::itemActivated, [&](QListWidgetItem *) { editItem(ui->listWidget); });
repaintList(ui->listWidget);
auto ret = dialog->exec();
dialog->deleteLater();
delete ui;
return ret;
} }
QString AbstractExtItemAggregator::getName() QString AbstractExtItemAggregator::getName()
{ {
bool ok; bool ok;
QString name = QInputDialog::getText(this, i18n("Enter file name"), auto name = QInputDialog::getText(nullptr, i18n("Enter file name"), i18n("File name"), QLineEdit::Normal, "", &ok);
i18n("File name"), QLineEdit::Normal,
QString(""), &ok);
if ((!ok) || (name.isEmpty())) if ((!ok) || (name.isEmpty()))
return QString(""); return "";
if (!name.endsWith(QString(".desktop"))) if (!name.endsWith(".desktop"))
name += QString(".desktop"); name += ".desktop";
return name; return name;
} }
AbstractExtItem *AbstractExtItemAggregator::itemFromWidget() AbstractExtItem *AbstractExtItemAggregator::itemFromWidget(QListWidget *_widget) const
{ {
QListWidgetItem *widgetItem = ui->listWidget->currentItem(); auto widgetItem = _widget->currentItem();
if (!widgetItem) if (!widgetItem)
return nullptr; return nullptr;
AbstractExtItem *found = nullptr; AbstractExtItem *found = nullptr;
for (auto item : items()) { for (auto &item : items()) {
QString fileName = QFileInfo(item->fileName()).fileName(); auto fileName = QFileInfo(item->fileName()).fileName();
if (fileName != widgetItem->text()) if (fileName != widgetItem->text())
continue; continue;
found = item; found = item;
break; break;
} }
if (!found) if (!found)
qCWarning(LOG_LIB) << "Could not find item by name" qCWarning(LOG_LIB) << "Could not find item by name" << widgetItem->text();
<< widgetItem->text();
return found; return found;
} }
void AbstractExtItemAggregator::repaintList() void AbstractExtItemAggregator::repaintList(QListWidget *_widget) const
{ {
ui->listWidget->clear(); _widget->clear();
for (auto _item : items()) { for (auto &_item : items()) {
QString fileName = QFileInfo(_item->fileName()).fileName(); QString fileName = QFileInfo(_item->fileName()).fileName();
QListWidgetItem *item = new QListWidgetItem(fileName, ui->listWidget); auto item = new QListWidgetItem(fileName, _widget);
QStringList tooltip; QStringList tooltip;
tooltip.append(i18n("Name: %1", _item->name())); tooltip.append(i18n("Name: %1", _item->name()));
tooltip.append(i18n("Comment: %1", _item->comment())); tooltip.append(i18n("Comment: %1", _item->comment()));
tooltip.append(i18n("Identity: %1", _item->uniq())); tooltip.append(i18n("Identity: %1", _item->uniq()));
item->setToolTip(tooltip.join(QChar('\n'))); item->setToolTip(tooltip.join('\n'));
ui->listWidget->addItem(item); _widget->addItem(item);
} }
} }
@ -166,7 +178,7 @@ void AbstractExtItemAggregator::repaintList()
int AbstractExtItemAggregator::uniqNumber() const int AbstractExtItemAggregator::uniqNumber() const
{ {
QList<int> tagList; QList<int> tagList;
for (auto item : items()) for (auto &item : items())
tagList.append(item->number()); tagList.append(item->number());
int number = 0; int number = 0;
while (tagList.contains(number)) while (tagList.contains(number))
@ -182,34 +194,24 @@ QVariant AbstractExtItemAggregator::configArgs() const
} }
QStringList AbstractExtItemAggregator::directories() const
{
auto dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString("awesomewidgets/%1").arg(type()),
QStandardPaths::LocateDirectory);
return dirs;
}
QString AbstractExtItemAggregator::type() const QString AbstractExtItemAggregator::type() const
{ {
return m_type; return m_type;
} }
void AbstractExtItemAggregator::setConfigArgs(const QVariant _configArgs) void AbstractExtItemAggregator::setConfigArgs(const QVariant &_configArgs)
{ {
qCDebug(LOG_LIB) << "Configuration arguments" << _configArgs; qCDebug(LOG_LIB) << "Configuration arguments" << _configArgs;
m_configArgs = _configArgs; m_configArgs = _configArgs;
} }
void AbstractExtItemAggregator::editItemActivated(QListWidgetItem *)
{
return editItem();
}
void AbstractExtItemAggregator::editItemButtonPressed(QAbstractButton *button)
{
if (static_cast<QPushButton *>(button) == copyButton)
return copyItem();
else if (static_cast<QPushButton *>(button) == createButton)
return doCreateItem();
else if (static_cast<QPushButton *>(button) == deleteButton)
return deleteItem();
else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole)
return editItem();
}

View File

@ -18,7 +18,6 @@
#ifndef ABSTRACTEXTITEMAGGREGATOR_H #ifndef ABSTRACTEXTITEMAGGREGATOR_H
#define ABSTRACTEXTITEMAGGREGATOR_H #define ABSTRACTEXTITEMAGGREGATOR_H
#include <QDialog>
#include <QStandardPaths> #include <QStandardPaths>
#include "abstractextitem.h" #include "abstractextitem.h"
@ -26,73 +25,60 @@
class QAbstractButton; class QAbstractButton;
class QListWidget;
class QListWidgetItem; class QListWidgetItem;
namespace Ui
{
class AbstractExtItemAggregator;
}
class AbstractExtItemAggregator : public QDialog class AbstractExtItemAggregator : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QVariant configArgs READ configArgs WRITE setConfigArgs) Q_PROPERTY(QVariant configArgs READ configArgs WRITE setConfigArgs)
Q_PROPERTY(QVariant type READ type) Q_PROPERTY(QVariant type READ type)
public: public:
explicit AbstractExtItemAggregator(QWidget *parent, const QString type); explicit AbstractExtItemAggregator(QObject *_parent, QString _type);
virtual ~AbstractExtItemAggregator();
// methods // methods
void copyItem(); void copyItem(QListWidget *_widget);
template <class T> void createItem() template <class T> void createItem(QListWidget *_widget)
{ {
QString fileName = getName(); auto fileName = getName();
int number = uniqNumber(); auto number = uniqNumber();
QString dir = QString("%1/awesomewidgets/%2") auto dir = QString("%1/awesomewidgets/%2")
.arg(QStandardPaths::writableLocation( .arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), m_type);
QStandardPaths::GenericDataLocation))
.arg(m_type);
if (fileName.isEmpty()) { if (fileName.isEmpty()) {
qCWarning(LOG_LIB) << "Nothing to create"; qCWarning(LOG_LIB) << "Nothing to create";
return; return;
}; }
QString filePath = QString("%1/%2").arg(dir).arg(fileName); auto filePath = QString("%1/%2").arg(dir, fileName);
T *newItem = new T(this, filePath); auto newItem = new T(this, filePath);
newItem->setNumber(number); newItem->setNumber(number);
if (newItem->showConfiguration(configArgs()) == 1) { if (newItem->showConfiguration(nullptr, configArgs()) == 1) {
initItems(); initItems();
repaintList(); repaintList(_widget);
}; }
}; };
void deleteItem(); void deleteItem(QListWidget *_widget);
void editItem(); void editItem(QListWidget *_widget);
[[nodiscard]] int exec();
QString getName(); QString getName();
AbstractExtItem *itemFromWidget(); virtual void initItems() = 0;
void repaintList(); [[nodiscard]] AbstractExtItem *itemFromWidget(QListWidget *_widget) const;
int uniqNumber() const; void repaintList(QListWidget *_widget) const;
[[nodiscard]] int uniqNumber() const;
// get methods // get methods
QVariant configArgs() const; [[nodiscard]] QVariant configArgs() const;
virtual QList<AbstractExtItem *> items() const = 0; [[nodiscard]] QStringList directories() const;
QString type() const; [[nodiscard]] virtual QList<AbstractExtItem *> items() const = 0;
[[nodiscard]] QString type() const;
// set methods // set methods
void setConfigArgs(const QVariant _configArgs); void setConfigArgs(const QVariant &_configArgs);
private slots:
void editItemActivated(QListWidgetItem *);
void editItemButtonPressed(QAbstractButton *button);
private: private:
// ui
Ui::AbstractExtItemAggregator *ui = nullptr;
QPushButton *copyButton = nullptr;
QPushButton *createButton = nullptr;
QPushButton *deleteButton = nullptr;
// properties // properties
QVariant m_configArgs; QVariant m_configArgs;
QString m_type; QString m_type;
// ui methods // ui methods
virtual void doCreateItem() = 0; virtual void doCreateItem(QListWidget *_widget) = 0;
virtual void initItems() = 0;
}; };

View File

@ -0,0 +1,45 @@
/***************************************************************************
* This file is part of awesome-widgets *
* *
* awesome-widgets is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* awesome-widgets is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#ifndef ABSTRACTQUOTESPROVIDER_H
#define ABSTRACTQUOTESPROVIDER_H
#include <QObject>
#include <QUrl>
#include "abstractextitem.h"
class AbstractQuotesProvider : public QObject
{
Q_OBJECT
public:
explicit AbstractQuotesProvider(QObject *_parent)
: QObject(_parent){};
~AbstractQuotesProvider() override = default;
virtual void initUrl(const QString &_asset) = 0;
[[nodiscard]] virtual QVariantHash parse(const QByteArray &_source, const QVariantHash &_oldValues) const = 0;
[[nodiscard]] QString tag(const QString &_type) const
{
return dynamic_cast<AbstractExtItem *>(parent())->tag(_type);
};
[[nodiscard]] virtual QUrl url() const = 0;
};
#endif /* ABSTRACTQUOTESPROVIDER_H */

View File

@ -21,26 +21,24 @@
#include <QObject> #include <QObject>
#include <QUrl> #include <QUrl>
#include "abstractextitem.h"
class AbstractWeatherProvider : public QObject class AbstractWeatherProvider : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(int number READ number)
public: public:
explicit AbstractWeatherProvider(QObject *parent, const int number) explicit AbstractWeatherProvider(QObject *_parent)
: QObject(parent) : QObject(_parent){};
, m_number(number){}; ~AbstractWeatherProvider() override = default;
virtual ~AbstractWeatherProvider(){}; virtual void initUrl(const QString &_city, const QString &_country, int _ts) = 0;
virtual void initUrl(const QString city, const QString country, [[nodiscard]] virtual QVariantHash parse(const QVariantMap &_json) const = 0;
const int ts) [[nodiscard]] QString tag(const QString &_type) const
= 0; {
virtual QVariantHash parse(const QVariantMap &json) const = 0; return dynamic_cast<AbstractExtItem *>(parent())->tag(_type);
virtual QUrl url() const = 0; };
int number() const { return m_number; }; [[nodiscard]] virtual QUrl url() const = 0;
private:
int m_number;
}; };

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