Compare commits

..

13 Commits

Author SHA1 Message Date
53918f4528 Merge pull request #100 from arcan1s/development
Release 3.2
2016-07-10 01:09:49 +04:00
77675a8e2f Merge pull request #99 from arcan1s/development
Master update
2016-07-08 15:11:07 +04:00
e4e8f299c0 Merge pull request #98 from arcan1s/development
add last sources test for playersource
2016-06-18 06:09:06 +04:00
1465657648 Merge pull request #97 from arcan1s/development
Master update
2016-06-17 16:22:07 +04:00
082efcc127 Merge pull request #93 from arcan1s/development
Release master update
2016-05-09 01:13:10 +04:00
24d45c6d48 Merge pull request #92 from arcan1s/development
Prerelease master update
2016-04-29 14:02:33 +04:00
7eb82c8c8d Merge pull request #90 from arcan1s/development
Master update
2016-04-21 17:46:47 +04:00
48e98239d9 Merge pull request #89 from arcan1s/development
Devel branch backports
2016-04-10 01:23:39 +04:00
2514dcc74d Merge pull request #88 from arcan1s/development
release 3.1.1
2016-04-06 14:51:48 +03:00
4a499a6157 Merge pull request #86 from arcan1s/development
master release update
2016-04-06 01:40:25 +03:00
6916c8f992 Merge pull request #79 from wlemuel/master
update zh translations
2016-03-02 20:07:23 +03:00
2c7b072829 update zh translations 2016-02-14 13:51:10 +08:00
636978b442 Merge pull request #78 from arcan1s/development
One more master update
2016-01-31 23:37:50 +06:00
487 changed files with 18280 additions and 31849 deletions

View File

@ -1,43 +0,0 @@
name: build & tests
on:
push:
branches:
- master
pull_request:
branches:
- 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 -Syu --noconfirm base-devel cmake extra-cmake-modules python util-linux-libs xorg-server-xvfb
- name: install dependencies
run: pacman -S --noconfirm plasma-workspace
- name: configure cmake
run: cmake -B build -S sources -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_FUTURE=ON -DBUILD_TESTING=ON
- name: build
working-directory: /repo/build
run: make
- name: test
working-directory: /repo/build
run: xvfb-run -a make test

View File

@ -1,51 +0,0 @@
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,4 +47,3 @@ pkg
# clion settings # clion settings
.idea .idea
cmake-build*

3
.gitmodules vendored Normal file
View File

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

20
.travis.yml.bckp Normal file
View File

@ -0,0 +1,20 @@
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,5 +11,3 @@ 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,67 +1,3 @@
Ver.4.0.1:
- temporary disable tooltip painting in main widget
Ver.4.0.0:
* migration to plasma 6
* dialog windows have been replaced by notifications
+ $gpuN keys have been added
+ new key $ssid
- $cuptime key has been removed in favour of $uptime
- $gputemp key has been replaced by $gpuN
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:
+ add X-AW-Translate option to DateTime formatter
+ add formatters to configuration export and import
+ add macro fuction to selector
+ add default formatters
- add translation reinit (fix #102)
- fix invalid float formatter saving
- fix missing ApiVersion for formatters
* use sockets for MPD data
* translation update
Ver.3.2.0: Ver.3.2.0:
+ custom formatters (#91) + custom formatters (#91)
+ add backend tests (#95) + add backend tests (#95)

View File

@ -6,20 +6,27 @@ for more details. To avoid manual labor there is automatic cmake target named
`clangformat` (see below). Some additional detail see below. `clangformat` (see below). Some additional detail see below.
* Indent is only spaces. 4 spaces. * Indent is only spaces. 4 spaces.
* Any private variable should start with `m_` prefix (`m_foo`). The only one exception is `Ui` object which should be named as `ui`. * It is highly recommended to name private variables with `m_` prefix (`m_foo`).
There is no exceptions for properties.
* Avoid to create a large methods. Exception: if method contains lambda functions. * Avoid to create a large methods. Exception: if method contains lambda functions.
* If some method is called only once, it is recommended to use lambda functions.
Exception is `Q_INVOKABLE` methods.
* STL containers are not recommended, use Qt ones instead. * STL containers are not recommended, use Qt ones instead.
* In other hand Qt specific variables types (`qint`, `qfloat`, etc) are not recommended. * In other hand Qt specific variables types (`qint`, `qfloat`, etc) are not
recommended.
* Do not repeat yourself ([DRY](https://en.wikipedia.org/wiki/Don't_repeat_yourself)). * Do not repeat yourself ([DRY](https://en.wikipedia.org/wiki/Don't_repeat_yourself)).
* Headers declaration: * Headers declaration:
* Include only those headers which are strictly necessary inside headers. Use forward class declaration instead. Exception is base class header declaration. * Include only those headers which are strictly necessary inside headers. Use
* In a`*.cpp` file header declaration should have the following order separated by a new line in the alphabet order: forward class declaration instead. Exception is base class header declaration.
* In a`*.cpp` file header declaration should have the following order separated
by a new line in the alphabet order:
1. Class header. 1. Class header.
2. KDE specific headers. 2. KDE specific headers.
3. Qt specific headers. 3. Qt specific headers.
4. Third party headers. 4. Third party headers.
5. Project headers. 5. Project headers.
* Any header should have `#pragma once`. * Any header should have [include guard](https://en.wikipedia.org/wiki/Include_guard)
named as `CLASSNAMECAPS_H`
* If any `#if` directive is used condition should be mentioned in `#endif`: * If any `#if` directive is used condition should be mentioned in `#endif`:
``` ```
@ -29,60 +36,92 @@ 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 `Q_FOREACH` (`foreach`) is not allowed use `for (auto &foo : bar)` instead. * Qt macros (e.g. `signals`, `slots`, `Q_OBJECT`, etc) are allowed. In other hand
* Current project standard is **C++23**. `Q_FOREACH` (`foreach`) is not allowed use `for (auto foo : bar)` instead.
* Current project standard is **C++11**.
* Do not use C-like code: * Do not use C-like code:
* 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. * C-like style iteration if possible. Use `for (auto foo : bar)` and
* C-like casts, use `const_cast`, `static_cast`, `dymanic_Cast` instead. Using of `reinterpret_cast` is not recommended. It is highly recommended to use `dynamic_cast` with the exception catching. It is also possible to use `qvariant_cast` if required. `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
of `reinterpret_cast` is not recommended. It is highly recommended to use
`dynamic_cast` with the exception catching. It is also possible to use
`qvariant_cast` if required. Exception is class constructors, e.g.:
```
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.
* C-like constant definition, use `static const vartype foo = bar` definition instead. * It is highly recommended to avoid implicit casts. Exception `nullptr` casts to
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 inside header not source code file. * Templates are allowed and recommended. Templates usually should be described
* Hardcode is not recommended. But it is possible to use cmake variables to configure some items during build time. inside header not source code file.
* Hardcode is not recommended. But it is possible to use cmake variables to
configure some items during build time.
* Build should not require any additional system variable declaration/changing. * Build should not require any additional system variable declaration/changing.
* Any line should not end with space. * Any line should not end with space.
* Do not hesitate move public methods to private one if possible. * Do not hesitate move public methods to private one if possible.
* Do not hesitate use `const` modifier. In other hand `volatile` modifier is not recommended. * Do not hesitate use `const` modifier. In other hand `volatile` modifier is not
recommended.
* New lines rules: * New lines rules:
* One line after license header. * One line after license header.
* One line between header group declaration (see above). * One line between header group declaration (see above).
* Two lines after header declaration and before declaration at the end of a file. * Two lines after header declaration and before declaration at the end of a
file.
* One line after class and types forward declarations in headers. * One line after class and types forward declarations in headers.
* One line before each method modifiers (`public`, `public slots`, etc). * One line before each method modifiers (`public`, `public slots`, etc).
* Two lines between methods inside source code (`*.cpp`). * Two lines between methods inside source code (`*.cpp`).
* One line after `qCDebug()` information (see below). * One line after `qCDebug()` information (see below).
* One line inside a method to improve code reading. * One line inside a method to improve code reading.
* Each destructor should be virtual. * Each destructor should be virtual.
* Class constructor should have default arguments. Use `QObject *_parent` property for QObject based classes. * Class constructor should have default arguments. Use `QObject *parent` property
for QObject based classes.
* QObject based classes constructors should have explicit modifier. * QObject based classes constructors should have explicit modifier.
* Create one file (source and header) per class. * Create one file (source and header) per class.
* `else if` construction is allowed and recommended. * `else if` construction is allowed and recommended.
* '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 assigned to `nullptr` after deletion and before initialization. Exception: if object is deleted into class destructor. * Any global pointer should be assign to `nullptr` after deletion and before
* Do not use semicolon in qml files unless it is required. initialization. Exception: if object is deleted into class destructor.
* Any method argument including class constructors should start with `_`.
Comments Comments
-------- --------
Please do not hesitate to use comments inside source code (especially in non-obvious blocks). Comments also may use the following keywords: Please do not hesitate to use comments inside source code (especially in non-obvious
blocks). Comments also may use the following keywords:
* **TODO** - indicates that some new code should be implemented here later. Please note that usually these methods should be implemented before the next release. * **TODO** - indicates that some new code should be implemented here later. Please
note that usually these methods should be implemented before the next release.
* **FIXME** - some dirty hacks and/or methods which should be done better. * **FIXME** - some dirty hacks and/or methods which should be done better.
* **HACK** - hacks inside code which requires to avoid some restrictions and/or which adds additional non-obvious optimizations. * **HACK** - hacks inside code which requires to avoid some restrictions and/or
which adds additional non-obvious optimizations.
Do not use dots at the end of the comment line. Do not use dots at the end of the comment line.
Development Development
----------- -----------
* Officially the latest libraries versions should be used. In addition, it is possible to add workarounds for all versions (usually by using preprocessor directives); in this case patches should be placed to `packages` directory. * Officially the latest libraries versions should be used. In addition it is
possible to add workarounds for all versions (usually by using preprocessor
directives); in this case patches should be placed to `packages` directory.
* Build should not contain any warning. * Build should not contain any warning.
* Try to minimize message in Release build with logging disabled. It is highly recommended to fix KDE/Qt specific warning if possible * Try to minimize message in Release build with logging disabled. It is highly
* Do not use dependency to KDE libraries if there are no any strictly necessary. Exceptions are KNotification and KI18n libraries. recommended to fix KDE/Qt specific warning if possible
* Do not use dependency to KDE libraries if there are no any strictly necessary.
Exceptions are KNotification and KI18n libraries.
* It is highly recommended to use submodules for third party libraries if possible. * It is highly recommended to use submodules for third party libraries if possible.
* The main branch is **master**. * The main branch is **development**. Changes in this branch may be merged to the
* For experimental features development new branch `feature/foo` creation is allowed and recommended. master one only if it is a 'stable' build.
* For experimental features development new branch `feature-foo` creation is allowed
and recommended.
* Experimental features should be added inside `BUILD_FUTURE` definition: * Experimental features should be added inside `BUILD_FUTURE` definition:
``` ```
@ -91,41 +130,55 @@ Development
#endif /* BUILD_FUTURE */ #endif /* BUILD_FUTURE */
``` ```
* Any project specific build variable should be mentioned inside `version.h` as well. * Any project specific build variable should be mentioned inside `version.h` as
well.
* Recommended compiler is `clang`. * Recommended compiler is `clang`.
HIG HIG
--- ---
The recommended HIG is [KDE one](https://techbase.kde.org/Projects/Usability/HIG). Avoid to paint interfaces inside plugin because QML and C++ parts may have different theming. The recommended HIG is [KDE one](https://techbase.kde.org/Projects/Usability/HIG).
Avoid to paint interfaces inside plugin because QML and C++ parts may have different
theming.
Licensing Licensing
--------- ---------
All files should be licensed under GPLv3, the owner of the license should be the project (i.e. **awesome-widgets**). See **Tools** section for more details. All files should be licensed under GPLv3, the owner of the license should be the
project (i.e. **awesome-widgets**). See **Tools** section for more details.
Logging Logging
------- -------
For logging please use [QLoggingCategory](http://doc.qt.io/qt-5/qloggingcategory.html). Available categories should be declared in `awdebug.*` files. The following log levels should be used: For logging please use [QLoggingCategory](http://doc.qt.io/qt-5/qloggingcategory.html).
Available categories should be declared in `awdebug.*` files. The following log
levels should be used:
* **debug** (`qCDebug()`) - method arguments information. Please note that it is recommended to logging all arguments in the one line. * **debug** (`qCDebug()`) - method arguments information. Please note that it
is recommended to logging all arguments in the one line.
* **info** (`qCInfo()`) - additional information inside methods. * **info** (`qCInfo()`) - additional information inside methods.
* **warning** (`qCWarning()`) - not critical information, which may be caused by mistakes in configuration for example. * **warning** (`qCWarning()`) - not critical information, which may be caused by
* **critical** (`qCCritical()`) - a critical error. After this error program may be terminated. mistakes in configuration for example.
* **critical** (`qCCritical()`) - a critical error. After this error program may
be terminated.
The empty log string (e.g. `qCDebug();`) is not allowed because the method names will be stripped by compiler with `Release` build type. To log class constructor and destructor use `__PRETTY_FUNCTION__` macro. The empty log string (e.g. `qCDebug();`) is not allowed because the method names
will be stripped by compiler with `Release` build type. To log class constructor
and destructor use `__PRETTY_FUNCTION__` macro.
Testing Testing
------- -------
* Any changes should be tested by using `plasmawindowed` and `plasmashell` applications. (It is also possible to use `plasmaengineexplorer` and `plasmoidviewer` in addition.) * Any changes should be tested by using `plasmawindowed` and `plasmashell` applications.
(It is also possible to use `plasmaengineexplorer` and `plasmoidviewer` in addition.)
* Any test should be performed on real (not Virtual Machine) system. * Any test should be performed on real (not Virtual Machine) system.
* Test builds should be: * Test builds should be:
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`.
* Additional test functions should be declated and used only inside `BUILD_TESTING` definition. * It is recommended to create addition test if possible.
* Addition test functions should be declated and used only inside `BUILD_TESTING`
definition.
Tools Tools
----- -----
@ -155,9 +208,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
@ -182,6 +235,7 @@ Tools
// declare with default value // declare with default value
bool m_prop = false; bool m_prop = false;
``` ```
* Use `cppcheck` to avoid common errors in the code. To start application just run `make cppcheck`. * Use `cppcheck` to avoid common errors in the code. To start application just
* Use `clang-format` to apply valid code format. To start application just run `make clangformat`. run `make cppcheck`.
* use `-DCMAKE_CXX_COMPILER=clang++` in order to enable clang-tidy checks. * Use `clang-format` to apply valid code format. To start application just run
`make clangformat`.

View File

@ -1,7 +1,7 @@
awesome-widgets (ex-pytextmonitor) awesome-widgets (ex-pytextmonitor)
================================== ==================================
[![build & tests](https://github.com/arcan1s/awesome-widgets/actions/workflows/build.yml/badge.svg)](https://github.com/arcan1s/awesome-widgets/actions/workflows/build.yml) [![Build Status](https://travis-ci.org/arcan1s/awesome-widgets.svg?branch=development)](https://travis-ci.org/arcan1s/awesome-widgets)
[![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
@ -14,11 +14,11 @@ A collection of minimalistic widgets which looks like Awesome Window Manager wid
Features Features
======== ========
* easy and fully configurable native Plasma widget which may be used as desktop or panel widget * easy and fully configurable native Plasma widget which may be used as Conky widget or as Awesome-like information panel
* additionnal widget which shows active desktop status * panel which shows active desktop status
* clear text configuration with html tags support * clear Conky-like configuration with html tags support
* custom command support (it may be simple action as well as special custom tag) * custom command support (it may be simple action as well as special custom tag)
* graphical widgets support - tooltips, bars * graphical item support - tooltips, bars
See [links](#Links) for more details. See [links](#Links) for more details.
@ -30,13 +30,15 @@ Instruction
Dependencies Dependencies
------------ ------------
* plasma-workspace * plasma-framework
Optional dependencies Optional dependencies
--------------------- ---------------------
* proprietary video driver
* hddtemp
* smartmontools
* music player (mpd or MPRIS supported) * music player (mpd or MPRIS supported)
* wireless_tools
Make dependencies Make dependencies
----------------- -----------------
@ -44,20 +46,17 @@ 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
------------ ------------
* download sources * download sources
* build package * install
cmake -B build -S sources -DCMAKE_BUILD_TYPE=Release mkdir build && cd build
cmake --build build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr ../
make && sudo make install
* install package **NOTE** on Plasma 5 it very likely requires `-DKDE_INSTALL_USE_QT_SYS_PATHS=ON` flag
cmake --install build
Additional information Additional information
====================== ======================
@ -75,5 +74,5 @@ Links
* [Scripts and bars](https://arcanis.me/en/2014/12/19/aw-v21-bells-and-whistles/) * [Scripts and bars](https://arcanis.me/en/2014/12/19/aw-v21-bells-and-whistles/)
* Plasmoid on [kde-look](http://kde-look.org/content/show.php/Awesome+Widgets?content=157124) * Plasmoid on [kde-look](http://kde-look.org/content/show.php/Awesome+Widgets?content=157124)
* DataEngine on [kde-look](http://kde-look.org/content/show.php/Extended+Systemmonitor+DataEngine?content=158773) * DataEngine on [kde-look](http://kde-look.org/content/show.php/Extended+Systemmonitor+DataEngine?content=158773)
* Archlinux [AUR](https://aur.archlinux.org/packages/plasma6-applets-awesome-widgets) package * Archlinux [AUR](https://aur.archlinux.org/packages/plasma5-applet-awesome-widgets/) package
* [OpenSuse](http://software.opensuse.org/search?q=awesome-widgets) packages, [KF5 OpenSuse](http://software.opensuse.org/package/plasma5-awesome-widgets) package * [OpenSuse](http://software.opensuse.org/search?q=awesome-widgets) packages, [KF5 OpenSuse](http://software.opensuse.org/package/plasma5-awesome-widgets) package

View File

@ -1,7 +1,13 @@
#!/bin/bash #!/bin/bash
SRCDIR="sources" SRCDIR="sources"
VERSION="$(git describe --tags --abbrev=0)" MAJOR=$(grep -m1 PROJECT_VERSION_MAJOR sources/CMakeLists.txt | awk '{print $2}' | sed 's/^.\(.*\)..$/\1/')
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"
@ -10,11 +16,17 @@ 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}" tar cJf "${ARCHIVE}-${VERSION}-src.tar.xz" "${ARCHIVE}"
ln -sf "../${ARCHIVE}-${VERSION}-src.tar.xz" packages
rm -rf "${ARCHIVE}" rm -rf "${ARCHIVE}"
# update md5sum
MD5SUMS=$(md5sum ${ARCHIVE}-${VERSION}-src.tar.xz | awk '{print $1}')
sed -i "/md5sums=('[0-9A-Fa-f]*/s/[^'][^)]*/md5sums=('${MD5SUMS}'/" packages/PKGBUILD
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,31 +1,41 @@
# Maintainer: Evgeniy Alekseev <arcanis at archlinux dot org> # Maintainer: Evgeniy Alekseev <arcanis at archlinux dot org>
pkgname=plasma6-applet-awesome-widgets pkgname=plasma5-applet-awesome-widgets
_pkgname=awesome-widgets _pkgname=awesome-widgets
pkgver=4.0.0alpha2 pkgver=3.2.0
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=('x86_64') arch=('i686' 'x86_64')
url="https://arcanis.me/projects/awesome-widgets" url="https://arcanis.me/projects/awesome-widgets"
license=('GPL3') license=('GPL3')
depends=('plasma-workspace') depends=('plasma-framework')
optdepends=("mpd: for music player monitor" optdepends=("catalyst: for GPU monitor"
"wireless_tools: wifi information") "hddtemp: for HDD temperature monitor"
"smartmontools: for HDD temperature monitor"
"mpd: for music player 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/${pkgver}/${_pkgname}-${pkgver}-src.tar.xz) source=(https://github.com/arcan1s/awesome-widgets/releases/download/V.${pkgver}/${_pkgname}-${pkgver}-src.tar.xz)
install="$pkgname.install" install=${pkgname}.install
md5sums=('81a85890d519bd8c5791d0d99cffc9c1')
backup=('etc/xdg/plasma-dataengine-extsysmon.conf') backup=('etc/xdg/plasma-dataengine-extsysmon.conf')
prepare() {
rm -rf "${srcdir}/build"
mkdir "${srcdir}/build"
}
build () { build () {
cmake -B build -S "${_pkgname}" \ cd "${srcdir}/build"
cmake -DKDE_INSTALL_USE_QT_SYS_PATHS=ON \
-DCMAKE_BUILD_TYPE=Optimization \ -DCMAKE_BUILD_TYPE=Optimization \
-DCMAKE_INSTALL_PREFIX=/usr \
-DBUILD_FUTURE=ON \ -DBUILD_FUTURE=ON \
-DBUILD_TESTING=OFF "../${_pkgname}"
cmake --build build make
} }
package() { package() {
DESTDIR="$pkgdir" cmake --install build cd "${srcdir}/build"
make DESTDIR="${pkgdir}" install
} }
sha256sums=('b2a7b07a1df6f710f4e0d6e5898933f4ddb131818b922dc4b8e48afe3e98a664')

View File

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

View File

View File

@ -0,0 +1,402 @@
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

@ -0,0 +1,31 @@
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

@ -0,0 +1,148 @@
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}

View File

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

View File

@ -0,0 +1,26 @@
[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

@ -0,0 +1,23 @@
[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

1
sources/3rdparty/fontdialog vendored Submodule

View File

@ -1,165 +0,0 @@
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.

View File

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

View File

@ -1,140 +0,0 @@
/***************************************************************************
* 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, &QComboBox::currentTextChanged, this, &CFontDialog::updateColor);
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, &QDialogButtonBox::accepted, this, &CFontDialog::accept);
QObject::connect(buttons, &QDialogButtonBox::rejected, this, &CFontDialog::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

@ -1,73 +0,0 @@
/***************************************************************************
* 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. *
***************************************************************************/
#pragma once
#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;
};

View File

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

View File

@ -1,25 +1,21 @@
cmake_minimum_required(VERSION 3.16.0) cmake_minimum_required(VERSION 2.8.12)
# 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 NEW) cmake_policy(SET CMP0063 OLD)
endif ()
if (POLICY CMP0071)
cmake_policy(SET CMP0071 NEW)
endif ()
if (POLICY CMP0160)
cmake_policy(SET CMP0160 OLD)
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 "4") set(PROJECT_VERSION_MAJOR "3")
set(PROJECT_VERSION_MINOR "0") set(PROJECT_VERSION_MINOR "2")
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 "")
@ -45,28 +41,44 @@ 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)
# directories # flags
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

@ -15,111 +15,79 @@
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ * * along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/ ***************************************************************************/
#ifndef NDEBUG
#define NDEBUG
#endif /* NDEBUG */
#include <KI18n/KLocalizedString>
#include "awdebug.h" #include "awdebug.h"
Q_LOGGING_CATEGORY(LOG_AW, "org.kde.plasma.awesomewidget", QtMsgType::QtWarningMsg) Q_LOGGING_CATEGORY(LOG_AW, "org.kde.plasma.awesomewidget",
Q_LOGGING_CATEGORY(LOG_DBUS, "org.kde.plasma.awdbus", QtMsgType::QtWarningMsg) QtMsgType::QtWarningMsg)
Q_LOGGING_CATEGORY(LOG_DP, "org.kde.plasma.desktoppanel", 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_ESM, "org.kde.plasma.extsysmon", QtMsgType::QtWarningMsg)
Q_LOGGING_CATEGORY(LOG_ESS, "org.kde.plasma.extsysmonsources", QtMsgType::QtWarningMsg) Q_LOGGING_CATEGORY(LOG_ESS, "org.kde.plasma.extsysmonsources",
Q_LOGGING_CATEGORY(LOG_LIB, "org.kde.plasma.awesomewidgets", QtMsgType::QtWarningMsg) QtMsgType::QtWarningMsg)
Q_LOGGING_CATEGORY(LOG_LIB, "org.kde.plasma.awesomewidgets",
QtMsgType::QtWarningMsg)
QString AWDebug::getAboutText(const QString &_type) const QStringList getBuildData()
{
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, i18n("Homepage"))
+ QString("<li><a href=\"%1\">%2</a></li>").arg(REPOSITORY, i18n("Repository"))
+ QString("<li><a href=\"%1\">%2</a></li>").arg(BUGTRACKER, i18n("Bugtracker"))
+ QString("<li><a href=\"%1\">%2</a></li>").arg(TRANSLATION, i18n("Translation issue"))
+ QString("<li><a href=\"%1\">%2</a></li>").arg(AUR_PACKAGES, i18n("AUR packages"))
+ QString("<li><a href=\"%1\">%2</a></li>").arg(OPENSUSE_PACKAGES, i18n("openSUSE packages")) + "</ul>";
} else if (_type == "copy") {
text = QString("<small>&copy; %1 <a href=\"mailto:%2\">%3</a><br>").arg(DATE, EMAIL, AUTHOR)
+ i18n("This software is licensed under %1", LICENSE) + "</small>";
} else if (_type == "translators") {
auto 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") {
auto trdPartyList = QString(TRDPARTY_LICENSE).split(';', Qt::SkipEmptyParts);
for (auto i = 0; i < trdPartyList.count(); ++i)
trdPartyList[i] = QString("<li><a href=\"%3\">%1</a> (%2 license)</li>")
.arg(trdPartyList.at(i).split(',')[0], trdPartyList.at(i).split(',')[1],
trdPartyList.at(i).split(',')[2]);
text = i18n("This software uses:") + "<ul>" + trdPartyList.join("") + "</ul>";
} else if (_type == "thanks") {
auto thanks = QString(SPECIAL_THANKS).split(';', Qt::SkipEmptyParts);
for (auto i = 0; i < thanks.count(); ++i)
thanks[i]
= QString("<li><a href=\"%2\">%1</a></li>").arg(thanks.at(i).split(',')[0], 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("=== Awesome Widgets configuration details ==="); metadata.append(QString("=== Awesome Widgets configuration details ==="));
// build information // build information
metadata.append("Build details:"); metadata.append(QString("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("API details:"); metadata.append(QString("API details:"));
metadata.append(QString(" AW_GRAPHITEM_API: %1").arg(AW_GRAPHITEM_API)); metadata.append(QString(" AWGIAPI: %1").arg(AWGIAPI));
metadata.append(QString(" AW_EXTQUOTES_API: %1").arg(AW_EXTQUOTES_API)); metadata.append(QString(" AWEQAPI: %1").arg(AWEQAPI));
metadata.append(QString(" AW_EXTSCRIPT_API: %1").arg(AW_EXTSCRIPT_API)); metadata.append(QString(" AWESAPI: %1").arg(AWESAPI));
metadata.append(QString(" AW_EXTUPGRADE_API: %1").arg(AW_EXTUPGRADE_API)); metadata.append(QString(" AWEUAPI: %1").arg(AWEUAPI));
metadata.append(QString(" AW_EXTWEATHER_API: %1").arg(AW_EXTWEATHER_API)); metadata.append(QString(" AWEWAPI: %1").arg(AWEWAPI));
metadata.append(QString(" AW_FORMATTER_API: %1").arg(AW_FORMATTER_API)); metadata.append(QString(" AWEFAPI: %1").arg(AWEFAPI));
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("cmake properties:"); metadata.append(QString("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(QString(" CMAKE_CXX_COMPILER: %1").arg(CMAKE_CXX_COMPILER)); metadata.append(
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(QString(" CMAKE_CXX_FLAGS_DEBUG: %1").arg(CMAKE_CXX_FLAGS_DEBUG)); metadata.append(
metadata.append(QString(" CMAKE_CXX_FLAGS_RELEASE: %1").arg(CMAKE_CXX_FLAGS_RELEASE)); QString(" CMAKE_CXX_FLAGS_DEBUG: %1").arg(CMAKE_CXX_FLAGS_DEBUG));
metadata.append(QString(" CMAKE_CXX_FLAGS_OPTIMIZATION: %1").arg(CMAKE_CXX_FLAGS_OPTIMIZATION)); metadata.append(QString(" CMAKE_CXX_FLAGS_RELEASE: %1")
metadata.append(QString(" CMAKE_DEFINITIONS: %1").arg(CMAKE_DEFINITIONS)); .arg(CMAKE_CXX_FLAGS_RELEASE));
metadata.append(QString(" CMAKE_INSTALL_PREFIX: %1").arg(CMAKE_INSTALL_PREFIX)); metadata.append(QString(" CMAKE_CXX_FLAGS_OPTIMIZATION: %1")
metadata.append(QString(" CMAKE_MODULE_LINKER_FLAGS: %1").arg(CMAKE_MODULE_LINKER_FLAGS)); .arg(CMAKE_CXX_FLAGS_OPTIMIZATION));
metadata.append(QString(" CMAKE_SHARED_LINKER_FLAGS: %1").arg(CMAKE_SHARED_LINKER_FLAGS)); metadata.append(
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("Components data:"); metadata.append(QString("Components data:"));
metadata.append(QString(" BUILD_PLASMOIDS: %1").arg(BUILD_PLASMOIDS)); metadata.append(QString(" BUILD_PLASMOIDS: %1").arg(BUILD_PLASMOIDS));
metadata.append(QString(" BUILD_DEB_PACKAGE: %1").arg(BUILD_DEB_PACKAGE)); metadata.append(
metadata.append(QString(" BUILD_RPM_PACKAGE: %1").arg(BUILD_RPM_PACKAGE)); QString(" BUILD_DEB_PACKAGE: %1").arg(BUILD_DEB_PACKAGE));
metadata.append(QString(" CLANGFORMAT_EXECUTABLE: %1").arg(CLANGFORMAT_EXECUTABLE)); metadata.append(
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(QString(" COVERITY_DIRECTORY: %1").arg(COVERITY_DIRECTORY)); metadata.append(
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(QString(" COVERITY_EXECUTABLE: %1").arg(COVERITY_EXECUTABLE)); metadata.append(
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(QString(" CPPCHECK_EXECUTABLE: %1").arg(CPPCHECK_EXECUTABLE)); metadata.append(
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

@ -15,28 +15,29 @@
* 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 AWDEBUG_H
#define AWDEBUG_H
#include <QLoggingCategory> #include <QLoggingCategory>
#include "version.h" #include "version.h"
namespace AWDebug #ifndef LOG_FORMAT
{ #define LOG_FORMAT \
const char LOG_FORMAT[] = "[%{time " "[%{time process}][%{if-debug}DD%{endif}%{if-info}II%{endif}%{if-" \
"process}][%{if-debug}DD%{endif}%{if-info}II%{endif}%" "warning}WW%{endif}%{if-critical}CC%{endif}%{if-fatal}FF%{endif}][%{" \
"{if-warning}WW%{endif}%{if-critical}CC%{endif}%{if-" "category}][%{function}] %{message}"
"fatal}FF%{endif}][%{category}][%{function}] " #endif /* LOG_FORMAT */
"%{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 */

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.json ${CMAKE_CURRENT_SOURCE_DIR}/package/metadata.json) configure_file(metadata.desktop ${CMAKE_CURRENT_SOURCE_DIR}/package/metadata.desktop)
add_subdirectory(plugin) add_subdirectory(plugin)
plasma_install_package(package org.kde.plasma.awesomewidget) plasma_install_package(package org.kde.plasma.awesomewidget)

View File

@ -0,0 +1,28 @@
[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

@ -1,26 +0,0 @@
{
"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.15 import QtQuick 2.0
import org.kde.plasma.configuration 2.0 import org.kde.plasma.configuration 2.0
@ -51,12 +51,6 @@ ConfigModel {
source: "dataengine.qml" source: "dataengine.qml"
} }
ConfigCategory {
name: i18n("Report bug")
icon: "tools-report-bug"
source: "bug.qml"
}
ConfigCategory { ConfigCategory {
name: i18n("About") name: i18n("About")
icon: "help-about" icon: "help-about"

View File

@ -7,143 +7,137 @@
<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="tempUnits" type="String"> <entry name="queueLimit" type="int">
<default>0</default>
</entry>
<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="historyCount" type="Int">
<default>100</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,22 +15,114 @@
* 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.15 import QtQuick 2.0
import org.kde.kcmutils as KCM import QtQuick.Controls 1.3 as QtControls
import QtQuick.Layouts 1.0 as QtLayouts
import org.kde.plasma.awesomewidgets import org.kde.plasma.private.awesomewidget 1.0
import org.kde.plasma.private.awesomewidget
KCM.SimpleKCM { Item {
id: aboutPage id: aboutPage
// backend
AWActions { AWActions {
id: awActions id: awActions
} }
AboutTab { width: childrenRect.width
textProvider: awActions height: childrenRect.height
implicitWidth: pageColumn.implicitWidth
implicitHeight: pageColumn.implicitHeight
property bool debug: awActions.isDebugEnabled()
Column {
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: {
if (debug) console.debug()
} }
} }

View File

@ -15,22 +15,30 @@
* 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.15 import QtQuick 2.0
import QtQuick.Controls import QtQuick.Controls 1.3 as QtControls
import org.kde.kcmutils as KCM import QtQuick.Dialogs 1.2 as QtDialogs
import org.kde.plasma.awesomewidgets import org.kde.plasma.private.awesomewidget 1.0
import org.kde.plasma.private.awesomewidget
KCM.SimpleKCM { Item {
id: advancedPage id: advancedPage
// backend // backend
AWActions {
id: awActions
}
AWConfigHelper { AWConfigHelper {
id: awConfig id: awConfig
} }
width: childrenRect.width
height: childrenRect.height
implicitWidth: pageColumn.implicitWidth
implicitHeight: pageColumn.implicitHeight
property bool debug: awActions.isDebugEnabled()
property alias cfg_background: background.checked property alias cfg_background: background.checked
property alias cfg_translateStrings: translate.checked property alias cfg_translateStrings: translate.checked
property alias cfg_wrapNewLines: wrapNewLines.checked property alias cfg_wrapNewLines: wrapNewLines.checked
@ -41,194 +49,428 @@ KCM.SimpleKCM {
property alias cfg_height: widgetHeight.value property alias cfg_height: widgetHeight.value
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 string cfg_tempUnits: tempUnits.value property alias cfg_queueLimit: queueLimit.value
property alias cfg_customTime: customTime.value property string cfg_tempUnits: tempUnits.currentText
property alias cfg_customUptime: customUptime.value property alias cfg_customTime: customTime.text
property alias cfg_acOnline: acOnline.value property alias cfg_customUptime: customUptime.text
property alias cfg_acOffline: acOffline.value property alias cfg_acOnline: acOnline.text
property alias cfg_historyCount: historyCount.value property alias cfg_acOffline: acOffline.text
Column { Column {
id: pageColumn
anchors.fill: parent anchors.fill: parent
Row {
CheckBoxSelector { height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.heigth
width: parent.width * 2 / 5
}
QtControls.CheckBox {
id: background id: background
width: parent.width * 3 / 5
text: i18n("Enable background") text: i18n("Enable background")
} }
}
CheckBoxSelector { Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.heigth
width: parent.width * 2 / 5
}
QtControls.CheckBox {
id: translate id: translate
width: parent.width * 3 / 5
text: i18n("Translate strings") text: i18n("Translate strings")
} }
}
CheckBoxSelector { Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.heigth
width: parent.width * 2 / 5
}
QtControls.CheckBox {
id: wrapNewLines id: wrapNewLines
width: parent.width * 3 / 5
text: i18n("Wrap new lines") text: i18n("Wrap new lines")
} }
}
CheckBoxSelector { Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.heigth
width: parent.width * 2 / 5
}
QtControls.CheckBox {
id: wordWrap id: wordWrap
width: parent.width * 3 / 5
text: i18n("Enable word wrap") text: i18n("Enable word wrap")
} }
}
CheckBoxSelector { Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.heigth
width: parent.width * 2 / 5
}
QtControls.CheckBox {
id: notify id: notify
width: parent.width * 3 / 5
text: i18n("Enable notifications") text: i18n("Enable notifications")
} }
}
CheckBoxSelector { Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.heigth
width: parent.width * 2 / 5
}
QtControls.CheckBox {
id: updates id: updates
width: parent.width * 3 / 5
text: i18n("Check updates on startup") text: i18n("Check updates on startup")
} }
}
CheckBoxSelector { Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.heigth
width: parent.width * 2 / 5
}
QtControls.CheckBox {
id: optimize id: optimize
width: parent.width * 3 / 5
text: i18n("Optimize subscription") text: i18n("Optimize subscription")
} }
}
IntegerSelector { Row {
id: widgetHeight height: implicitHeight
maximumValue: 4096 width: parent.width
minimumValue: 0 QtControls.Label {
stepSize: 50 height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Widget height, px") text: i18n("Widget height, px")
}
QtControls.SpinBox {
id: widgetHeight
width: parent.width * 3 / 5
minimumValue: 0
maximumValue: 4096
stepSize: 50
value: plasmoid.configuration.height value: plasmoid.configuration.height
} }
}
IntegerSelector { Row {
id: widgetWidth height: implicitHeight
maximumValue: 4096 width: parent.width
minimumValue: 0 QtControls.Label {
stepSize: 50 height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Widget width, px") text: i18n("Widget width, px")
}
QtControls.SpinBox {
id: widgetWidth
width: parent.width * 3 / 5
minimumValue: 0
maximumValue: 4096
stepSize: 50
value: plasmoid.configuration.width value: plasmoid.configuration.width
} }
}
IntegerSelector { Row {
id: update height: implicitHeight
maximumValue: 10000 width: parent.width
minimumValue: 1000 QtControls.Label {
stepSize: 500 height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Time interval") text: i18n("Time interval")
}
QtControls.SpinBox {
id: update
width: parent.width * 3 / 5
minimumValue: 1000
maximumValue: 10000
stepSize: 500
value: plasmoid.configuration.interval value: plasmoid.configuration.interval
} }
}
ComboBoxSelector { Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
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 {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Temperature units")
}
QtControls.ComboBox {
id: tempUnits id: tempUnits
width: parent.width * 3 / 5
textRole: "label"
model: [ model: [
{ {
"label": i18n("Celsius"), 'label': i18n("Celsius"),
"name": "Celsius" 'name': "Celsius"
}, },
{ {
"label": i18n("Fahrenheit"), 'label': i18n("Fahrenheit"),
"name": "Fahrenheit" 'name': "Fahrenheit"
}, },
{ {
"label": i18n("Kelvin"), 'label': i18n("Kelvin"),
"name": "Kelvin" 'name': "Kelvin"
}, },
{ {
"label": i18n("Reaumur"), 'label': i18n("Reaumur"),
"name": "Reaumur" 'name': "Reaumur"
}, },
{ {
"label": i18n("cm^-1"), 'label': i18n("cm^-1"),
"name": "cm^-1" 'name': "cm^-1"
}, },
{ {
"label": i18n("kJ/mol"), 'label': i18n("kJ/mol"),
"name": "kJ/mol" 'name': "kJ/mol"
}, },
{ {
"label": i18n("kcal/mol"), 'label': i18n("kcal/mol"),
"name": "kcal/mol" 'name': "kcal/mol"
} }
] ]
text: i18n("Temperature units") onCurrentIndexChanged: cfg_tempUnits = model[currentIndex]["name"]
value: plasmoid.configuration.tempUnits Component.onCompleted: {
onValueEdited: newValue => cfg_tempUnits = newValue if (debug) console.debug()
for (var i = 0; i < model.length; i++) {
if (model[i]["name"] == plasmoid.configuration.tempUnits) {
if (debug) console.info("Found", model[i]["name"], "on", i)
tempUnits.currentIndex = i;
}
}
}
}
} }
LineSelector { Row {
id: customTime height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Custom time format") text: i18n("Custom time format")
value: plasmoid.configuration.customTime }
QtControls.TextField {
id: customTime
width: parent.width * 3 / 5
text: plasmoid.configuration.customTime
}
} }
LineSelector { Row {
id: customUptime height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Custom uptime format") text: i18n("Custom uptime format")
value: plasmoid.configuration.customUptime }
QtControls.TextField {
id: customUptime
width: parent.width * 3 / 5
text: plasmoid.configuration.customUptime
}
} }
LineSelector { Row {
id: acOnline 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") text: i18n("AC online tag")
value: plasmoid.configuration.acOnline }
QtControls.TextField {
id: acOnline
width: parent.width * 3 / 5
text: plasmoid.configuration.acOnline
}
} }
LineSelector { Row {
id: acOffline 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") text: i18n("AC offline tag")
value: plasmoid.configuration.acOffline }
QtControls.TextField {
id: acOffline
width: parent.width * 3 / 5
text: plasmoid.configuration.acOffline
}
} }
GroupBox { Row {
width: parent.width
height: implicitHeight
title: i18n("Actions")
Column {
height: implicitHeight height: implicitHeight
width: parent.width width: parent.width
QtControls.Label {
ButtonSelector { height: parent.height
value: i18n("Drop key cache") width: parent.width * 2 / 5
onButtonActivated: awConfig.dropCache() }
QtControls.Button {
width: parent.width * 3 / 5
text: i18n("Drop key cache")
onClicked: awActions.dropCache()
}
} }
ButtonSelector { Row {
ExportDialog { 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 id: saveConfigAs
configuration: plasmoid.configuration selectExisting: false
} title: i18n("Export")
value: i18n("Export configuration") folder: awConfig.configurationDirectory()
onButtonActivated: saveConfigAs.open() onAccepted: {
} var status = awConfig.exportConfiguration(
plasmoid.configuration,
ButtonSelector { saveConfigAs.fileUrl.toString().replace("file://", ""))
ImportDialog { if (status) {
id: loadConfigFrom messageDialog.title = i18n("Success")
onConfigurationReceived: { messageDialog.text = i18n("Please note that binary files were not copied")
for (const key in configuration) } else {
plasmoid.configuration[key] = configuration[key] messageDialog.title = i18n("Ooops...")
} messageDialog.text = i18n("Could not save configuration file")
}
value: i18n("Import configuration")
onButtonActivated: loadConfigFrom.open()
} }
messageDialog.open()
} }
} }
GroupBox { QtDialogs.MessageDialog {
id: messageDialog
standardButtons: QtDialogs.StandardButton.Ok
}
}
Row {
height: implicitHeight height: implicitHeight
width: parent.width width: parent.width
title: i18n("History") 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 { Column {
height: implicitHeight QtControls.CheckBox {
width: parent.width id: importPlasmoid
text: i18n("Import plasmoid settings")
}
IntegerSelector { QtControls.CheckBox {
id: historyCount id: importExtensions
maximumValue: 10000 text: i18n("Import extensions")
minimumValue: 0 }
stepSize: 50
text: i18n("History count") QtControls.CheckBox {
value: plasmoid.configuration.historyCount id: importAdds
text: i18n("Import additional files")
}
}
onAccepted: {
if (debug) console.debug()
var importConfig = awConfig.importConfiguration(
openConfig.fileUrl.toString().replace("file://", ""),
importPlasmoid.checked, importExtensions.checked,
importAdds.checked)
for (var key in importConfig)
plasmoid.configuration[key] = importConfig[key]
} }
} }
} }
} }
Component.onCompleted: {
if (debug) console.debug()
}
} }

View File

@ -15,84 +15,229 @@
* 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.15 import QtQuick 2.0
import org.kde.kcmutils as KCM 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.awesomewidgets import org.kde.plasma.private.awesomewidget 1.0
import org.kde.plasma.private.awesomewidget
KCM.SimpleKCM { Item {
id: appearancePage id: appearancePage
// backend
AWActions {
id: awActions
}
width: childrenRect.width
height: childrenRect.height
implicitWidth: pageColumn.implicitWidth
implicitHeight: pageColumn.implicitHeight
property bool debug: awActions.isDebugEnabled()
property variant weight: { property variant weight: {
25: 0, 25: 0,
50: 1, 50: 1,
63: 3, 63: 3,
75: 4, 75: 4,
87: 5, 87: 5
} }
property alias cfg_fontFamily: font.value property alias cfg_fontFamily: selectFont.text
property alias cfg_fontSize: fontSize.value property alias cfg_fontSize: fontSize.value
property string cfg_fontWeight: fontWeight.value property string cfg_fontWeight: fontWeight.currentText
property string cfg_fontStyle: fontStyle.value property string cfg_fontStyle: fontStyle.currentText
property alias cfg_fontColor: selectColor.value property alias cfg_fontColor: selectColor.text
property alias cfg_textStyleColor: selectStyleColor.value
property string cfg_textStyle: textStyle.value
Column { Column {
id: pageColumn
anchors.fill: parent anchors.fill: parent
Row {
FontSelector { height: implicitHeight
id: font width: parent.width
QtControls.Label {
height: parent.height
width: parent.width / 3
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Font") text: i18n("Font")
value: plasmoid.configuration.fontFamily }
QtControls.Button {
id: selectFont
width: parent.width * 2 / 3
text: plasmoid.configuration.fontFamily
onClicked: {
if (debug) console.debug()
fontDialog.setFont()
fontDialog.visible = true
}
}
} }
IntegerSelector { Row {
id: fontSize height: implicitHeight
maximumValue: 32 width: parent.width
minimumValue: 8 QtControls.Label {
stepSize: 1 height: parent.height
width: parent.width / 3
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Font size") text: i18n("Font size")
}
QtControls.SpinBox {
id: fontSize
width: parent.width * 2 / 3
minimumValue: 8
maximumValue: 32
stepSize: 1
value: plasmoid.configuration.fontSize value: plasmoid.configuration.fontSize
} }
}
ComboBoxSelector { Row {
id: fontWeight height: implicitHeight
model: General.fontWeightModel width: parent.width
QtControls.Label {
height: parent.height
width: parent.width / 3
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Font weight") text: i18n("Font weight")
value: plasmoid.configuration.fontWeight }
onValueEdited: newValue => cfg_fontWeight = newValue 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;
}
}
}
}
} }
ComboBoxSelector { Row {
id: fontStyle height: implicitHeight
model: General.fontStyleModel width: parent.width
QtControls.Label {
height: parent.height
width: parent.width / 3
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Font style") text: i18n("Font style")
value: plasmoid.configuration.fontStyle }
onValueEdited: newValue => cfg_fontStyle = newValue 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;
}
}
}
}
} }
ColorSelector { Row {
id: selectColor height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width / 3
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Font color") text: i18n("Font color")
value: plasmoid.configuration.fontColor }
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
}
}
} }
ComboBoxSelector { QtDialogs.ColorDialog {
id: textStyle id: colorDialog
model: General.textStyleModel title: i18n("Select a color")
text: i18n("Style") color: selectColor.text
value: plasmoid.configuration.textStyle onAccepted: selectColor.text = colorDialog.color
onValueEdited: newValue => cfg_textStyle = newValue
} }
ColorSelector { QtDialogs.FontDialog {
id: selectStyleColor id: fontDialog
text: i18n("Style color") title: i18n("Select a font")
value: plasmoid.configuration.textStyleColor 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()
fontDialog.font = Qt.font({
family: selectFont.text,
pointSize: fontSize.value > 0 ? fontSize.value : 12,
italic: fontStyle.currentIndex == 1,
weight: Font.Normal,
})
} }
} }
Component.onCompleted: {
if (debug) console.debug()
}
} }

View File

@ -1,159 +0,0 @@
/***************************************************************************
* 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/ *
***************************************************************************/
import QtQuick 2.15
import QtQuick.Controls
import QtQuick.Dialogs
import QtQuick.Layouts
import org.kde.kcmutils as KCM
import org.kde.plasma.awesomewidgets
import org.kde.plasma.private.awesomewidget
KCM.SimpleKCM {
id: bugPage
AWActions {
id: awActions
}
AWBugReporter {
id: awBugReporter
}
ColumnLayout {
anchors.fill: parent
TextField {
id: title
Layout.fillWidth: true
placeholderText: i18n("Report subject")
}
ColumnLayout {
Layout.fillWidth: true
GroupBox {
Layout.fillWidth: true
title: i18n("Description")
TextArea {
id: description
anchors.fill: parent
textFormat: TextEdit.PlainText
}
}
GroupBox {
Layout.fillWidth: true
title: i18n("Steps to reproduce")
TextArea {
id: reproduce
anchors.fill: parent
textFormat: TextEdit.PlainText
}
}
GroupBox {
Layout.fillWidth: true
title: i18n("Expected result")
TextArea {
id: expected
anchors.fill: parent
textFormat: TextEdit.PlainText
}
}
GroupBox {
Layout.fillWidth: true
Layout.alignment: Qt.AlignBottom
title: i18n("Logs")
ColumnLayout {
anchors.fill: parent
Layout.fillWidth: true
Row {
Layout.fillWidth: true
Label {
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignJustify
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WordWrap
text: i18n("Use command")
}
TextField {
width: parent.width * 3 / 5
readOnly: true
text: "QT_LOGGING_RULES=*=true plasmawindowed org.kde.plasma.awesomewidget"
}
}
Button {
Layout.fillWidth: true
text: i18n("Load log file")
onClicked: logPath.open()
}
TextArea {
id: logBody
Layout.fillWidth: true
Layout.alignment: Qt.AlignBottom
textFormat: TextEdit.PlainText
}
}
FileDialog {
id: logPath
title: i18n("Open log file")
onAccepted: logBody.text = awActions.getFileContent(logPath.selectedFile.toString().replace("file://", ""))
}
}
DialogButtonBox {
Layout.fillWidth: true
standardButtons: DialogButtonBox.Ok | DialogButtonBox.Reset
alignment: Qt.AlignRight
onAccepted: sendBugReport()
onReset: resetDialog()
}
}
}
function sendBugReport() {
const text = awBugReporter.generateText(description.text, reproduce.text, expected.text, logBody.text)
awBugReporter.sendBugReport(title.text, text)
}
function resetDialog() {
title.text = ""
description.text = ""
reproduce.text = ""
expected.text = ""
logBody.text = ""
}
Component.onCompleted: {
resetDialog()
awBugReporter.doConnect()
}
}

View File

@ -15,172 +15,319 @@
* 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.15 import QtQuick 2.0
import QtQuick.Controls import QtQuick.Controls 1.3 as QtControls
import org.kde.kcmutils as KCM import QtQuick.Dialogs 1.1 as QtDialogs
import org.kde.plasma.awesomewidgets import org.kde.plasma.private.awesomewidget 1.0
import org.kde.plasma.private.awesomewidget
KCM.SimpleKCM { Item {
id: dataenginePage id: dataenginePage
// backend // backend
AWKeys { AWKeys {
id: awKeys id: awKeys
} }
AWActions {
id: awActions
}
AWConfigHelper { AWConfigHelper {
id: awConfig id: awConfig
} }
width: childrenRect.width
height: childrenRect.height
implicitWidth: pageColumn.implicitWidth
implicitHeight: pageColumn.implicitHeight
property bool debug: awActions.isDebugEnabled()
property variant cfg_dataengine: awConfig.readDataEngineConfiguration() property variant cfg_dataengine: awConfig.readDataEngineConfiguration()
Column {
anchors.fill: parent
GroupBox { Column {
id: pageColumn
anchors.fill: parent
QtControls.GroupBox {
height: implicitHeight height: implicitHeight
width: parent.width width: parent.width
title: i18n("ACPI") title: i18n("ACPI")
LineSelector { Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("ACPI path") text: i18n("ACPI path")
value: cfg_dataengine["ACPIPATH"] }
onValueEdited: newValue => cfg_dataengine["ACPIPATH"] = newValue QtControls.TextField {
width: parent.width * 3 / 5
text: cfg_dataengine["ACPIPATH"]
onEditingFinished: cfg_dataengine["ACPIPATH"] = text
}
} }
} }
GroupBox { QtControls.GroupBox {
height: implicitHeight
width: parent.width
title: i18n("GPU")
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("GPU device")
}
QtControls.ComboBox {
id: gpuDev
width: parent.width * 3 / 5
model: ["auto", "disable", "ati", "nvidia"]
Component.onCompleted: {
if (debug) console.debug()
for (var i=0; i<model.length; i++) {
if (model[i] == cfg_dataengine["GPUDEV"]) {
if (debug) console.info("Found", model[i], "on", i)
currentIndex = i;
}
}
}
}
}
}
QtControls.GroupBox {
height: implicitHeight
width: parent.width
title: i18n("HDD temperature")
Column {
height: implicitHeight
width: parent.width
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("HDD")
}
QtControls.ComboBox {
id: hdd
width: parent.width * 3 / 5
}
}
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
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 {
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
IntegerSelector { Row {
maximumValue: 100 height: implicitHeight
minimumValue: 1 width: parent.width
stepSize: 1 QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Player data symbols") text: i18n("Player data symbols")
}
QtControls.SpinBox {
width: parent.width * 3 / 5
minimumValue: 1
maximumValue: 100
stepSize: 1
value: cfg_dataengine["PLAYERSYMBOLS"] value: cfg_dataengine["PLAYERSYMBOLS"]
onValueEdited: newValue => cfg_dataengine["PLAYERSYMBOLS"] = newValue onEditingFinished: cfg_dataengine["PLAYERSYMBOLS"] = value
}
} }
ComboBoxSelector { Row {
model: [ height: implicitHeight
{ width: parent.width
"label": "disable", QtControls.Label {
"name": "disable" height: parent.height
}, width: parent.width * 2 / 5
{ horizontalAlignment: Text.AlignRight
"label": "mpris", verticalAlignment: Text.AlignVCenter
"name": "mpris"
},
{
"label": "mpd",
"name": "mpd"
}
]
text: i18n("Music player") text: i18n("Music player")
value: cfg_dataengine["PLAYER"] }
onValueEdited: newValue => cfg_dataengine["PLAYER"] = newValue QtControls.ComboBox {
id: player
width: parent.width * 3 / 5
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;
}
}
}
}
} }
ComboBoxSelector { Row {
id: mpris height: implicitHeight
editable: true width: parent.width
model: [ QtControls.Label {
{ height: parent.height
"label": "auto", width: parent.width * 2 / 5
"name": "auto" horizontalAlignment: Text.AlignRight
}, verticalAlignment: Text.AlignVCenter
{
"label": "amarok",
"name": "amarok"
},
{
"label": "audacious",
"name": "audacious"
},
{
"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") text: i18n("MPRIS player name")
}
QtControls.ComboBox {
id: mpris
width: parent.width * 3 / 5
editable: true
model: ["auto", "amarok", "audacious", "clementine", "deadbeef",
"vlc", "qmmp", "xmms2", cfg_dataengine["MPRIS"]]
currentIndex: model.length - 1 currentIndex: model.length - 1
} }
}
LineSelector { Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("MPD address") text: i18n("MPD address")
value: cfg_dataengine["MPDADDRESS"] }
onValueEdited: newValue => cfg_dataengine["MPDADDRESS"] = newValue QtControls.TextField {
width: parent.width * 3 / 5
text: cfg_dataengine["MPDADDRESS"]
onEditingFinished: cfg_dataengine["MPDADDRESS"] = text
}
} }
IntegerSelector { Row {
maximumValue: 65535 height: implicitHeight
minimumValue: 1000 width: parent.width
stepSize: 1 QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("MPD port") text: i18n("MPD port")
}
QtControls.SpinBox {
width: parent.width * 3 / 5
minimumValue: 1000
maximumValue: 65535
stepSize: 1
value: cfg_dataengine["MPDPORT"] value: cfg_dataengine["MPDPORT"]
onValueEdited: newValue => cfg_dataengine["MPDPORT"] = newValue onEditingFinished: cfg_dataengine["MPDPORT"] = value
}
} }
} }
} }
GroupBox { QtControls.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")
}
} }
ButtonSelector { Row {
value: i18n("Network requests") height: implicitHeight
onButtonActivated: awKeys.editItem("extnetworkrequest") width: parent.width
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")
}
} }
ButtonSelector { Row {
value: i18n("Package manager") height: implicitHeight
onButtonActivated: awKeys.editItem("extupgrade") width: parent.width
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")
}
} }
ButtonSelector { Row {
value: i18n("Quotes monitor") height: implicitHeight
onButtonActivated: awKeys.editItem("extquotes") width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Weather")
}
QtControls.Button {
width: parent.width * 3 / 5
text: i18n("Edit weather")
onClicked: awKeys.editItem("extweather")
} }
ButtonSelector {
value: i18n("Weather")
onButtonActivated: awKeys.editItem("extweather")
} }
} }
} }
@ -188,12 +335,28 @@ KCM.SimpleKCM {
Component.onCompleted: { Component.onCompleted: {
if (debug) console.debug()
// init submodule // init submodule
awKeys.updateCache() awKeys.updateCache()
// update hdd model
hdd.model = awKeys.getHddDevices()
for (var i=0; i<hdd.model.length; i++) {
if (hdd.model[i] == cfg_dataengine["HDDDEV"]) {
if (debug) console.info("Found", hdd.model[i], "on", i)
hdd.currentIndex = i;
}
}
} }
Component.onDestruction: { Component.onDestruction: {
cfg_dataengine["MPRIS"] = mpris.editText if (debug) console.debug()
cfg_dataengine["GPUDEV"] = gpuDev.currentText
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,24 +15,22 @@
* 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.15 pragma Singleton
import QtQuick.Controls import QtQuick 2.0
Row { QtObject {
height: implicitHeight property variant fontWeight: {
width: parent.width "light": Font.Light,
"normal": Font.Normal,
property alias text: checkBox.text "demibold": Font.DemiBold,
property alias checked: checkBox.checked "bold": Font.Bold,
"black": Font.Black
Label {
height: parent.heigth
width: parent.width * 2 / 5
} }
property variant align: {
CheckBox { "left": Text.AlignLeft,
id: checkBox "center": Text.AlignHCenter,
width: parent.width * 3 / 5 "right": Text.AlignRight,
"justify": Text.AlignJustify
} }
} }

View File

@ -15,18 +15,20 @@
* 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.15 import QtQuick 2.4
import QtQuick.Layouts import QtQuick.Controls 1.3 as QtControls
import org.kde.plasma.core as PlasmaCore import QtQuick.Dialogs 1.2 as QtDialogs
import QtQuick.Layouts 1.1
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.awesomewidgets import org.kde.plasma.private.awesomewidget 1.0
import org.kde.plasma.private.awesomewidget import "."
PlasmoidItem { Item {
id: main id: main
// backend // backend
AWKeys { AWKeys {
id: awKeys id: awKeys
@ -34,10 +36,8 @@ PlasmoidItem {
AWActions { AWActions {
id: awActions id: awActions
} }
AWTelemetryHandler {
id: awTelemetryHandler
}
property bool debug: awActions.isDebugEnabled()
property variant tooltipSettings: { property variant tooltipSettings: {
"tooltipNumber": plasmoid.configuration.tooltipNumber, "tooltipNumber": plasmoid.configuration.tooltipNumber,
"useTooltipBackground": plasmoid.configuration.useTooltipBackground, "useTooltipBackground": plasmoid.configuration.useTooltipBackground,
@ -67,12 +67,19 @@ PlasmoidItem {
signal needToolTipUpdate(string newText) signal needToolTipUpdate(string newText)
signal sizeUpdate signal sizeUpdate
Layout.fillWidth: PlasmoidItem.formFactor !== PlasmaCore.Planar
Layout.fillHeight: PlasmoidItem.formFactor !== PlasmaCore.Planar // init
Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation
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
Text { Text {
@ -82,17 +89,14 @@ PlasmoidItem {
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" 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
@ -106,55 +110,72 @@ PlasmoidItem {
} }
} }
Plasmoid.contextualActions: [ QtDialogs.Dialog {
PlasmaCore.Action { id: tagSelector
text: i18n("Run monitor") title: i18n("Select tag")
icon.name: "utilities-system-monitor"
onTriggered: awActions.runCmd("plasma-systemmonitor", []) QtControls.ComboBox {
}, id: tagSelectorBox
PlasmaCore.Action { width: parent.width
text: i18n("Show README") editable: true
icon.name: "text-x-readme" }
onTriggered: awActions.showReadme()
}, onAccepted: {
PlasmaCore.Action { var tag = tagSelectorBox.editText
text: i18n("Check updates") var message = i18n("Tag: %1", tag)
icon.name: "system-software-update" message += "<br>"
onTriggered: awActions.checkUpdates(true) message += i18n("Value: %1", awKeys.valueByKey(tag))
message += "<br>"
message += i18n("Info: %1", awKeys.infoByKey(tag))
awActions.sendNotification("tag", message)
}
} }
]
Component.onCompleted: { Component.onCompleted: {
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
awKeys.needTextToBeUpdated.connect(needTextUpdate) awKeys.needTextToBeUpdated.connect(needTextUpdate)
//awKeys.needToolTipToBeUpdated.connect(needToolTipUpdate) awKeys.needToolTipToBeUpdated.connect(needToolTipUpdate)
// check updates if required // check updates if required
if (plasmoid.configuration.checkUpdates) return awActions.checkUpdates(false) if (plasmoid.configuration.checkUpdates) return awActions.checkUpdates(false)
} }
onNeedTextUpdate: newText => { onNeedTextUpdate: {
if (debug) console.debug()
text.text = newText text.text = newText
sizeUpdate() sizeUpdate()
} }
onNeedToolTipUpdate: newText => { onNeedToolTipUpdate: {
if (debug) console.debug()
tooltip.text = newText tooltip.text = newText
} }
onSizeUpdate: { onSizeUpdate: {
if (debug) console.debug()
// 16 is a magic number // 16 is a magic number
// in other case plasmoid will increase own size on each update // in other case plasmoid will increase own size on each update
if (plasmoid.configuration.height === 0) {
if (plasmoid.configuration.height == 0) {
Layout.minimumHeight = text.contentHeight - 16 Layout.minimumHeight = text.contentHeight - 16
Layout.maximumHeight = -1 Layout.maximumHeight = -1
} else { } else {
Layout.minimumHeight = plasmoid.configuration.height Layout.minimumHeight = plasmoid.configuration.height
Layout.maximumHeight = plasmoid.configuration.height Layout.maximumHeight = plasmoid.configuration.height
} }
if (plasmoid.configuration.width === 0) { if (plasmoid.configuration.width == 0) {
Layout.minimumWidth = text.contentWidth - 16 Layout.minimumWidth = text.contentWidth - 16
Layout.maximumWidth = -1 Layout.maximumWidth = -1
} else { } else {
@ -165,10 +186,12 @@ PlasmoidItem {
Plasmoid.onUserConfiguringChanged: { Plasmoid.onUserConfiguringChanged: {
if (plasmoid.userConfiguring) return if (plasmoid.userConfiguring) return
if (debug) console.debug()
// init submodule // init submodule
awKeys.initDataAggregator(tooltipSettings) awKeys.initDataAggregator(tooltipSettings)
awKeys.initKeys(plasmoid.configuration.text, plasmoid.configuration.interval, plasmoid.configuration.optimize) awKeys.initKeys(plasmoid.configuration.text, plasmoid.configuration.interval,
plasmoid.configuration.queueLimit, plasmoid.configuration.optimize)
awKeys.setWrapNewLines(plasmoid.configuration.wrapNewLines) awKeys.setWrapNewLines(plasmoid.configuration.wrapNewLines)
// configure aggregator // configure aggregator
awKeys.setAggregatorProperty("acOffline", plasmoid.configuration.acOffline) awKeys.setAggregatorProperty("acOffline", plasmoid.configuration.acOffline)
@ -177,8 +200,25 @@ PlasmoidItem {
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)
// save telemetry }
awTelemetryHandler.init(plasmoid.configuration.historyCount)
awTelemetryHandler.put("awwidgetconfig", plasmoid.configuration.text)
function action_checkUpdates() {
if (debug) console.debug()
return awActions.checkUpdates(true)
}
function action_showReadme() {
if (debug) console.debug()
return awActions.showReadme()
}
function action_requestKey() {
if (debug) console.debug()
tagSelectorBox.model = awKeys.dictKeys(true)
return tagSelector.open()
} }
} }

View File

@ -0,0 +1 @@
singleton general 1.0 general.qml

View File

@ -15,39 +15,51 @@
* 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.15 import QtQuick 2.0
import QtQuick.Controls import QtQuick.Controls 1.3 as QtControls
import org.kde.kcmutils as KCM import QtQuick.Controls.Styles 1.3 as QtStyles
import QtQuick.Dialogs 1.1 as QtDialogs
import org.kde.plasma.awesomewidgets import org.kde.plasma.private.awesomewidget 1.0
import org.kde.plasma.private.awesomewidget
KCM.SimpleKCM { Item {
id: tooltipPage id: tooltipPage
// backend
AWActions {
id: awActions
}
width: childrenRect.width
height: childrenRect.height
implicitWidth: pageColumn.implicitWidth
implicitHeight: pageColumn.implicitHeight
property bool debug: awActions.isDebugEnabled()
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.value property alias cfg_tooltipBackground: tooltipBackground.text
property alias cfg_cpuTooltip: cpuTooltip.checked property alias cfg_cpuTooltip: cpuTooltip.checked
property alias cfg_cpuTooltipColor: cpuTooltipColor.value property alias cfg_cpuTooltipColor: cpuTooltipColor.text
property alias cfg_cpuclTooltip: cpuclTooltip.checked property alias cfg_cpuclTooltip: cpuclTooltip.checked
property alias cfg_cpuclTooltipColor: cpuclTooltipColor.value property alias cfg_cpuclTooltipColor: cpuclTooltipColor.text
property alias cfg_memTooltip: memTooltip.checked property alias cfg_memTooltip: memTooltip.checked
property alias cfg_memTooltipColor: memTooltipColor.value property alias cfg_memTooltipColor: memTooltipColor.text
property alias cfg_swapTooltip: swapTooltip.checked property alias cfg_swapTooltip: swapTooltip.checked
property alias cfg_swapTooltipColor: swapTooltipColor.value property alias cfg_swapTooltipColor: swapTooltipColor.text
property alias cfg_downkbTooltip: networkTooltip.checked property alias cfg_downkbTooltip: downkbTooltip.checked
property alias cfg_downkbTooltipColor: downkbTooltipColor.value property alias cfg_downkbTooltipColor: downkbTooltipColor.text
property alias cfg_upkbTooltipColor: upkbTooltipColor.value property alias cfg_upkbTooltipColor: upkbTooltipColor.text
property alias cfg_batTooltip: batTooltip.checked property alias cfg_batTooltip: batTooltip.checked
property alias cfg_batTooltipColor: batTooltipColor.value property alias cfg_batTooltipColor: batTooltipColor.text
property alias cfg_batInTooltipColor: batInTooltipColor.value property alias cfg_batInTooltipColor: batInTooltipColor.text
Column { Column {
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
@ -55,159 +67,354 @@ KCM.SimpleKCM {
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.")
} }
IntegerSelector { Row {
id: tooltipNumber height: implicitHeight
maximumValue: 1000 width: parent.width
minimumValue: 50 QtControls.Label {
stepSize: 25 height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Number of values for tooltips") 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 value: plasmoid.configuration.tooltipNumber
} }
}
GroupBox { QtControls.GroupBox {
id: useTooltipBackground id: useTooltipBackground
height: implicitHeight
width: parent.width width: parent.width
checkable: true
property alias checked: useTooltipBackgroundLabel.checked title: i18n("Background")
label: CheckBox { Row {
id: useTooltipBackgroundLabel height: implicitHeight
text: i18n("Background") width: parent.width
} QtControls.Label {
height: parent.height
ColorSelector { width: parent.width * 2 / 5
id: tooltipBackground horizontalAlignment: Text.AlignRight
enabled: useTooltipBackgroundLabel.checked verticalAlignment: Text.AlignVCenter
text: i18n("Background color") text: i18n("Background color")
value: plasmoid.configuration.tooltipBackground }
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 {
id: tooltipBackgroundDialog
title: i18n("Select a color")
color: tooltipBackground.text
onAccepted: tooltipBackground.text = tooltipBackgroundDialog.color
}
} }
} }
GroupBox { QtControls.GroupBox {
id: cpuTooltip id: cpuTooltip
height: implicitHeight
width: parent.width width: parent.width
checkable: true
property alias checked: cpuTooltipLabel.checked title: i18n("CPU")
label: CheckBox { Row {
id: cpuTooltipLabel height: implicitHeight
text: i18n("CPU") width: parent.width
} QtControls.Label {
height: parent.height
ColorSelector { width: parent.width * 2 / 5
id: cpuTooltipColor horizontalAlignment: Text.AlignRight
enabled: cpuTooltipLabel.checked verticalAlignment: Text.AlignVCenter
text: i18n("CPU color") text: i18n("CPU color")
value: plasmoid.configuration.cpuTooltipColor }
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 {
id: cpuTooltipColorDialog
title: i18n("Select a color")
color: cpuTooltipColor.text
onAccepted: cpuTooltipColor.text = cpuTooltipColorDialog.color
}
} }
} }
GroupBox { QtControls.GroupBox {
id: cpuclTooltip id: cpuclTooltip
height: implicitHeight
width: parent.width width: parent.width
checkable: true
property alias checked: cpuclTooltipLabel.checked title: i18n("CPU clock")
label: CheckBox { Row {
id: cpuclTooltipLabel height: implicitHeight
text: i18n("CPU clock") width: parent.width
} QtControls.Label {
height: parent.height
ColorSelector { width: parent.width * 2 / 5
id: cpuclTooltipColor horizontalAlignment: Text.AlignRight
enabled: cpuclTooltipLabel.checked verticalAlignment: Text.AlignVCenter
text: i18n("CPU clock color") text: i18n("CPU clock color")
value: plasmoid.configuration.cpuclTooltipColor }
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 {
id: cpuclTooltipColorDialog
title: i18n("Select a color")
color: cpuclTooltipColor.text
onAccepted: cpuclTooltipColor.text = cpuclTooltipColorDialog.color
}
} }
} }
GroupBox { QtControls.GroupBox {
id: memTooltip id: memTooltip
height: implicitHeight
width: parent.width width: parent.width
checkable: true
property alias checked: memTooltipLabel.checked title: i18n("Memory")
label: CheckBox { Row {
id: memTooltipLabel height: implicitHeight
text: i18n("Memory") width: parent.width
} QtControls.Label {
height: parent.height
ColorSelector { width: parent.width * 2 / 5
id: memTooltipColor horizontalAlignment: Text.AlignRight
enabled: memTooltipLabel.checked verticalAlignment: Text.AlignVCenter
text: i18n("Memory color") text: i18n("Memory color")
value: plasmoid.configuration.memTooltipColor }
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 {
id: memTooltipColorDialog
title: i18n("Select a color")
color: memTooltipColor.text
onAccepted: memTooltipColor.text = memTooltipColorDialog.color
}
} }
} }
GroupBox { QtControls.GroupBox {
id: swapTooltip id: swapTooltip
height: implicitHeight
width: parent.width width: parent.width
checkable: true
property alias checked: swapTooltipLabel.checked title: i18n("Swap")
label: CheckBox { Row {
id: swapTooltipLabel height: implicitHeight
text: i18n("Swap") width: parent.width
} QtControls.Label {
height: parent.height
ColorSelector { width: parent.width * 2 / 5
id: swapTooltipColor horizontalAlignment: Text.AlignRight
enabled: swapTooltipLabel.checked verticalAlignment: Text.AlignVCenter
text: i18n("Swap color") text: i18n("Swap color")
value: plasmoid.configuration.swapTooltipColor }
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 {
id: swapTooltipColorDialog
title: i18n("Select a color")
color: swapTooltipColor.text
onAccepted: swapTooltipColor.text = swapTooltipColorDialog.color
}
} }
} }
GroupBox { QtControls.GroupBox {
id: networkTooltip id: downkbTooltip
height: implicitHeight
width: parent.width width: parent.width
checkable: true
property alias checked: networkTooltipLabel.checked title: i18n("Network")
label: CheckBox {
id: networkTooltipLabel
text: i18n("Network")
}
Column { Column {
height: implicitHeight
width: parent.width width: parent.width
enabled: networkTooltipLabel.checked Row {
height: implicitHeight
ColorSelector { width: parent.width
id: downkbTooltipColor QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Download speed color") text: i18n("Download speed color")
value: plasmoid.configuration.downkbTooltipColor }
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
} }
ColorSelector { QtDialogs.ColorDialog {
id: upkbTooltipColor id: downkbTooltipColorDialog
title: i18n("Select a color")
color: downkbTooltipColor.text
onAccepted: downkbTooltipColor.text = downkbTooltipColorDialog.color
}
}
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Upload speed color") text: i18n("Upload speed color")
value: plasmoid.configuration.upkbTooltipColor }
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
}
} }
} }
} }
GroupBox { QtControls.GroupBox {
id: batTooltip id: batTooltip
height: implicitHeight
width: parent.width width: parent.width
checkable: true
property alias checked: batteryTooltipLabel.checked title: i18n("Battery")
label: CheckBox {
id: batteryTooltipLabel
text: i18n("Battery")
}
Column { Column {
height: implicitHeight
width: parent.width width: parent.width
enabled: batteryTooltipLabel.checked Row {
height: implicitHeight
ColorSelector { width: parent.width
id: batTooltipColor QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Battery active color") text: i18n("Battery active color")
value: plasmoid.configuration.batTooltipColor }
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
} }
ColorSelector { QtDialogs.ColorDialog {
id: batInTooltipColor id: batTooltipColorDialog
title: i18n("Select a color")
color: batTooltipColor.text
onAccepted: batTooltipColor.text = batTooltipColorDialog.color
}
}
Row {
height: implicitHeight
width: parent.width
QtControls.Label {
height: parent.height
width: parent.width * 2 / 5
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: i18n("Battery inactive color") text: i18n("Battery inactive color")
value: plasmoid.configuration.batInTooltipColor }
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
} }
} }
} }
} }
} }
Component.onCompleted: {
if (debug) console.debug()
}
}

View File

@ -15,17 +15,15 @@
* 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.15 import QtQuick 2.0
import QtQuick.Controls import QtQuick.Controls 1.3 as QtControls
import org.kde.kcmutils as KCM import QtQuick.Dialogs 1.2 as QtDialogs
import org.kde.plasma.awesomewidgets import org.kde.plasma.private.awesomewidget 1.0
import org.kde.plasma.private.awesomewidget
KCM.SimpleKCM { Item {
id: widgetPage id: widgetPage
// backend // backend
AWKeys { AWKeys {
id: awKeys id: awKeys
@ -33,42 +31,337 @@ KCM.SimpleKCM {
AWActions { AWActions {
id: awActions id: awActions
} }
AWFormatterConfigFactory {
id: awFormatter
}
width: childrenRect.width
height: childrenRect.height
implicitWidth: pageColumn.implicitWidth
implicitHeight: pageColumn.implicitHeight
property bool debug: awActions.isDebugEnabled()
property alias cfg_text: textPattern.text property alias cfg_text: textPattern.text
property bool lock: true property bool lock: true
signal needTextUpdate(string newText) signal needTextUpdate(string newText)
Column { Column {
id: pageColumn
anchors.fill: parent anchors.fill: parent
QtControls.Label {
AWInfoLabel {} width: parent.width
horizontalAlignment: Text.AlignHCenter
HtmlDefaultFunctionsBar { verticalAlignment: Text.AlignVCenter
textArea: textPattern wrapMode: Text.WordWrap
text: i18n("Detailed information may be found on <a href=\"https://arcanis.me/projects/awesome-widgets/\">project homepage</a>")
onLinkActivated: Qt.openUrlExternally(link);
} }
AWTagSelector { Row {
backend: awKeys height: implicitHeight
notifyBackend: awActions width: parent.width
textArea: textPattern QtControls.Button {
groups: General.awTagRegexp width: parent.width * 3 / 15
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
} }
AWExtensions { var selected = textPattern.selectedText
id: extensions textPattern.remove(textPattern.selectionStart, textPattern.selectionEnd)
backend: awKeys textPattern.insert(textPattern.cursorPosition,
textArea: textPattern "<span style=\"color:" + font.color +
onUnlock: lock = false "; 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")
}
} }
AWTextEditor { 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 {
height: implicitHeight
width: parent.width
QtControls.ComboBox {
width: parent.width * 2 / 5
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_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 {
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
backend: awKeys width: parent.width
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()
awKeys.needTextToBeUpdated.connect(needTextUpdate) awKeys.needTextToBeUpdated.connect(needTextUpdate)
// init submodule // init submodule
awKeys.initKeys(plasmoid.configuration.text, plasmoid.configuration.interval, awKeys.initKeys(plasmoid.configuration.text, plasmoid.configuration.interval,
@ -81,10 +374,12 @@ KCM.SimpleKCM {
awKeys.setAggregatorProperty("translate", plasmoid.configuration.translateStrings) awKeys.setAggregatorProperty("translate", plasmoid.configuration.translateStrings)
} }
onNeedTextUpdate: newText => { onNeedTextUpdate: {
if (lock) return if (lock) return
if (debug) console.debug()
extensions.showMessage(newText) compiledText.text = newText.replace(/&nbsp;/g, " ")
lock = true compiledText.open()
lock = true;
} }
} }

View File

@ -0,0 +1,28 @@
[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.1.2
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

@ -1,26 +0,0 @@
{
"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": "4.0.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}
${Kf6_INCLUDE} ${Kf5_INCLUDE}
) )
file(GLOB SUBPROJECT_SOURCE *.cpp formatters/*.cpp matchers/*.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)
qt6_wrap_ui(SUBPROJECT_UI_HEADER ${SUBPROJECT_UI} OPTIONS --translate ui_i18n) qt5_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} ${Kf6_LIBRARIES}) target_link_libraries(${PLUGIN_NAME} ${PROJECT_LIBRARY} ${Qt_LIBRARIES} ${Kf5_LIBRARIES})
install(TARGETS ${PLUGIN_NAME} DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/private/awesomewidget) install(TARGETS ${PLUGIN_NAME} DESTINATION ${QML_INSTALL_DIR}/org/kde/plasma/private/awesomewidget)
install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/private/awesomewidget) install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/plasma/private/awesomewidget)
install(FILES ${SUBPROJECT_NOTIFY} DESTINATION ${KDE_INSTALL_KNOTIFYRCDIR}) install(FILES ${SUBPROJECT_NOTIFY} DESTINATION ${KNOTIFYRC_INSTALL_DIR})

View File

@ -1,188 +0,0 @@
/***************************************************************************
* 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, &QDialogButtonBox::accepted, this, &AWAbstractPairConfig::accept);
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &AWAbstractPairConfig::reject);
// edit feature
if (m_hasEdit) {
m_editButton = ui->buttonBox->addButton(i18n("Edit"), QDialogButtonBox::ActionRole);
connect(m_editButton, &QPushButton::clicked, [this]() { return edit(); });
}
}
AWAbstractPairConfig::~AWAbstractPairConfig()
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
clearSelectors();
delete ui;
}
void AWAbstractPairConfig::setHelper(std::unique_ptr<AWAbstractPairHelper> _helper)
{
m_helper = std::move(_helper);
}
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()
{
auto current = dynamic_cast<AWAbstractSelector *>(sender())->current();
auto 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;
auto 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, &AWAbstractSelector::selectionChanged, this, &AWAbstractPairConfig::updateUi);
m_selectors.append(selector);
}
void AWAbstractPairConfig::clearSelectors()
{
for (auto selector : m_selectors) {
disconnect(selector, &AWAbstractSelector::selectionChanged, this, &AWAbstractPairConfig::updateUi);
ui->verticalLayout->removeWidget(selector);
selector->deleteLater();
}
m_selectors.clear();
}
void AWAbstractPairConfig::execDialog()
{
auto ret = exec();
QHash<QString, QString> data;
for (auto selector : m_selectors) {
auto 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 {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, {key, pairs[key]});
// empty one
addSelector(keys.first, keys.second, {});
}

View File

@ -1,62 +0,0 @@
/***************************************************************************
* 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/ *
***************************************************************************/
#pragma once
#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 = {});
~AWAbstractPairConfig() override;
void setHelper(std::unique_ptr<AWAbstractPairHelper> _helper);
void showDialog();
// properties
void setEditable(bool _first, bool _second);
private slots:
void edit();
void updateUi();
private:
QPushButton *m_editButton = nullptr;
Ui::AWAbstractPairConfig *ui = nullptr;
std::unique_ptr<AWAbstractPairHelper> m_helper;
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();
};

View File

@ -1,128 +0,0 @@
/***************************************************************************
* 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();
}
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();
auto 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);
auto keys = settings.childKeys();
for (auto &key : keys) {
auto 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;
auto fileName
= QString("%1/%2").arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), 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;
auto fileName
= QString("%1/%2").arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), m_filePath);
QSettings settings(fileName, QSettings::IniFormat);
qCInfo(LOG_AW) << "Configuration file" << fileName;
settings.beginGroup(m_section);
for (auto &key : settings.childKeys()) {
if (_keys.contains(key))
continue;
settings.remove(key);
}
settings.endGroup();
settings.sync();
return settings.status() == QSettings::NoError;
}

View File

@ -1,46 +0,0 @@
/***************************************************************************
* 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/ *
***************************************************************************/
#pragma once
#include <QHash>
class AWAbstractPairHelper
{
public:
explicit AWAbstractPairHelper(QString _filePath = "", QString _section = "");
virtual ~AWAbstractPairHelper() = default;
[[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;
};

View File

@ -21,18 +21,18 @@
#include "awdebug.h" #include "awdebug.h"
AWAbstractSelector::AWAbstractSelector(QWidget *_parent, const QPair<bool, bool> &_editable) AWAbstractSelector::AWAbstractSelector(QWidget *parent)
: 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, &QComboBox::currentIndexChanged, this, &AWAbstractSelector::selectionChanged); connect(ui->comboBox_key, SIGNAL(currentIndexChanged(int)), this,
connect(ui->comboBox_value, &QComboBox::currentIndexChanged, this, &AWAbstractSelector::selectionChanged); SIGNAL(selectionChanged()));
connect(ui->comboBox_value, SIGNAL(currentIndexChanged(int)), this,
SIGNAL(selectionChanged()));
} }
@ -46,30 +46,31 @@ AWAbstractSelector::~AWAbstractSelector()
QPair<QString, QString> AWAbstractSelector::current() const QPair<QString, QString> AWAbstractSelector::current() const
{ {
auto key = ui->comboBox_key->currentText(); QString key = ui->comboBox_key->currentText();
auto value = ui->comboBox_value->currentText(); QString value = ui->comboBox_value->currentText();
return {key, value}; return QPair<QString, QString>(key, value);
} }
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 << "not found in default ones"; qCWarning(LOG_AW) << "Invalid current value" << current
<< "not found in default ones";
return; return;
} }
qCDebug(LOG_AW) << "Init selector with keys" << _keys << "and values" << _values << "and current ones are" qCDebug(LOG_AW) << "Init selector with keys" << keys << "and values"
<< _current; << values << "and current ones are" << 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

@ -15,7 +15,9 @@
* 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 AWABSTRACTSELECTOR_H
#define AWABSTRACTSELECTOR_H
#include <QWidget> #include <QWidget>
@ -30,10 +32,11 @@ class AWAbstractSelector : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit AWAbstractSelector(QWidget *_parent = nullptr, const QPair<bool, bool> &_editable = {false, false}); explicit AWAbstractSelector(QWidget *parent = nullptr);
~AWAbstractSelector() override; virtual ~AWAbstractSelector();
[[nodiscard]] QPair<QString, QString> current() const; QPair<QString, QString> current() const;
void init(const QStringList &_keys, const QStringList &_values, const QPair<QString, QString> &_current); void init(const QStringList keys, const QStringList values,
const QPair<QString, QString> current);
signals: signals:
void selectionChanged(); void selectionChanged();
@ -41,3 +44,6 @@ signals:
private: private:
Ui::AWAbstractSelector *ui = nullptr; Ui::AWAbstractSelector *ui = nullptr;
}; };
#endif /* AWABSTRACTSELECTOR_H */

View File

@ -21,7 +21,6 @@
#include <KNotifications/KNotification> #include <KNotifications/KNotification>
#include <QDesktopServices> #include <QDesktopServices>
#include <QFile>
#include <QProcess> #include <QProcess>
#include <QUrl> #include <QUrl>
@ -31,8 +30,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__;
@ -40,81 +39,143 @@ AWActions::AWActions(QObject *_parent)
} }
void AWActions::checkUpdates(const bool _showAnyway) AWActions::~AWActions()
{ {
qCDebug(LOG_AW) << "Show anyway" << _showAnyway; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
delete m_updateHelper;
}
void AWActions::checkUpdates(const bool 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) // HACK: since QML could not use QLoggingCategory I need this hack
bool AWActions::isDebugEnabled() const
{ {
qCDebug(LOG_AW) << "Get content from file" << _path; return LOG_AW().isDebugEnabled();
QFile inputFile(_path);
if (!inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qCWarning(LOG_AW) << "Could not open file as text" << inputFile.fileName();
return "";
}
auto output = inputFile.readAll();
inputFile.close();
return output;
} }
bool AWActions::runCmd(const QString &_cmd, const QStringList &_args) bool AWActions::runCmd(const QString cmd) const
{ {
qCDebug(LOG_AW) << "Cmd" << _cmd << "args" << _args; qCDebug(LOG_AW) << "Cmd" << cmd;
sendNotification("system", i18n("Run %1", _cmd)); sendNotification(QString("Info"), i18n("Run %1", cmd));
return QProcess::startDetached(_cmd, _args); return QProcess::startDetached(cmd);
} }
// HACK: this method uses variable from version.h // HACK: this method uses variable from version.h
void AWActions::showReadme() void AWActions::showReadme() const
{ {
QDesktopServices::openUrl(QUrl(HOMEPAGE)); QDesktopServices::openUrl(QUrl(HOMEPAGE));
} }
// HACK: this method uses variables from version.h // HACK: this method uses variables from version.h
QString AWActions::getAboutText(const QString &_type) QString AWActions::getAboutText(const QString type) const
{ {
qCDebug(LOG_AW) << "Type" << _type; qCDebug(LOG_AW) << "Type" << type;
return AWDebug::getAboutText(_type); QString text;
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) QVariantMap AWActions::getFont(const QVariantMap defaultFont) const
{ {
qCDebug(LOG_AW) << "Default font is" << _defaultFont; qCDebug(LOG_AW) << "Default font is" << defaultFont;
QVariantMap fontMap; QVariantMap fontMap;
auto ret = 0; int ret = 0;
auto defaultCFont = CFont(_defaultFont["family"].toString(), _defaultFont["size"].toInt(), 400, false, CFont defaultCFont = CFont(defaultFont[QString("family")].toString(),
_defaultFont["color"].toString()); defaultFont[QString("size")].toInt(), 400, false,
auto font = CFontDialog::getFont(i18n("Select font"), defaultCFont, false, false, &ret); defaultFont[QString("color")].toString());
CFont font = CFontDialog::getFont(i18n("Select font"), defaultCFont, false,
false, &ret);
fontMap["applied"] = ret; fontMap[QString("applied")] = ret;
fontMap["color"] = font.color().name(); fontMap[QString("color")] = font.color().name();
fontMap["family"] = font.family(); fontMap[QString("family")] = font.family();
fontMap["size"] = font.pointSize(); fontMap[QString("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;
auto event = KNotification::event(_eventId, QString("Awesome Widget ::: %1").arg(_eventId), _message); KNotification *notification = KNotification::event(
event->setComponentName("plasma-applet-org.kde.plasma.awesome-widget"); eventId, QString("Awesome Widget ::: %1").arg(eventId), message);
notification->setComponentName(
QString("plasma-applet-org.kde.plasma.awesome-widget"));
} }

View File

@ -15,7 +15,9 @@
* 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 AWACTIONS_H
#define AWACTIONS_H
#include <QMap> #include <QMap>
#include <QObject> #include <QObject>
@ -28,19 +30,24 @@ class AWActions : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit AWActions(QObject *_parent = nullptr); explicit AWActions(QObject *parent = nullptr);
~AWActions() override = default; virtual ~AWActions();
Q_INVOKABLE void checkUpdates(bool _showAnyway = false); Q_INVOKABLE void checkUpdates(const bool showAnyway = false);
Q_INVOKABLE static QString getFileContent(const QString &_path); Q_INVOKABLE bool isDebugEnabled() const;
Q_INVOKABLE static bool runCmd(const QString &_cmd, const QStringList &_args); Q_INVOKABLE bool runCmd(const QString cmd = QString("/usr/bin/true")) const;
Q_INVOKABLE static void showReadme(); Q_INVOKABLE void showReadme() const;
// configuration slots // configuration slots
Q_INVOKABLE static QString getAboutText(const QString &_type); Q_INVOKABLE QString getAboutText(const QString type
Q_INVOKABLE static QVariantMap getFont(const QVariantMap &_defaultFont); = QString("header")) const;
Q_INVOKABLE QVariantMap getFont(const QVariantMap defaultFont) const;
public slots: public slots:
Q_INVOKABLE static void sendNotification(const QString &_eventId, const QString &_message); Q_INVOKABLE static void sendNotification(const QString eventId,
const QString message);
private: private:
AWUpdateHelper *m_updateHelper = nullptr; AWUpdateHelper *m_updateHelper = nullptr;
}; };
#endif /* AWACTIONS_H */

View File

@ -1,139 +0,0 @@
/***************************************************************************
* 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 <KNotifications/KNotification>
#include <QDesktopServices>
#include <QJsonDocument>
#include <QMessageBox>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include "awdebug.h"
AWBugReporter::AWBugReporter(QObject *_parent)
: QObject(_parent)
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
m_manager = new QNetworkAccessManager(nullptr);
connect(m_manager, &QNetworkAccessManager::finished, this, &AWBugReporter::issueReplyReceived);
}
AWBugReporter::~AWBugReporter()
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
m_manager->deleteLater();
}
void AWBugReporter::doConnect() const
{
// additional method for testing needs
connect(this, &AWBugReporter::replyReceived, this, &AWBugReporter::showInformation);
}
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 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
auto data = QJsonDocument::fromVariant(payload).toJson(QJsonDocument::Compact);
qCInfo(LOG_AW) << "Send request with _body" << data.data() << "and size" << data.size();
m_manager->post(request, data);
}
void AWBugReporter::issueReplyReceived(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{};
auto 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
auto response = jsonDoc.toVariant().toMap();
auto url = response["html_url"].toString();
auto number = response["number"].toInt();
return emit(replyReceived(number, url));
}
void AWBugReporter::openBugReport()
{
QDesktopServices::openUrl(m_lastBugUrl);
}
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 event = KNotification::event("system", i18n("Issue created"), i18n("Issue %1 has been created", _number));
event->setComponentName("plasma-applet-org.kde.plasma.awesome-widget");
auto action = event->addAction(i18n("Details"));
connect(action, &KNotificationAction::activated, this, &AWBugReporter::openBugReport);
}

View File

@ -1,49 +0,0 @@
/***************************************************************************
* 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/ *
***************************************************************************/
#pragma once
#include <QObject>
class QNetworkAccessManager;
class QNetworkReply;
class __attribute__((visibility("default"))) AWBugReporter : public QObject
{
Q_OBJECT
public:
explicit AWBugReporter(QObject *_parent = nullptr);
~AWBugReporter() override;
Q_INVOKABLE void doConnect() const;
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 issueReplyReceived(QNetworkReply *_reply);
void openBugReport();
void showInformation(int _number, const QString &_url);
private:
QString m_lastBugUrl;
QNetworkAccessManager *m_manager = nullptr;
};

View File

@ -17,32 +17,40 @@
#include "awconfighelper.h" #include "awconfighelper.h"
#include <KI18n/KLocalizedString>
#include <QDir> #include <QDir>
#include <QQmlPropertyMap> #include <QQmlPropertyMap>
#include <QSettings> #include <QSettings>
#include <QStandardPaths> #include <QTextCodec>
#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));
} }
QString AWConfigHelper::configurationDirectory() AWConfigHelper::~AWConfigHelper()
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
}
QString AWConfigHelper::configurationDirectory() const
{ {
// get readable directory // get readable directory
auto localDir = QString("%1/awesomewidgets/configs") QString localDir = QString("%1/awesomewidgets/configs")
.arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)); .arg(QStandardPaths::writableLocation(
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)) && (localDirectory.mkpath(localDir))) { if ((!localDirectory.exists(localDir))
&& (localDirectory.mkpath(localDir))) {
qCInfo(LOG_AW) << "Created directory" << localDir; qCInfo(LOG_AW) << "Created directory" << localDir;
copyConfigs(localDir); copyConfigs(localDir);
} }
@ -51,25 +59,29 @@ QString AWConfigHelper::configurationDirectory()
} }
bool AWConfigHelper::dropCache() bool AWConfigHelper::dropCache() const
{ {
auto fileName QString fileName = QString("%1/awesomewidgets.ndx")
= QString("%1/awesomewidgets.ndx").arg(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation)); .arg(QStandardPaths::writableLocation(
QStandardPaths::GenericCacheLocation));
return QFile(fileName).remove(); return QFile(fileName).remove();
} }
bool AWConfigHelper::exportConfiguration(QObject *_nativeConfig, const QString &_fileName) const bool AWConfigHelper::exportConfiguration(const QObject *nativeConfig,
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
auto configuration = dynamic_cast<const QQmlPropertyMap *>(_nativeConfig); const QQmlPropertyMap *configuration
settings.beginGroup("plasmoid"); = static_cast<const QQmlPropertyMap *>(nativeConfig);
for (auto &key : configuration->keys()) { settings.beginGroup(QString("plasmoid"));
auto value = configuration->value(key); for (auto key : configuration->keys()) {
QVariant value = configuration->value(key);
if (!value.isValid()) if (!value.isValid())
continue; continue;
settings.setValue(key, value); settings.setValue(key, value);
@ -77,27 +89,27 @@ bool AWConfigHelper::exportConfiguration(QObject *_nativeConfig, const QString &
settings.endGroup(); settings.endGroup();
// extensions // extensions
for (auto &item : m_dirs) { for (auto item : m_dirs) {
auto items = QDir(QString("%1/%2").arg(m_baseDir, item)).entryList({"*.desktop"}, QDir::Files); QStringList items
= QDir(QString("%1/%2").arg(m_baseDir).arg(item))
.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("json"); settings.beginGroup(QString("json"));
// script filters // script filters
readFile(settings, "filters", QString("%1/scripts/awesomewidgets-extscripts-filters.json").arg(m_baseDir)); readFile(settings, QString("filters"),
QString("%1/scripts/awesomewidgets-extscripts-filters.json")
.arg(m_baseDir));
// weather icon settings // weather icon settings
readFile(settings, "weathers", QString("%1/weather/awesomewidgets-extweather-ids.json").arg(m_baseDir)); readFile(settings, QString("weathers"),
settings.endGroup(); QString("%1/weather/awesomewidgets-extweather-ids.json")
.arg(m_baseDir));
settings.beginGroup("ini");
// formatter settings
readFile(settings, "formatters", 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
@ -107,45 +119,44 @@ bool AWConfigHelper::exportConfiguration(QObject *_nativeConfig, const QString &
} }
QVariantMap AWConfigHelper::importConfiguration(const QString &_fileName, const bool _importPlasmoid, QVariantMap AWConfigHelper::importConfiguration(const QString fileName,
const bool _importExtensions, const bool _importAdds) const const bool importPlasmoid,
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("json"); settings.beginGroup(QString("json"));
// script filters // script filters
writeFile(settings, "filters", QString("%1/scripts/awesomewidgets-extscripts-filters.json").arg(m_baseDir)); writeFile(settings, QString("filters"),
QString("%1/scripts/awesomewidgets-extscripts-filters.json")
.arg(m_baseDir));
// weather icon settings // weather icon settings
writeFile(settings, "weathers", QString("%1/weather/awesomewidgets-extweather-ids.json").arg(m_baseDir)); writeFile(settings, QString("weathers"),
settings.endGroup(); QString("%1/weather/awesomewidgets-extweather-ids.json")
.arg(m_baseDir));
settings.beginGroup("ini");
// formatter settings
writeFile(settings, "formatters", 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("plasmoid"); settings.beginGroup(QString("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();
} }
@ -154,20 +165,34 @@ QVariantMap AWConfigHelper::importConfiguration(const QString &_fileName, const
} }
QVariantMap AWConfigHelper::readDataEngineConfiguration() QVariantMap AWConfigHelper::readDataEngineConfiguration() const
{ {
auto fileName = QStandardPaths::locate(QStandardPaths::ConfigLocation, "plasma-dataengine-extsysmon.conf"); QString fileName
= 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("Configuration"); settings.beginGroup(QString("Configuration"));
configuration["ACPIPATH"] = settings.value("ACPIPATH", "/sys/class/power_supply/"); configuration[QString("ACPIPATH")] = settings.value(
configuration["MPDADDRESS"] = settings.value("MPDADDRESS", "localhost"); QString("ACPIPATH"), QString("/sys/class/power_supply/"));
configuration["MPDPORT"] = settings.value("MPDPORT", "6600"); configuration[QString("GPUDEV")]
configuration["MPRIS"] = settings.value("MPRIS", "auto"); = settings.value(QString("GPUDEV"), QString("auto"));
configuration["PLAYER"] = settings.value("PLAYER", "mpris"); configuration[QString("HDDDEV")]
configuration["PLAYERSYMBOLS"] = settings.value("PLAYERSYMBOLS", "10"); = settings.value(QString("HDDDEV"), QString("all"));
configuration[QString("HDDTEMPCMD")]
= settings.value(QString("HDDTEMPCMD"), QString("sudo smartctl -a"));
configuration[QString("MPDADDRESS")]
= 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;
@ -176,22 +201,30 @@ QVariantMap AWConfigHelper::readDataEngineConfiguration()
} }
bool AWConfigHelper::writeDataEngineConfiguration(const QVariantMap &_configuration) bool AWConfigHelper::writeDataEngineConfiguration(
const QVariantMap configuration) const
{ {
qCDebug(LOG_AW) << "Configuration" << _configuration; qCDebug(LOG_AW) << "Configuration" << configuration;
auto fileName = QString("%1/plasma-dataengine-extsysmon.conf") QString fileName
.arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)); = 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("Configuration"); settings.beginGroup(QString("Configuration"));
settings.setValue("ACPIPATH", _configuration["ACPIPATH"]); settings.setValue(QString("ACPIPATH"), configuration[QString("ACPIPATH")]);
settings.setValue("MPDADDRESS", _configuration["MPDADDRESS"]); settings.setValue(QString("GPUDEV"), configuration[QString("GPUDEV")]);
settings.setValue("MPDPORT", _configuration["MPDPORT"]); settings.setValue(QString("HDDDEV"), configuration[QString("HDDDEV")]);
settings.setValue("MPRIS", _configuration["MPRIS"]); settings.setValue(QString("HDDTEMPCMD"),
settings.setValue("PLAYER", _configuration["PLAYER"]); configuration[QString("HDDTEMPCMD")]);
settings.setValue("PLAYERSYMBOLS", _configuration["PLAYERSYMBOLS"]); settings.setValue(QString("MPDADDRESS"),
configuration[QString("MPDADDRESS")]);
settings.setValue(QString("MPDPORT"), configuration[QString("MPDPORT")]);
settings.setValue(QString("MPRIS"), configuration[QString("MPRIS")]);
settings.setValue(QString("PLAYER"), configuration[QString("PLAYER")]);
settings.setValue(QString("PLAYERSYMBOLS"),
configuration[QString("PLAYERSYMBOLS")]);
settings.endGroup(); settings.endGroup();
settings.sync(); settings.sync();
@ -200,81 +233,91 @@ bool AWConfigHelper::writeDataEngineConfiguration(const QVariantMap &_configurat
} }
void AWConfigHelper::copyConfigs(const QString &_localDir) void AWConfigHelper::copyConfigs(const QString localDir) const
{ {
qCDebug(LOG_AW) << "Local directory" << _localDir; qCDebug(LOG_AW) << "Local directory" << localDir;
auto dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "awesomewidgets/configs", QStringList dirs = QStandardPaths::locateAll(
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;
auto files = QDir(dir).entryList(QDir::Files); QStringList files = QDir(dir).entryList(QDir::Files);
for (auto &source : files) { for (auto source : files) {
auto destination = QString("%1/%2").arg(_localDir, source); QString destination = QString("%1/%2").arg(localDir).arg(source);
auto status = QFile::copy(QString("%1/%2").arg(dir, source), destination); bool status = QFile::copy(QString("%1/%2").arg(dir).arg(source),
qCInfo(LOG_AW) << "File" << source << "has been copied to" << destination << "with status" << status; destination);
qCInfo(LOG_AW) << "File" << source << "has been copied to"
<< destination << "with status" << status;
} }
} }
} }
void AWConfigHelper::copyExtensions(const QString &_item, const QString &_type, QSettings &_settings, void AWConfigHelper::copyExtensions(const QString item, const QString type,
const bool _inverse) const QSettings &settings,
const bool inverse) const
{ {
qCDebug(LOG_AW) << "Extension" << _item << "has type" << _type << "inverse copying" << _inverse; qCDebug(LOG_AW) << "Extension" << item << "has type" << type
<< "inverse copying" << inverse;
_settings.beginGroup(_item); settings.beginGroup(item);
QSettings itemSettings(QString("%1/%2/%3").arg(m_baseDir, _type, _item), QSettings::IniFormat); QSettings itemSettings(
itemSettings.beginGroup("Desktop Entry"); QString("%1/%2/%3").arg(m_baseDir).arg(type).arg(item),
if (_inverse) QSettings::IniFormat);
copySettings(_settings, itemSettings); itemSettings.beginGroup(QString("Desktop Entry"));
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) void AWConfigHelper::copySettings(QSettings &from, QSettings &to) const
{ {
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, const QString &_fileName) void AWConfigHelper::readFile(QSettings &settings, const QString key,
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)) {
auto 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 to read" << file.fileName(); qCWarning(LOG_AW) << "Could not open" << file.fileName();
} }
} }
void AWConfigHelper::writeFile(QSettings &_settings, const QString &_key, const QString &_fileName) void AWConfigHelper::writeFile(QSettings &settings, const QString key,
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 << _settings.value(_key).toString().toUtf8(); out.setCodec("UTF-8");
out << settings.value(key).toString().toUtf8();
out.flush(); out.flush();
file.close(); file.close();
} else { } else {
qCWarning(LOG_AW) << "Could not open to write" << file.fileName(); qCWarning(LOG_AW) << "Could not open" << file.fileName();
} }
} }

View File

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

View File

@ -1,31 +0,0 @@
/***************************************************************************
* 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 "awcustomkeysconfig.h"
#include "awcustomkeyshelper.h"
#include "awdebug.h"
AWCustomKeysConfig::AWCustomKeysConfig(QWidget *_parent, const QStringList &_keys)
: AWAbstractPairConfig(_parent, false, _keys)
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
setEditable(true, false);
setHelper(std::make_unique<AWCustomKeysHelper>());
}

View File

@ -1,30 +0,0 @@
/***************************************************************************
* 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/ *
***************************************************************************/
#pragma once
#include "awabstractpairconfig.h"
class AWCustomKeysConfig : public AWAbstractPairConfig
{
Q_OBJECT
public:
explicit AWCustomKeysConfig(QWidget *_parent = nullptr, const QStringList &_keys = QStringList());
~AWCustomKeysConfig() override = default;
};

View File

@ -1,72 +0,0 @@
/***************************************************************************
* 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__;
}
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

@ -1,40 +0,0 @@
/***************************************************************************
* 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/ *
***************************************************************************/
#pragma once
#include <QObject>
#include "awabstractpairhelper.h"
class AWCustomKeysHelper : public QObject, public AWAbstractPairHelper
{
Q_OBJECT
public:
explicit AWCustomKeysHelper(QObject *_parent = nullptr);
~AWCustomKeysHelper() override = default;
// 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;
};

View File

@ -22,6 +22,8 @@
#include <QBuffer> #include <QBuffer>
#include <QGraphicsScene> #include <QGraphicsScene>
#include <QGraphicsView> #include <QGraphicsView>
#include <QPixmap>
#include <QtConcurrent/QtConcurrent>
#include <cmath> #include <cmath>
@ -29,20 +31,22 @@
#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["cpuTooltip"] = 100.0; boundaries[QString("cpuTooltip")] = 100.0;
m_boundaries["cpuclTooltip"] = 4000.0; boundaries[QString("cpuclTooltip")] = 4000.0;
m_boundaries["memTooltip"] = 100.0; boundaries[QString("memTooltip")] = 100.0;
m_boundaries["swapTooltip"] = 100.0; boundaries[QString("swapTooltip")] = 100.0;
m_boundaries["downkbTooltip"] = 1.0; boundaries[QString("downkbTooltip")] = 1.0;
m_boundaries["upkbTooltip"] = 1.0; boundaries[QString("upkbTooltip")] = 1.0;
m_boundaries["batTooltip"] = 100.0; boundaries[QString("batTooltip")] = 100.0;
initScene(); initScene();
connect(this, SIGNAL(updateData(const QVariantHash &)), this,
SLOT(dataUpdate(const QVariantHash &)));
} }
@ -50,246 +54,269 @@ AWDataAggregator::~AWDataAggregator()
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
m_toolTipView->deleteLater(); delete toolTipScene;
m_toolTipScene->deleteLater();
} }
QString AWDataAggregator::htmlImage(const QPixmap &_source) QList<float> AWDataAggregator::getData(const QString key) const
{
qCDebug(LOG_AW) << "Key" << key;
return data[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("<img src=\"data:image/png;base64,%1\"/>").arg(QString(byteArray.toBase64())); ? QString()
: QString("<img src=\"data:image/png;base64,%1\"/>")
.arg(QString(byteArray.toBase64()));
} }
void AWDataAggregator::setParameters(const QVariantMap &_settings) void AWDataAggregator::setParameters(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); configuration = qvariant_cast<QVariantHash>(settings);
m_enablePopup = m_configuration["notify"].toBool(); m_enablePopup = configuration[QString("notify")].toBool();
m_counts = 0; counts = 0;
m_counts += m_configuration["cpuTooltip"].toInt(); counts += configuration[QString("cpuTooltip")].toInt();
m_counts += m_configuration["cpuclTooltip"].toInt(); counts += configuration[QString("cpuclTooltip")].toInt();
m_counts += m_configuration["memTooltip"].toInt(); counts += configuration[QString("memTooltip")].toInt();
m_counts += m_configuration["swapTooltip"].toInt(); counts += configuration[QString("swapTooltip")].toInt();
m_counts += m_configuration["downkbTooltip"].toInt(); counts += configuration[QString("downkbTooltip")].toInt();
m_counts += m_configuration["batTooltip"].toInt(); counts += configuration[QString("batTooltip")].toInt();
// resize tooltip image // resize tooltip image
m_toolTipView->resize(100 * m_counts, 105); toolTipView->resize(100 * counts, 105);
m_requiredKeys.clear(); requiredKeys.clear();
if (m_configuration["cpuTooltip"].toBool()) if (configuration[QString("cpuTooltip")].toBool())
m_requiredKeys.append("cpuTooltip"); requiredKeys.append(QString("cpuTooltip"));
if (m_configuration["cpuclTooltip"].toBool()) if (configuration[QString("cpuclTooltip")].toBool())
m_requiredKeys.append("cpuclTooltip"); requiredKeys.append(QString("cpuclTooltip"));
if (m_configuration["memTooltip"].toBool()) if (configuration[QString("memTooltip")].toBool())
m_requiredKeys.append("memTooltip"); requiredKeys.append(QString("memTooltip"));
if (m_configuration["swapTooltip"].toBool()) if (configuration[QString("swapTooltip")].toBool())
m_requiredKeys.append("swapTooltip"); requiredKeys.append(QString("swapTooltip"));
if (m_configuration["downkbTooltip"].toBool()) if (configuration[QString("downkbTooltip")].toBool())
m_requiredKeys.append("downkbTooltip"); requiredKeys.append(QString("downkbTooltip"));
if (m_configuration["upkbTooltip"].toBool()) if (configuration[QString("upkbTooltip")].toBool())
m_requiredKeys.append("upkbTooltip"); requiredKeys.append(QString("upkbTooltip"));
if (m_configuration["batTooltip"].toBool()) if (configuration[QString("batTooltip")].toBool())
m_requiredKeys.append("batTooltip"); requiredKeys.append(QString("batTooltip"));
// background // background
m_toolTipScene->setBackgroundBrush(m_configuration["useTooltipBackground"].toBool() toolTipScene->setBackgroundBrush(
? QColor(m_configuration["tooltipBackground"].toString()) configuration[QString("useTooltipBackground")].toBool()
: Qt::NoBrush); ? QBrush(QColor(
configuration[QString("tooltipBackground")].toString()))
: QBrush(Qt::NoBrush));
} }
QPixmap AWDataAggregator::tooltipImage() QPixmap AWDataAggregator::tooltipImage()
{ {
// create image // create image
m_toolTipScene->clear(); toolTipScene->clear();
QPen pen; QPen pen;
auto shift = 0.0; bool down = false;
for (auto key : requiredKeys) {
for (auto i = 0; i < m_requiredKeys.count(); ++i) {
auto key = m_requiredKeys[i];
// create frame // create frame
auto normX = 100.0 / static_cast<float>(m_values[key].count()); float normX = 100.0f / static_cast<float>(data[key].count());
auto normY = 100.0 / (1.5 * m_boundaries[key]); float normY = 100.0f / (1.5f * boundaries[key]);
float shift = requiredKeys.indexOf(key) * 100.0f;
if (down)
shift -= 100.0;
// apply pen color // apply pen color
if (key != "batTooltip") if (key != QString("batTooltip"))
pen.setColor(m_configuration[QString("%1Color").arg(key)].toString()); pen.setColor(
QColor(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 < data[key].count() - 1; j++) {
// some magic here // some magic here
auto x1 = j * normX + shift; float x1 = j * normX + shift;
auto y1 = -std::fabs(m_values[key].at(j)) * normY + 5.0; float y1 = -fabs(data[key].at(j)) * normY + 5.0f;
auto x2 = (j + 1) * normX + shift; float x2 = (j + 1) * normX + shift;
auto y2 = -std::fabs(m_values[key].at(j + 1)) * normY + 5.0; float y2 = -fabs(data[key].at(j + 1)) * normY + 5.0f;
// apply color for the battery tooltip based on charge/discharge if (key == QString("batTooltip")) {
if (key == "batTooltip") { if (data[key].at(j + 1) > 0)
if (m_values[key].at(j + 1) > 0) pen.setColor(QColor(
pen.setColor(QColor(m_configuration["batTooltipColor"].toString())); configuration[QString("batTooltipColor")].toString()));
else else
pen.setColor(QColor(m_configuration["batInTooltipColor"].toString())); pen.setColor(
QColor(configuration[QString("batInTooltipColor")]
.toString()));
}
toolTipScene->addLine(x1, y1, x2, y2, pen);
}
if (key == QString("downkbTooltip"))
down = true;
} }
m_toolTipScene->addLine(x1, y1, x2, y2, pen); return toolTipView->grab();
}
// increase frame shift if not downkbtooltip
// Additional workaround is required because there is frame (uokb and downkb) which contains two charts
// with the same shift
if (key != "downkbTooltip")
shift += 100.0;
}
return m_toolTipView->grab();
} }
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 double _value, const double _extremum) const void AWDataAggregator::checkValue(const QString source, const float value,
const float extremum) const
{ {
qCDebug(LOG_AW) << "Notification source" << _source << "with value" << _value << "called with extremum" qCDebug(LOG_AW) << "Notification source" << source << "with value" << value
<< _extremum; << "called with extremum" << extremum;
if (_value >= 0.0) { if (value >= 0.0) {
if ((m_enablePopup) && (_value > _extremum) && (m_values[_source].last() < _extremum)) if ((m_enablePopup) && (value > extremum)
return AWActions::sendNotification("event", notificationText(_source, _value)); && (data[source].last() < extremum))
return AWActions::sendNotification(QString("event"),
notificationText(source, value));
} else { } else {
if ((m_enablePopup) && (_value < _extremum) && (m_values[_source].last() > _extremum)) if ((m_enablePopup) && (value < extremum)
return AWActions::sendNotification("event", notificationText(_source, _value)); && (data[source].last() > extremum))
return AWActions::sendNotification(QString("event"),
notificationText(source, value));
} }
} }
void AWDataAggregator::checkValue(const QString &_source, const QString &_current, const QString &_received) const void AWDataAggregator::checkValue(const QString source, const QString current,
const QString received) const
{ {
qCDebug(LOG_AW) << "Notification source" << _source << "with current value" << _current << "and received one" qCDebug(LOG_AW) << "Notification source" << source << "with current value"
<< _received; << current << "and received one" << received;
if ((m_enablePopup) && (_current != _received) && (!_received.isEmpty())) if ((m_enablePopup) && (current != received) && (!received.isEmpty()))
return AWActions::sendNotification("event", notificationText(_source, _received)); return AWActions::sendNotification(QString("event"),
notificationText(source, received));
} }
void AWDataAggregator::initScene() void AWDataAggregator::initScene()
{ {
m_toolTipScene = new QGraphicsScene(nullptr); toolTipScene = new QGraphicsScene(nullptr);
m_toolTipView = new QGraphicsView(m_toolTipScene); toolTipView = new QGraphicsView(toolTipScene);
m_toolTipView->setStyleSheet("background: transparent"); toolTipView->setStyleSheet(QString("background: transparent"));
m_toolTipView->setContentsMargins(0, 0, 0, 0); toolTipView->setContentsMargins(0, 0, 0, 0);
m_toolTipView->setFrameShape(QFrame::NoFrame); toolTipView->setFrameShape(QFrame::NoFrame);
m_toolTipView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); toolTipView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_toolTipView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); toolTipView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
} }
QString AWDataAggregator::notificationText(const QString &_source, const float _value) QString AWDataAggregator::notificationText(const QString source,
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 == "batTooltip") if (source == QString("batTooltip"))
output = _value > 0.0 ? i18n("AC online") : i18n("AC offline"); output = value > 0.0 ? i18n("AC online") : i18n("AC offline");
else if (_source == "cpuTooltip") else if (source == QString("cpuTooltip"))
output = i18n("High CPU load"); output = i18n("High CPU load");
else if (_source == "memTooltip") else if (source == QString("memTooltip"))
output = i18n("High memory usage"); output = i18n("High memory usage");
else if (_source == "swapTooltip") else if (source == QString("swapTooltip"))
output = i18n("Swap is used"); output = i18n("Swap is used");
else if (_source == "gpu") else if (source == QString("gpu"))
output = i18n("High GPU load"); output = i18n("High GPU load");
return output; return output;
} }
QString AWDataAggregator::notificationText(const QString &_source, const QString &_value) QString AWDataAggregator::notificationText(const QString source,
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 == "netdev") if (source == QString("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["ac"].toString() == m_configuration["acOnline"], "batTooltip", _values["bat"].toDouble()); setData(values[QString("ac")].toString()
== configuration[QString("acOnline")],
QString("batTooltip"), values[QString("bat")].toFloat());
// usual case // usual case
setData("cpuTooltip", _values["cpu"].toDouble(), 90.0); setData(QString("cpuTooltip"), values[QString("cpu")].toFloat(), 90.0);
setData("cpuclTooltip", _values["cpucl"].toDouble()); setData(QString("cpuclTooltip"), values[QString("cpucl")].toFloat());
setData("memTooltip", _values["mem"].toDouble(), 80.0); setData(QString("memTooltip"), values[QString("mem")].toFloat(), 80.0);
setData("swapTooltip", _values["swap"].toDouble(), 0.0); setData(QString("swapTooltip"), values[QString("swap")].toFloat(), 0.0);
setData("downkbTooltip", _values["downkb"].toDouble()); setData(QString("downkbTooltip"), values[QString("downkb")].toFloat());
setData("upkbTooltip", _values["upkb"].toDouble()); setData(QString("upkbTooltip"), values[QString("upkb")].toFloat());
// additional check for network device // additional check for network device
auto currentNetworkDevice = _values["netdev"].toString(); [this](const QString value) {
checkValue("netdev", m_currentNetworkDevice, currentNetworkDevice); checkValue(QString("netdev"), currentNetworkDevice, value);
m_currentNetworkDevice = currentNetworkDevice; currentNetworkDevice = value;
}(values[QString("netdev")].toString());
// additional check for GPU load // additional check for GPU load
checkValue("gpu", _values["gpu"].toDouble(), 90.0); [this](const float value) {
checkValue(QString("gpu"), value, 90.0);
currentGPULoad = value;
}(values[QString("gpu")].toFloat());
} }
void AWDataAggregator::setData(const QString &_source, double _value, const double _extremum) void AWDataAggregator::setData(const QString &source, float value,
const float extremum)
{ {
qCDebug(LOG_AW) << "Source" << _source << "to value" << _value << "with extremum" << _extremum; qCDebug(LOG_AW) << "Source" << source << "to value" << value
<< "with extremum" << extremum;
if (m_values[_source].count() == 0) if (data[source].count() == 0)
m_values[_source].append(0.0); data[source].append(0.0);
else if (m_values[_source].count() > m_configuration["tooltipNumber"].toInt()) else if (data[source].count()
m_values[_source].removeFirst(); > configuration[QString("tooltipNumber")].toInt())
if (std::isnan(_value)) data[source].removeFirst();
_value = 0.0; if (std::isnan(value))
value = 0.0;
// notifications // notifications
checkValue(_source, _value, _extremum); checkValue(source, value, extremum);
m_values[_source].append(_value); data[source].append(value);
if (_source == "downkbTooltip") { if (source == QString("downkbTooltip")) {
// to avoid copying of objects to another list we find max elements in each sequence and compare them QList<float> netValues
auto downMax = m_values["downkbTooltip"].empty() = data[QString("downkbTooltip")] + data[QString("upkbTooltip")];
? 1.0 // to avoid inf value of normY
: *std::max_element(m_values["downkbTooltip"].cbegin(), m_values["downkbTooltip"].cend()); netValues << 1.0;
auto upMax = m_values["upkbTooltip"].empty() boundaries[QString("downkbTooltip")]
? 1.0 = 1.2f * *std::max_element(netValues.cbegin(), netValues.cend());
: *std::max_element(m_values["upkbTooltip"].cbegin(), m_values["upkbTooltip"].cend()); boundaries[QString("upkbTooltip")]
// assign both = boundaries[QString("downkbTooltip")];
m_boundaries["upkbTooltip"] = m_boundaries["downkbTooltip"] = 1.2 * std::max(downMax, upMax);
} }
} }
void AWDataAggregator::setData(const bool _dontInvert, const QString &_source, double _value) void AWDataAggregator::setData(const bool dontInvert, const QString &source,
float value)
{ {
qCDebug(LOG_AW) << "Do not invert" << _dontInvert << "value" << _value << "for source" << _source; qCDebug(LOG_AW) << "Do not invert" << dontInvert << "value" << value
<< "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

@ -15,52 +15,65 @@
* 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 AWTOOLTIP_H
#define AWTOOLTIP_H
#include <QObject>
#include <QVariant> #include <QVariant>
class QGraphicsScene; class QGraphicsScene;
class QGraphicsView; class QGraphicsView;
class QPixmap; class QPixmap;
class QThreadPool;
class AWDataAggregator : public QObject class AWDataAggregator : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AWDataAggregator(QObject *_parent = nullptr); explicit AWDataAggregator(QObject *parent = nullptr);
~AWDataAggregator() override; virtual ~AWDataAggregator();
static QString htmlImage(const QPixmap &_source); QList<float> getData(const QString key) const;
void setParameters(const QVariantMap &_settings); QString htmlImage(const QPixmap &source) const;
void setParameters(QVariantMap settings);
QPixmap tooltipImage(); QPixmap tooltipImage();
public slots:
void dataUpdate(const QVariantHash &_values);
signals: signals:
void toolTipPainted(const QString &_image) const; void updateData(const QVariantHash &values);
void toolTipPainted(const QString image) const;
private slots:
void dataUpdate(const QVariantHash &values);
private: private:
// ui // ui
QGraphicsScene *m_toolTipScene = nullptr; QGraphicsScene *toolTipScene = nullptr;
QGraphicsView *m_toolTipView = nullptr; QGraphicsView *toolTipView = nullptr;
void checkValue(const QString &_source, double _value, double _extremum) const; void checkValue(const QString source, const float value,
void checkValue(const QString &_source, const QString &_current, const QString &_received) const; const float extremum) const;
void checkValue(const QString source, const QString current,
const QString received) const;
void initScene(); void initScene();
static QString notificationText(const QString &_source, float _value); QString notificationText(const QString source, const float value) const;
static QString notificationText(const QString &_source, const QString &_value); QString notificationText(const QString source, const QString value) const;
// main method // main method
void setData(const QVariantHash &_values); void setData(const QVariantHash &values);
void setData(const QString &_source, double _value, double _extremum = -1.0); void setData(const QString &source, float value,
const float extremum = -1.0f);
// different signature for battery device // different signature for battery device
void setData(bool _dontInvert, const QString &_source, double _value); void setData(const bool dontInvert, const QString &source, float value);
// variables // variables
int m_counts = 0; int counts = 0;
QVariantHash m_configuration; QVariantHash configuration;
QString m_currentNetworkDevice = "lo"; float currentGPULoad = 0.0;
QHash<QString, double> m_boundaries; QString currentNetworkDevice = QString("lo");
QHash<QString, QList<double>> m_values; QHash<QString, float> boundaries;
QHash<QString, QList<float>> data;
bool m_enablePopup = false; bool m_enablePopup = false;
QStringList m_requiredKeys; QStringList requiredKeys;
}; };
#endif /* AWTOOLTIP_H */

View File

@ -17,35 +17,14 @@
#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();
} }
@ -53,103 +32,70 @@ AWDataEngineAggregator::~AWDataEngineAggregator()
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
disconnectSources(); clear();
m_interface->deleteLater();
} }
void AWDataEngineAggregator::connectSources() void AWDataEngineAggregator::clear()
{ {
auto keys = m_sensors.keys(); // disconnect sources first
auto newKeys = QSet(keys.cbegin(), keys.cend()) - m_subscribed; disconnectSources();
m_dataEngines.clear();
m_interface->subscribe(newKeys.values()).waitForFinished(); delete m_consumer;
m_subscribed.unite(newKeys);
} }
void AWDataEngineAggregator::disconnectSources() void AWDataEngineAggregator::disconnectSources()
{ {
m_interface->unsubscribe(m_subscribed.values()).waitForFinished(); for (auto dataengine : m_dataEngines.values())
m_subscribed.clear(); for (auto source : dataengine->sources())
dataengine->disconnectSource(source, parent());
} }
bool AWDataEngineAggregator::isValidSensor(const KSysGuard::SensorInfo &_sensor) void AWDataEngineAggregator::initDataEngines(const int interval)
{ {
return _sensor.unit != KSysGuard::UnitInvalid; qCDebug(LOG_AW) << "Init dataengines with interval" << interval;
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::loadSources() void AWDataEngineAggregator::dropSource(const QString source)
{ {
auto response = m_interface->allSensors(); qCDebug(LOG_AW) << "Source" << source;
response.waitForFinished();
auto sensors = response.value(); // HACK there is no possibility to check to which dataengine source
updateSensors(sensors); // connected we will try to disconnect it from systemmonitor and extsysmon
connectSources(); m_dataEngines[QString("systemmonitor")]->disconnectSource(source, parent());
m_dataEngines[QString("extsysmon")]->disconnectSource(source, parent());
for (auto &sensor : m_sensors.keys()) m_dataEngines[QString("time")]->disconnectSource(source, parent());
emit(deviceAdded(sensor));
} }
void AWDataEngineAggregator::dropSource(const QString &_source) void AWDataEngineAggregator::reconnectSources(const int interval)
{ {
qCDebug(LOG_AW) << "Disconnect sensor" << _source; qCDebug(LOG_AW) << "Reconnect sources with interval" << interval;
if (m_subscribed.contains(_source)) { m_dataEngines[QString("systemmonitor")]->connectAllSources(parent(),
m_interface->unsubscribe({_source}).waitForFinished(); interval);
m_subscribed.remove(_source); m_dataEngines[QString("extsysmon")]->connectAllSources(parent(), interval);
} 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);
}
// notify about new device
emit(deviceAdded(_sensor));
}
void AWDataEngineAggregator::sensorRemoved(const QString &_sensor)
{
qCDebug(LOG_AW) << "Sensor" << _sensor << "has been removed";
m_sensors.remove(_sensor);
dropSource(_sensor);
}
void AWDataEngineAggregator::updateData(const KSysGuard::SensorDataList &_data)
{
emit(dataUpdated(m_sensors, _data));
}
void AWDataEngineAggregator::updateSensors(const QHash<QString, KSysGuard::SensorInfo> &_sensors)
{
for (auto [source, sensor] : _sensors.asKeyValueRange()) {
if (!isValidSensor(sensor))
continue;
m_sensors.insert(source, sensor);
}
} }

View File

@ -15,45 +15,38 @@
* 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
#include <ksysguard/systemstats/SensorInfo.h> #ifndef AWDATAENGINEAGGREGATOR_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);
~AWDataEngineAggregator() override; virtual ~AWDataEngineAggregator();
void connectSources(); void clear();
void disconnectSources(); void disconnectSources();
[[nodiscard]] static bool isValidSensor(const KSysGuard::SensorInfo &_sensor); void initDataEngines(const int interval);
void loadSources();
signals: signals:
void dataUpdated(const QHash<QString, KSysGuard::SensorInfo> &_sensors, const KSysGuard::SensorDataList &_data); void deviceAdded(const QString &source);
void deviceAdded(const QString &_source);
public slots: public slots:
void dropSource(const QString &_source); void dropSource(const QString source);
void sensorAdded(const QString &_sensor); void reconnectSources(const int interval);
void sensorRemoved(const QString &_sensor);
void updateData(const KSysGuard::SensorDataList &_data);
void updateSensors(const QHash<QString, KSysGuard::SensorInfo> &_sensors);
private: private:
KSysGuard::SystemStats::DBusInterface *m_interface = nullptr; Plasma::DataEngineConsumer *m_consumer = nullptr;
QHash<QString, KSysGuard::SensorInfo> m_sensors; QHash<QString, Plasma::DataEngine *> m_dataEngines;
QSet<QString> m_subscribed;
}; };
#endif /* AWDATAENGINEAGGREGATOR_H */

View File

@ -1,112 +0,0 @@
/***************************************************************************
* 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"
#include "formatters/formatters.h"
#include "matchers/matchers.h"
AWDataEngineMapper::AWDataEngineMapper(QObject *_parent, AWFormatterHelper *_custom)
: QObject(_parent)
, m_customFormatters(_custom)
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
// default formatters
// network
m_formatter["down"] = AWPluginFormatterNet::instance();
m_formatter["downkb"] = AWPluginFormatterMemory::instance();
m_formatter["downtot"] = AWPluginFormatterMemoryMB::instance();
m_formatter["downtotkb"] = AWPluginFormatterMemory::instance();
m_formatter["downunits"] = AWPluginFormatterNetUnits::instance();
m_formatter["up"] = AWPluginFormatterNet::instance();
m_formatter["upkb"] = AWPluginFormatterMemory::instance();
m_formatter["uptot"] = AWPluginFormatterMemoryMB::instance();
m_formatter["uptotkb"] = AWPluginFormatterMemory::instance();
m_formatter["upunits"] = AWPluginFormatterNetUnits::instance();
}
AWPluginFormaterInterface *AWDataEngineMapper::formatter(const QString &_key) const
{
qCDebug(LOG_AW) << "Get formatter for key" << _key;
return m_formatter.value(_key, AWPluginFormatterNoFormat::instance());
}
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;
auto matchers = AWPluginMatchers::matchers;
auto matcher = std::find_if(matchers.cbegin(), matchers.cend(),
[&_source](auto matcher) { return matcher->matches(_source); });
if (matcher == matchers.cend())
return {};
auto foundKeys = (*matcher)->keys(_source, _units, m_settings);
auto keys = foundKeys.keys(); // speedup a little bit
// rewrite formatters for custom ones
QStringList customFormattersKeys;
if (m_customFormatters)
customFormattersKeys = m_customFormatters->definedFormatters();
qCInfo(LOG_AW) << "Looking for formatters" << keys << "in" << customFormattersKeys;
for (auto &key : keys) {
if (!customFormattersKeys.contains(key))
continue;
foundKeys[key] = AWPluginFormatterCustom::instance();
}
// check if keys were actually requested
qCInfo(LOG_AW) << "Looking for keys" << keys << "in" << _keys;
auto required = _keys.isEmpty()
|| std::any_of(keys.cbegin(), keys.cend(), [&_keys](auto &key) { return _keys.contains(key); });
if (!required)
return {};
// insert keys into memory
for (auto [key, formatter] : foundKeys.asKeyValueRange()) {
m_map.insert(_source, key);
m_formatter[key] = formatter;
}
return keys;
}
void AWDataEngineMapper::setDevices(const AWPluginMatcherSettings &_settings)
{
m_settings = _settings;
}

View File

@ -1,52 +0,0 @@
/***************************************************************************
* 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/ *
***************************************************************************/
#pragma once
#include <ksysguard/formatter/Unit.h>
#include <QMultiHash>
#include <QObject>
#include "formatters/awpluginformatter.h"
#include "matchers/awpluginmatchersettings.h"
class AWFormatterHelper;
class AWDataEngineMapper : public QObject
{
Q_OBJECT
public:
explicit AWDataEngineMapper(QObject *_parent = nullptr, AWFormatterHelper *_custom = nullptr);
~AWDataEngineMapper() override = default;
// get methods
[[nodiscard]] AWPluginFormaterInterface *formatter(const QString &_key) const;
[[nodiscard]] QStringList keysFromSource(const QString &_source) const;
// set methods
QStringList registerSource(const QString &_source, KSysGuard::Unit _units, const QStringList &_keys);
void setDevices(const AWPluginMatcherSettings &_settings);
private:
AWFormatterHelper *m_customFormatters = nullptr;
AWPluginMatcherSettings m_settings;
// variables
QHash<QString, QStringList> m_devices;
QHash<QString, AWPluginFormaterInterface *> m_formatter;
QMultiHash<QString, QString> m_map;
};

View File

@ -1,101 +0,0 @@
/***************************************************************************
* 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__;
}
QStringList AWDBusAdaptor::ActiveServices()
{
auto listServices = QDBusConnection::sessionBus().interface()->call(QDBus::BlockWithGui, "ListNames");
if (listServices.arguments().isEmpty()) {
qCWarning(LOG_DBUS) << "Could not find any DBus service";
return {};
}
auto arguments = listServices.arguments().first().toStringList();
return std::accumulate(arguments.cbegin(), arguments.cend(), QStringList(), [](auto source, auto &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;
}
auto state = enabled ? "true" : "false";
QLoggingCategory::setFilterRules(QString("%1.%2=%3").arg(what, level, state));
}

View File

@ -1,50 +0,0 @@
/***************************************************************************
* 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/ *
***************************************************************************/
#pragma once
#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 = default;
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"};
};

View File

@ -20,11 +20,9 @@
#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)
@ -32,9 +30,8 @@ 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<AWPairConfigFactory>(uri, 1, 0, "AWPairConfigFactory"); qmlRegisterType<AWFormatterConfigFactory>(uri, 1, 0,
"AWFormatterConfigFactory");
qmlRegisterType<AWKeys>(uri, 1, 0, "AWKeys"); qmlRegisterType<AWKeys>(uri, 1, 0, "AWKeys");
qmlRegisterType<AWTelemetryHandler>(uri, 1, 0, "AWTelemetryHandler");
} }

View File

@ -15,7 +15,9 @@
* 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 AWPLUGIN_H
#define AWPLUGIN_H
#include <QQmlExtensionPlugin> #include <QQmlExtensionPlugin>
@ -26,5 +28,8 @@ 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) override; void registerTypes(const char *uri);
}; };
#endif /* AWPLUGIN_H */

View File

@ -16,16 +16,166 @@
***************************************************************************/ ***************************************************************************/
#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)
: AWAbstractPairConfig(_parent, true, _keys) : QDialog(parent)
, ui(new Ui::AWFormatterConfig)
, m_keys(keys)
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
setEditable(false, false); ui->setupUi(this);
setHelper(std::make_unique<AWFormatterHelper>()); editButton
= 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(editButton, SIGNAL(clicked(bool)), this, SLOT(editFormatters()));
}
AWFormatterConfig::~AWFormatterConfig()
{
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

@ -15,16 +15,50 @@
* 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
#include "awabstractpairconfig.h" #ifndef AWFORMATTERCONFIG_H
#define AWFORMATTERCONFIG_H
#include <QDialog>
class AWFormatterConfig : public AWAbstractPairConfig class AWAbstractSelector;
class AWFormatterHelper;
namespace Ui
{
class AWFormatterConfig;
}
class AWFormatterConfig : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AWFormatterConfig(QWidget *_parent = nullptr, const QStringList &_keys = QStringList()); explicit AWFormatterConfig(QWidget *parent = nullptr,
~AWFormatterConfig() override = default; const QStringList keys = QStringList());
virtual ~AWFormatterConfig();
Q_INVOKABLE void showDialog();
private slots:
void editFormatters();
void updateUi();
private:
QPushButton *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();
}; };
#endif /* AWFORMATTERCONFIG_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>AWAbstractPairConfig</class> <class>AWFormatterConfig</class>
<widget class="QDialog" name="AWAbstractPairConfig"> <widget class="QDialog" name="AWFormatterConfig">
<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>AWAbstractPairConfig</receiver> <receiver>AWFormatterConfig</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>AWAbstractPairConfig</receiver> <receiver>AWFormatterConfig</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -15,31 +15,28 @@
* 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 "awpairconfigfactory.h" #include "awformatterconfigfactory.h"
#include "awcustomkeysconfig.h"
#include "awdebug.h" #include "awdebug.h"
#include "awformatterconfig.h" #include "awformatterconfig.h"
AWPairConfigFactory::AWPairConfigFactory(QObject *_parent) AWFormatterConfigFactory::AWFormatterConfigFactory(QObject *parent)
: QObject(_parent) : QObject(parent)
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
} }
void AWPairConfigFactory::showFormatterDialog(const QStringList &_keys) AWFormatterConfigFactory::~AWFormatterConfigFactory()
{ {
auto config = new AWFormatterConfig(nullptr, _keys); qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
config->showDialog();
config->deleteLater();
} }
void AWPairConfigFactory::showKeysDialog(const QStringList &_keys) void AWFormatterConfigFactory::showDialog(const QStringList keys)
{ {
auto config = new AWCustomKeysConfig(nullptr, _keys); AWFormatterConfig *config = new AWFormatterConfig(nullptr, keys);
config->showDialog(); config->showDialog();
config->deleteLater(); config->deleteLater();
} }

View File

@ -15,20 +15,24 @@
* 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 AWFORMATTERCONFIGFACTORY_H
#define AWFORMATTERCONFIGFACTORY_H
#include <QObject> #include <QObject>
#include "abstractextsysmonsource.h"
class AWFormatterConfigFactory : public QObject
class TimeSource : public AbstractExtSysMonSource
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit TimeSource(QObject *_parent); explicit AWFormatterConfigFactory(QObject *parent = nullptr);
~TimeSource() override = default; virtual ~AWFormatterConfigFactory();
[[nodiscard]] QVariant data(const QString &_source) override; Q_INVOKABLE void showDialog(const QStringList keys);
[[nodiscard]] QHash<QString, KSysGuard::SensorInfo *> sources() const override;
private:
}; };
#endif /* AWFORMATTERCONFIGFACTORY_H */

View File

@ -26,20 +26,18 @@
#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(QObject *_parent) AWFormatterHelper::AWFormatterHelper(QWidget *parent)
: AbstractExtItemAggregator(_parent, "formatters") : AbstractExtItemAggregator(parent, QString("formatters"))
, AWAbstractPairHelper("awesomewidgets/formatters/formatters.ini", "Formatters")
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
AWFormatterHelper::initItems(); initItems();
} }
@ -52,28 +50,13 @@ AWFormatterHelper::~AWFormatterHelper()
} }
void AWFormatterHelper::initItems() QString AWFormatterHelper::convert(const QVariant &value,
const QString &name) const
{ {
initFormatters(); qCDebug(LOG_AW) << "Convert value" << value << "for" << name;
// assign internal storage return m_formatters.contains(name) ? m_formatters[name]->convert(value)
m_formatters.clear(); : value.toString();
for (auto [key, name] : pairs().asKeyValueRange()) {
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();
} }
@ -83,6 +66,16 @@ 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;
@ -93,52 +86,88 @@ QList<AbstractExtItem *> AWFormatterHelper::items() const
} }
void AWFormatterHelper::editPairs() QStringList AWFormatterHelper::knownFormatters() const
{
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()
{ {
auto ret = exec(); repaintList();
int ret = exec();
qCInfo(LOG_AW) << "Dialog returns" << ret; qCInfo(LOG_AW) << "Dialog returns" << ret;
} }
AWAbstractFormatter::FormatterClass AWFormatterHelper::defineFormatterClass(const QString &_stringType) AWAbstractFormatter::FormatterClass
AWFormatterHelper::defineFormatterClass(const QString stringType) const
{ {
qCDebug(LOG_AW) << "Define formatter class for" << _stringType; qCDebug(LOG_AW) << "Define formatter class for" << stringType;
auto formatter = AWAbstractFormatter::FormatterClass::NoFormat; AWAbstractFormatter::FormatterClass formatter
if (_stringType == "DateTime") = AWAbstractFormatter::FormatterClass::NoFormat;
if (stringType == QString("DateTime"))
formatter = AWAbstractFormatter::FormatterClass::DateTime; formatter = AWAbstractFormatter::FormatterClass::DateTime;
else if (_stringType == "Float") else if (stringType == QString("Float"))
formatter = AWAbstractFormatter::FormatterClass::Float; formatter = AWAbstractFormatter::FormatterClass::Float;
else if (_stringType == "List") else if (stringType == QString("List"))
formatter = AWAbstractFormatter::FormatterClass::List; formatter = AWAbstractFormatter::FormatterClass::List;
else if (_stringType == "NoFormat") else if (stringType == QString("NoFormat"))
; ;
else if (_stringType == "Script") else if (stringType == QString("Script"))
formatter = AWAbstractFormatter::FormatterClass::Script; formatter = AWAbstractFormatter::FormatterClass::Script;
else if (_stringType == "String") else if (stringType == QString("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;
} }
@ -148,43 +177,44 @@ void AWFormatterHelper::initFormatters()
{ {
m_formattersClasses.clear(); m_formattersClasses.clear();
auto dirs = directories(); for (int i = m_directories.count() - 1; i >= 0; i--) {
for (auto &dir : dirs) { QStringList files
auto files = QDir(dir).entryList(QDir::Files, QDir::Name); = QDir(m_directories.at(i)).entryList(QDir::Files, QDir::Name);
for (auto &file : files) { for (auto file : files) {
// check filename if (!file.endsWith(QString(".desktop")))
if (!file.endsWith(".desktop"))
continue; continue;
qCInfo(LOG_AW) << "Found file" << file << "in" << dir; qCInfo(LOG_AW) << "Found file" << file << "in"
auto filePath = QString("%1/%2").arg(dir, file); << m_directories.at(i);
// check if already exists QString filePath
auto values = m_formattersClasses.values(); = QString("%1/%2").arg(m_directories.at(i)).arg(file);
if (std::any_of(values.cbegin(), values.cend(), auto metadata = readMetadata(filePath);
[&filePath](auto item) { return (item->filePath() == filePath); })) QString name = metadata.first;
if (m_formattersClasses.contains(name))
continue; continue;
auto metadata = readMetadata(filePath);
switch (metadata.second) { switch (metadata.second) {
case AWAbstractFormatter::FormatterClass::DateTime: case AWAbstractFormatter::FormatterClass::DateTime:
m_formattersClasses[metadata.first] = new AWDateTimeFormatter(this, filePath); m_formattersClasses[name]
= new AWDateTimeFormatter(this, filePath);
break; break;
case AWAbstractFormatter::FormatterClass::Float: case AWAbstractFormatter::FormatterClass::Float:
m_formattersClasses[metadata.first] = new AWFloatFormatter(this, filePath); m_formattersClasses[name]
= new AWFloatFormatter(this, filePath);
break; break;
case AWAbstractFormatter::FormatterClass::List: case AWAbstractFormatter::FormatterClass::List:
m_formattersClasses[metadata.first] = new AWListFormatter(this, filePath); m_formattersClasses[name] = new AWListFormatter(this, filePath);
break; break;
case AWAbstractFormatter::FormatterClass::Script: case AWAbstractFormatter::FormatterClass::Script:
m_formattersClasses[metadata.first] = new AWScriptFormatter(this, filePath); m_formattersClasses[name]
= new AWScriptFormatter(this, filePath);
break; break;
case AWAbstractFormatter::FormatterClass::String: case AWAbstractFormatter::FormatterClass::String:
m_formattersClasses[metadata.first] = new AWStringFormatter(this, filePath); m_formattersClasses[name]
break; = new AWStringFormatter(this, filePath);
case AWAbstractFormatter::FormatterClass::Json:
m_formattersClasses[metadata.first] = new AWJsonFormatter(this, filePath);
break; break;
case AWAbstractFormatter::FormatterClass::NoFormat: case AWAbstractFormatter::FormatterClass::NoFormat:
m_formattersClasses[metadata.first] = new AWNoFormatter(this, filePath); m_formattersClasses[name] = new AWNoFormatter(this, filePath);
break; break;
} }
} }
@ -192,48 +222,110 @@ void AWFormatterHelper::initFormatters()
} }
QPair<QString, AWAbstractFormatter::FormatterClass> AWFormatterHelper::readMetadata(const QString &_filePath) void AWFormatterHelper::initKeys()
{ {
qCDebug(LOG_AW) << "Read initial parameters from" << _filePath; m_formatters.clear();
QSettings settings(_filePath, QSettings::IniFormat); QStringList configs = QStandardPaths::locateAll(
QStandardPaths::GenericDataLocation,
QString("awesomewidgets/formatters/formatters.ini"));
settings.beginGroup("Desktop Entry"); for (auto fileName : configs) {
auto name = settings.value("Name", _filePath).toString(); QSettings settings(fileName, QSettings::IniFormat);
auto type = settings.value("X-AW-Type", "NoFormat").toString(); qCInfo(LOG_AW) << "Configuration file" << settings.fileName();
auto formatter = defineFormatterClass(type);
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(); settings.endGroup();
}
return {name, formatter};
} }
void AWFormatterHelper::doCreateItem(QListWidget *_widget) void AWFormatterHelper::installDirectories()
{ {
QStringList selection = {"NoFormat", "DateTime", "Float", "List", "Script", "String", "Json"}; // 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();
return QPair<QString, AWAbstractFormatter::FormatterClass>(name, formatter);
}
void AWFormatterHelper::doCreateItem()
{
QStringList selection = QStringList()
<< QString("NoFormat") << QString("DateTime")
<< QString("Float") << QString("List")
<< QString("Script") << QString("String");
bool ok; bool ok;
auto select = QInputDialog::getItem(nullptr, i18n("Select type"), i18n("Type:"), selection, 0, false, &ok); QString select = QInputDialog::getItem(
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;
auto formatter = defineFormatterClass(select); AWAbstractFormatter::FormatterClass formatter
= defineFormatterClass(select);
switch (formatter) { switch (formatter) {
case AWAbstractFormatter::FormatterClass::DateTime: case AWAbstractFormatter::FormatterClass::DateTime:
return createItem<AWDateTimeFormatter>(_widget); return createItem<AWDateTimeFormatter>();
case AWAbstractFormatter::FormatterClass::Float: case AWAbstractFormatter::FormatterClass::Float:
return createItem<AWFloatFormatter>(_widget); return createItem<AWFloatFormatter>();
case AWAbstractFormatter::FormatterClass::List: case AWAbstractFormatter::FormatterClass::List:
return createItem<AWListFormatter>(_widget); return createItem<AWListFormatter>();
case AWAbstractFormatter::FormatterClass::Script: case AWAbstractFormatter::FormatterClass::Script:
return createItem<AWScriptFormatter>(_widget); return createItem<AWScriptFormatter>();
case AWAbstractFormatter::FormatterClass::String: case AWAbstractFormatter::FormatterClass::String:
return createItem<AWStringFormatter>(_widget); return createItem<AWStringFormatter>();
case AWAbstractFormatter::FormatterClass::Json:
return createItem<AWJsonFormatter>(_widget);
case AWAbstractFormatter::FormatterClass::NoFormat: case AWAbstractFormatter::FormatterClass::NoFormat:
return createItem<AWNoFormatter>(_widget); return createItem<AWNoFormatter>();
} }
} }
void AWFormatterHelper::initItems()
{
installDirectories();
initFormatters();
initKeys();
}

View File

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

View File

@ -15,47 +15,66 @@
* 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 <QRegularExpression> #include <QRegExp>
#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;
auto fileName QString fileName = QString("%1/awesomewidgets.ndx")
= QString("%1/awesomewidgets.ndx").arg(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation)); .arg(QStandardPaths::writableLocation(
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 == "net") { if (type == QString("hdd")) {
auto rawInterfaceList = QNetworkInterface::allInterfaces(); QStringList allDevices
for (auto &interface : rawInterfaceList) { = QDir(QString("/dev")).entryList(QDir::System, QDir::Name);
auto device = interface.name(); QStringList devices
= allDevices.filter(QRegExp(QString("^[hms]d[a-z]$")));
for (auto dev : devices) {
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(QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')), device); cache.setValue(
QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')),
device);
}
} else if (type == QString("net")) {
QList<QNetworkInterface> rawInterfaceList
= QNetworkInterface::allInterfaces();
for (auto interface : rawInterfaceList) {
QString device = interface.name();
if (cachedValues.contains(device))
continue;
qCInfo(LOG_AW) << "Found new key" << device << "for type" << type;
cachedValues.append(device);
cache.setValue(
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(QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')), _key); cache.setValue(
QString("%1").arg(cache.allKeys().count(), 3, 10, QChar('0')), key);
} }
cache.endGroup(); cache.endGroup();
@ -64,65 +83,104 @@ bool AWKeyCache::addKeyToCache(const QString &_type, const QString &_key)
} }
QStringList AWKeyCache::getRequiredKeys(const QStringList &_keys, const QStringList &_bars, const QVariantMap &_tooltip, QStringList AWKeyCache::getRequiredKeys(const QStringList &keys,
const QStringList &_userKeys, const QStringList &_allKeys) const QStringList &bars,
const QVariantMap &tooltip,
const QStringList &allKeys)
{ {
qCDebug(LOG_AW) << "Looking for required keys in" << _keys << _bars << "using tooltip settings" << _tooltip; qCDebug(LOG_AW) << "Looking for required keys in" << keys << bars
<< "using tooltip settings" << tooltip;
// initial copy // initial copy
QSet<QString> used(_keys.cbegin(), _keys.cend()); QSet<QString> used = QSet<QString>::fromList(keys);
used.unite(QSet(_bars.cbegin(), _bars.cend())); used.unite(QSet<QString>::fromList(bars));
used.unite(QSet(_userKeys.cbegin(), _userKeys.cend()));
// insert keys from tooltip // insert keys from tooltip
for (auto [key, value] : _tooltip.asKeyValueRange()) { for (auto key : tooltip.keys()) {
if ((key.endsWith("Tooltip")) && value.toBool()) { if ((key.endsWith(QString("Tooltip"))) && (tooltip[key].toBool())) {
auto local = key; key.remove(QString("Tooltip"));
local.remove("Tooltip"); used << key;
used << local;
} }
} }
// insert keys which depend on others, refer to AWKeys::calculateValues() // insert depending keys, refer to AWKeys::calculateValues()
// network keys // hddtotmb*
QStringList netKeys( for (auto key : allKeys.filter(QRegExp(QString("^hddtotmb")))) {
{"up", "upkb", "uptot", "uptotkb", "upunits", "down", "downkb", "downtot", "downtotkb", "downunits"});
for (auto &key : netKeys) {
if (!used.contains(key)) if (!used.contains(key))
continue; continue;
auto filt = _allKeys.filter(QRegularExpression(QString("^%1[0-9]{1,}").arg(key))); key.remove(QString("hddtotmb"));
for (auto &filtered : filt) int index = key.toInt();
used << QString("hddfreemb%1").arg(index)
<< QString("hddmb%1").arg(index);
}
// hddtotgb*
for (auto key : allKeys.filter(QRegExp(QString("^hddtotgb")))) {
if (!used.contains(key))
continue;
key.remove(QString("hddtotgb"));
int index = key.toInt();
used << QString("hddfreegb%1").arg(index)
<< QString("hddgb%1").arg(index);
}
// mem
if (used.contains(QString("mem")))
used << QString("memmb") << QString("memtotmb");
// memtotmb
if (used.contains(QString("memtotmb")))
used << QString("memusedmb") << QString("memfreemb");
// memtotgb
if (used.contains(QString("memtotgb")))
used << QString("memusedgb") << QString("memfreegb");
// swap
if (used.contains(QString("swap")))
used << QString("swapmb") << QString("swaptotmb");
// swaptotmb
if (used.contains(QString("swaptotmb")))
used << QString("swapmb") << QString("swapfreemb");
// memtotgb
if (used.contains(QString("swaptotgb")))
used << QString("swapgb") << QString("swapfreegb");
// network keys
QStringList netKeys(QStringList()
<< QString("up") << QString("upkb")
<< QString("uptotal") << QString("uptotalkb")
<< QString("upunits") << QString("down")
<< QString("downkb") << QString("downtotal")
<< QString("downtotalkb") << QString("downunits"));
for (auto key : netKeys) {
if (!used.contains(key))
continue;
QStringList filt
= allKeys.filter(QRegExp(QString("^%1[0-9]{1,}").arg(key)));
for (auto filtered : filt)
used << filtered; used << filtered;
} }
// netdev key // netdev key
if (std::any_of(netKeys.cbegin(), netKeys.cend(), [&used](auto &key) { return used.contains(key); })) if (std::any_of(netKeys.cbegin(), netKeys.cend(),
used << "netdev"; [&used](const QString &key) { return used.contains(key); }))
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 << "dummy"; used << QString("dummy");
return used.values(); return used.toList();
} }
AWPluginMatcherSettings AWKeyCache::loadKeysFromCache() QHash<QString, QStringList> AWKeyCache::loadKeysFromCache()
{ {
auto fileName QString fileName = QString("%1/awesomewidgets.ndx")
= QString("%1/awesomewidgets.ndx").arg(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation)); .arg(QStandardPaths::writableLocation(
QStandardPaths::GenericCacheLocation));
qCInfo(LOG_AW) << "Cache file" << fileName; qCInfo(LOG_AW) << "Cache file" << fileName;
QSettings cache(fileName, QSettings::IniFormat); QSettings cache(fileName, QSettings::IniFormat);
AWPluginMatcherSettings devices; QHash<QString, QStringList> devices;
QHash<QString, QStringList *> groups = { for (auto group : cache.childGroups()) {
{"disk", &devices.disk}, {"gpu", &devices.gpu}, {"mount", &devices.mount},
{"net", &devices.network}, {"temp", &devices.sensors},
};
for (auto [group, list] : groups.asKeyValueRange()) {
cache.beginGroup(group); cache.beginGroup(group);
for (auto &key : cache.allKeys()) for (auto key : cache.allKeys())
list->append(cache.value(key).toString()); devices[group].append(cache.value(key).toString());
cache.endGroup(); cache.endGroup();
} }

View File

@ -15,18 +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/ *
***************************************************************************/ ***************************************************************************/
#pragma once
#ifndef AWKEYCACHE_H
#define AWKEYCACHE_H
#include <QHash>
#include <QString> #include <QString>
#include <QVariant> #include <QVariant>
#include <matchers/awpluginmatchersettings.h>
namespace AWKeyCache namespace AWKeyCache
{ {
bool addKeyToCache(const QString &_type, const QString &_key = ""); bool addKeyToCache(const QString type, const QString key = QString(""));
QStringList getRequiredKeys(const QStringList &_keys, const QStringList &_bars, const QVariantMap &_tooltip, QStringList getRequiredKeys(const QStringList &keys, const QStringList &bars,
const QStringList &_userKeys, const QStringList &_allKeys); const QVariantMap &tooltip,
AWPluginMatcherSettings loadKeysFromCache(); const QStringList &allKeys);
} // namespace AWKeyCache QHash<QString, QStringList> loadKeysFromCache();
};
#endif /* AWKEYCACHE_H */

View File

@ -18,15 +18,14 @@
#include "awkeyoperations.h" #include "awkeyoperations.h"
#include <QDir> #include <QDir>
#include <QRegularExpression> #include <QJSEngine>
#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"
@ -34,22 +33,35 @@
#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>(this, "desktops");
m_extNetRequest = new ExtItemAggregator<ExtNetworkRequest>(this, "requests");
m_extQuotes = new ExtItemAggregator<ExtQuotes>(this, "quotes");
m_extScripts = new ExtItemAggregator<ExtScript>(this, "scripts");
m_extUpgrade = new ExtItemAggregator<ExtUpgrade>(this, "upgrade");
m_extWeather = new ExtItemAggregator<ExtWeather>(this, "weather");
} }
AWPluginMatcherSettings AWKeyOperations::devices() const AWKeyOperations::~AWKeyOperations()
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
// extensions
delete graphicalItems;
delete extQuotes;
delete extScripts;
delete extUpgrade;
delete extWeather;
}
QStringList AWKeyOperations::devices(const QString type) const
{
qCDebug(LOG_AW) << "Looking for type" << type;
return m_devices[type];
}
QHash<QString, QStringList> AWKeyOperations::devices() const
{ {
return m_devices; return m_devices;
} }
@ -58,7 +70,8 @@ AWPluginMatcherSettings AWKeyOperations::devices() const
void AWKeyOperations::updateCache() void AWKeyOperations::updateCache()
{ {
// update network and hdd list // update network and hdd list
addKeyToCache("net"); addKeyToCache(QString("hdd"));
addKeyToCache(QString("net"));
} }
@ -66,29 +79,30 @@ QStringList AWKeyOperations::dictKeys() const
{ {
QStringList allKeys; QStringList allKeys;
// weather // weather
for (auto item : m_extWeather->activeItems()) { for (int i = extWeather->activeItems().count() - 1; i >= 0; i--) {
allKeys.append(item->tag("weatherId")); allKeys.append(
allKeys.append(item->tag("weather")); extWeather->activeItems().at(i)->tag(QString("weatherId")));
allKeys.append(item->tag("humidity")); allKeys.append(
allKeys.append(item->tag("pressure")); extWeather->activeItems().at(i)->tag(QString("weather")));
allKeys.append(item->tag("temperature")); allKeys.append(
allKeys.append(item->tag("timestamp")); extWeather->activeItems().at(i)->tag(QString("humidity")));
allKeys.append(
extWeather->activeItems().at(i)->tag(QString("pressure")));
allKeys.append(
extWeather->activeItems().at(i)->tag(QString("temperature")));
allKeys.append(
extWeather->activeItems().at(i)->tag(QString("timestamp")));
} }
// cpuclock & cpu // cpuclock & cpu
for (auto i = 0; i < QThread::idealThreadCount(); ++i) { for (int i = QThread::idealThreadCount() - 1; i >= 0; 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 (auto i = 0; i < m_devices.sensors.count(); ++i) for (int i = m_devices[QString("temp")].count() - 1; i >= 0; i--)
allKeys.append(QString("temp%1").arg(i)); allKeys.append(QString("temp%1").arg(i));
// gpu
for (auto i = 0; i < m_devices.gpu.count(); ++i) {
allKeys.append(QString("gpu%1").arg(i));
allKeys.append(QString("gputemp%1").arg(i));
}
// hdd // hdd
for (auto i = 0; i < m_devices.mount.count(); ++i) { for (int i = m_devices[QString("mount")].count() - 1; i >= 0; 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));
@ -98,62 +112,64 @@ QStringList AWKeyOperations::dictKeys() const
allKeys.append(QString("hdd%1").arg(i)); allKeys.append(QString("hdd%1").arg(i));
} }
// hdd speed // hdd speed
for (auto i = 0; i < m_devices.disk.count(); ++i) { for (int i = m_devices[QString("disk")].count() - 1; i >= 0; 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
for (int i = m_devices[QString("hdd")].count() - 1; i >= 0; i--)
allKeys.append(QString("hddtemp%1").arg(i));
// network // network
for (auto i = 0; i < m_devices.network.count(); ++i) { for (int i = m_devices[QString("net")].count() - 1; i >= 0; 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("downtotkb%1").arg(i)); allKeys.append(QString("downtotalkb%1").arg(i));
allKeys.append(QString("downtot%1").arg(i)); allKeys.append(QString("downtotal%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("uptotkb%1").arg(i)); allKeys.append(QString("uptotalkb%1").arg(i));
allKeys.append(QString("uptot%1").arg(i)); allKeys.append(QString("uptotal%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
auto allBatteryDevices = QDir("/sys/class/power_supply") QStringList allBatteryDevices
.entryList(QStringList({"BAT*"}), QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); = QDir(QString("/sys/class/power_supply"))
for (int i = 0; i < allBatteryDevices.count(); ++i) { .entryList(QStringList() << QString("BAT*"),
QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
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 (auto item : m_extUpgrade->activeItems()) for (int i = extUpgrade->activeItems().count() - 1; i >= 0; i--)
allKeys.append(item->tag("pkgcount")); allKeys.append(
extUpgrade->activeItems().at(i)->tag(QString("pkgcount")));
// quotes // quotes
for (auto item : m_extQuotes->activeItems()) { for (int i = extQuotes->activeItems().count() - 1; i >= 0; i--) {
allKeys.append(item->tag("price")); allKeys.append(extQuotes->activeItems().at(i)->tag(QString("ask")));
allKeys.append(item->tag("pricechg")); allKeys.append(extQuotes->activeItems().at(i)->tag(QString("askchg")));
allKeys.append(item->tag("percpricechg")); allKeys.append(
allKeys.append(item->tag("volume")); extQuotes->activeItems().at(i)->tag(QString("percaskchg")));
allKeys.append(item->tag("volumechg")); allKeys.append(extQuotes->activeItems().at(i)->tag(QString("bid")));
allKeys.append(item->tag("percvolumechg")); allKeys.append(extQuotes->activeItems().at(i)->tag(QString("bidchg")));
allKeys.append(
extQuotes->activeItems().at(i)->tag(QString("percbidchg")));
allKeys.append(extQuotes->activeItems().at(i)->tag(QString("price")));
allKeys.append(
extQuotes->activeItems().at(i)->tag(QString("pricechg")));
allKeys.append(
extQuotes->activeItems().at(i)->tag(QString("percpricechg")));
} }
// custom // custom
for (auto item : m_extScripts->activeItems()) for (int i = extScripts->activeItems().count() - 1; i >= 0; i--)
allKeys.append(item->tag("custom")); allKeys.append(extScripts->activeItems().at(i)->tag(QString("custom")));
// network requests
for (auto item : m_extNetRequest->activeItems())
allKeys.append(item->tag("response"));
// bars // bars
for (auto item : m_graphicalItems->activeItems()) for (int i = graphicalItems->activeItems().count() - 1; i >= 0; i--)
allKeys.append(item->tag("bar")); allKeys.append(
// user defined keys graphicalItems->activeItems().at(i)->tag(QString("bar")));
allKeys.append(m_customKeys->keys());
// static keys // static keys
allKeys.append(QString(STATIC_KEYS).split(',')); QStringList staticKeys = QString(STATIC_KEYS).split(QChar(','));
std::for_each(staticKeys.cbegin(), staticKeys.cend(),
// sort in valid order [&allKeys](const QString &key) { allKeys.append(key); });
allKeys.sort();
std::reverse(allKeys.begin(), allKeys.end());
return allKeys; return allKeys;
} }
@ -161,92 +177,66 @@ 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, "bar"); return graphicalItems->itemByTag(key, QString("bar"));
} }
QStringList AWKeyOperations::requiredUserKeys() const QString AWKeyOperations::infoByKey(QString key) const
{ {
return m_customKeys->refinedSources(); qCDebug(LOG_AW) << "Requested key" << key;
}
QString stripped = key;
QStringList AWKeyOperations::userKeys() const stripped.remove(QRegExp(QString("\\d+")));
{
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;
static auto numberRegExp = QRegularExpression("\\d+");
auto stripped = _key;
stripped.remove(numberRegExp);
QString output; QString output;
static auto hddRegExp = QRegularExpression("^hdd(|mb|gb|freemb|freegb|totmb|totgb)"); if (key.startsWith(QString("bar"))) {
static auto hddrwRegExp = QRegularExpression("^hdd[rw]"); AbstractExtItem *item = graphicalItems->itemByTag(key, stripped);
static auto hddMatchRegExp = QRegularExpression("^hdd([0-9]|mb|gb|freemb|freegb|totmb|totgb)");
static auto netRegExp = QRegularExpression("^(down|up)");
static auto netMatchRegExp = QRegularExpression("^(down|up)[0-9]");
static auto quotesRegExp = QRegularExpression("^(|perc)(ask|bid|price)(chg|)");
static auto weatherRegExp = QRegularExpression("^(weather|weatherId|humidity|pressure|temperature)");
if (_key.startsWith("bar")) {
auto item = m_graphicalItems->itemByTag(_key, stripped);
if (item) if (item)
output = item->uniq(); output = item->uniq();
} else if (_key.startsWith("custom")) { } else if (key.startsWith(QString("custom"))) {
auto item = m_extScripts->itemByTag(_key, stripped); AbstractExtItem *item = extScripts->itemByTag(key, stripped);
if (item) if (item)
output = item->uniq(); output = item->uniq();
} else if (_key.contains(hddrwRegExp)) { } else if (key.contains(QRegExp(QString("^hdd[rw]")))) {
auto index = _key; output = m_devices[QString("disk")]
index.remove(hddrwRegExp); [key.remove(QRegExp(QString("hdd[rw]"))).toInt()];
output = m_devices.disk[index.toInt()]; } else if (key.contains(QRegExp(
} else if (_key.contains(hddMatchRegExp)) { QString("^hdd([0-9]|mb|gb|freemb|freegb|totmb|totgb)")))) {
auto index = _key; output
index.remove(hddRegExp); = m_devices[QString("mount")]
output = m_devices.mount[index.toInt()]; [key
} else if (_key.contains(netMatchRegExp)) { .remove(QRegExp(QString(
auto index = _key; "^hdd([0-9]|mb|gb|freemb|freegb|totmb|totgb)")))
index.remove(netRegExp); .toInt()];
output = m_devices.network[index.toInt()]; } else if (key.startsWith(QString("hddtemp"))) {
} else if (_key.startsWith("pkgcount")) { output
auto item = m_extUpgrade->itemByTag(_key, stripped); = m_devices[QString("hdd")][key.remove(QString("hddtemp")).toInt()];
} else if (key.contains(QRegExp(QString("^(down|up)[0-9]")))) {
output = m_devices[QString("net")]
[key.remove(QRegExp(QString("^(down|up)"))).toInt()];
} else if (key.startsWith(QString("pkgcount"))) {
AbstractExtItem *item = extUpgrade->itemByTag(key, stripped);
if (item) if (item)
output = item->uniq(); output = item->uniq();
} else if (_key.contains(quotesRegExp)) { } else if (key.contains(
auto item = m_extQuotes->itemByTag(_key, stripped); QRegExp(QString("(^|perc)(ask|bid|price)(chg|)")))) {
AbstractExtItem *item = extQuotes->itemByTag(key, stripped);
if (item) if (item)
output = item->uniq(); output = item->uniq();
} else if (_key.contains(weatherRegExp)) { } else if (key.contains(QRegExp(QString(
auto item = m_extWeather->itemByTag(_key, stripped); "(weather|weatherId|humidity|pressure|temperature)")))) {
if (item) AbstractExtItem *item = extWeather->itemByTag(key, stripped);
output = item->uniq();
} else if (_key.startsWith("temp")) {
auto index = _key;
index.remove("temp");
output = m_devices.sensors[index.toInt()];
} else if (_key.startsWith("response")) {
auto 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 = "(none)"; output = QString("(none)");
} }
return output; return output;
@ -259,72 +249,63 @@ 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;
static auto supportsGraphicalRegExp = QRegularExpression("^(cpu(?!cl).*|gpu$|mem$|swap$|hdd[0-9].*|bat.*)"); if (type == QString("graphicalitem")) {
QStringList keys = dictKeys().filter(QRegExp(
if (_type == "graphicalitem") { QString("^(cpu(?!cl).*|gpu$|mem$|swap$|hdd[0-9].*|bat.*)")));
auto keys = dictKeys().filter(supportsGraphicalRegExp);
keys.sort(); keys.sort();
m_graphicalItems->setConfigArgs(keys); graphicalItems->setConfigArgs(keys);
return m_graphicalItems->editItems(); return graphicalItems->editItems();
} else if (_type == "extnetworkrequest") { } else if (type == QString("extquotes")) {
return m_extNetRequest->editItems(); return extQuotes->editItems();
} else if (_type == "extquotes") { } else if (type == QString("extscript")) {
return m_extQuotes->editItems(); return extScripts->editItems();
} else if (_type == "extscript") { } else if (type == QString("extupgrade")) {
return m_extScripts->editItems(); return extUpgrade->editItems();
} else if (_type == "extupgrade") { } else if (type == QString("extweather")) {
return m_extUpgrade->editItems(); return extWeather->editItems();
} else if (_type == "extweather") {
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;
static auto diskRegexp = QRegularExpression("^disk/.*/read$"); QRegExp diskRegexp
static auto mountRegexp = QRegularExpression("^disk/.*/usedPercent$"); = QRegExp(QString("disk/(?:md|sd|hd)[a-z|0-9]_.*/Rate/(?:rblk)"));
static auto cpuTempRegExp = QRegularExpression("^cpu/cpu.*/temperature$"); QRegExp mountRegexp = QRegExp(QString("partitions/.*/filllevel"));
static auto gpuRegExp = QRegularExpression("^gpu/gpu.*/usage$");
if (_source.contains(diskRegexp)) { if (source.contains(diskRegexp)) {
auto device = _source; QString device = source;
device.remove("disk/").remove("/read"); device.remove(QString("/Rate/rblk"));
addKeyToCache("disk", device); addKeyToCache(QString("disk"), device);
} else if (_source.contains(mountRegexp)) { } else if (source.contains(mountRegexp)) {
auto device = _source; QString device = source;
device.remove("disk/").remove("/usedPercent"); device.remove(QString("partitions")).remove(QString("/filllevel"));
addKeyToCache("mount", device); addKeyToCache(QString("mount"), device);
} else if (_source.startsWith("lmsensors") || _source.contains(cpuTempRegExp) } else if (source.startsWith(QString("lmsensors"))) {
|| _source == "cpu/all/averageTemperature") { addKeyToCache(QString("temp"), source);
addKeyToCache("temp", _source);
} else if (_source.contains(gpuRegExp)) {
auto device = _source;
device.remove("gpu/").remove("/usage");
addKeyToCache("gpu", device);
} }
} }
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();
} }
@ -333,16 +314,28 @@ void AWKeyOperations::addKeyToCache(const QString &_type, const QString &_key)
void AWKeyOperations::reinitKeys() void AWKeyOperations::reinitKeys()
{ {
m_customKeys->initItems(); // renew extensions
m_graphicalItems->initItems(); // delete them if any
m_extNetRequest->initItems(); delete graphicalItems;
m_extQuotes->initItems(); graphicalItems = nullptr;
m_extScripts->initItems(); delete extQuotes;
m_extUpgrade->initItems(); extQuotes = nullptr;
m_extWeather->initItems(); delete extScripts;
extScripts = nullptr;
delete extUpgrade;
extUpgrade = nullptr;
delete extWeather;
extWeather = nullptr;
// create
graphicalItems
= new ExtItemAggregator<GraphicalItem>(nullptr, QString("desktops"));
extQuotes = new ExtItemAggregator<ExtQuotes>(nullptr, QString("quotes"));
extScripts = new ExtItemAggregator<ExtScript>(nullptr, QString("scripts"));
extUpgrade = new ExtItemAggregator<ExtUpgrade>(nullptr, QString("upgrade"));
extWeather = new ExtItemAggregator<ExtWeather>(nullptr, QString("weather"));
// init // init
auto allKeys = dictKeys(); QStringList allKeys = dictKeys();
// apply aw_* functions // apply aw_* functions
m_pattern = AWPatternFunctions::insertAllKeys(m_pattern, allKeys); m_pattern = AWPatternFunctions::insertAllKeys(m_pattern, allKeys);

View File

@ -15,21 +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/ *
***************************************************************************/ ***************************************************************************/
#pragma once
#ifndef AWKEYOPERATIONS_H
#define AWKEYOPERATIONS_H
#include <Plasma/DataEngine>
#include <QMutex>
#include <QObject> #include <QObject>
#include "extitemaggregator.h" #include "extitemaggregator.h"
#include "matchers/awpluginmatchersettings.h"
class AWCustomKeysHelper; class AWDataAggregator;
class ExtNetworkRequest; class AWDataEngineAggregator;
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
{ {
@ -37,42 +43,41 @@ 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);
~AWKeyOperations() override = default; virtual ~AWKeyOperations();
[[nodiscard]] AWPluginMatcherSettings devices() const; QStringList devices(const QString type) const;
QHash<QString, QStringList> devices() const;
void updateCache(); void updateCache();
// keys // keys
[[nodiscard]] QStringList dictKeys() const; QStringList dictKeys() const;
[[nodiscard]] GraphicalItem *giByKey(const QString &_key) const; GraphicalItem *giByKey(const QString key) const;
[[nodiscard]] QStringList requiredUserKeys() const;
[[nodiscard]] QStringList userKeys() const;
[[nodiscard]] QString userKeySource(const QString &_key) const;
// values // values
[[nodiscard]] QString infoByKey(const QString &_key) const; QString infoByKey(QString key) const;
[[nodiscard]] QString pattern() const; 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 = ""); void addKeyToCache(const QString type, const QString key = QString(""));
void reinitKeys(); void reinitKeys();
// objects // objects
AWCustomKeysHelper *m_customKeys = nullptr; ExtItemAggregator<GraphicalItem> *graphicalItems = nullptr;
ExtItemAggregator<GraphicalItem> *m_graphicalItems = nullptr; ExtItemAggregator<ExtQuotes> *extQuotes = nullptr;
ExtItemAggregator<ExtNetworkRequest> *m_extNetRequest = nullptr; ExtItemAggregator<ExtScript> *extScripts = nullptr;
ExtItemAggregator<ExtQuotes> *m_extQuotes = nullptr; ExtItemAggregator<ExtUpgrade> *extUpgrade = nullptr;
ExtItemAggregator<ExtScript> *m_extScripts = nullptr; ExtItemAggregator<ExtWeather> *extWeather = nullptr;
ExtItemAggregator<ExtUpgrade> *m_extUpgrade = nullptr;
ExtItemAggregator<ExtWeather> *m_extWeather = nullptr;
// variables // variables
AWPluginMatcherSettings m_devices; QHash<QString, QStringList> m_devices;
QString m_pattern; QString m_pattern;
}; };
#endif /* AWKEYOPERATIONS_H */

View File

@ -17,14 +17,14 @@
#include "awkeys.h" #include "awkeys.h"
#include <QDBusConnection> #include <QJSEngine>
#include <QDBusError> #include <QRegExp>
#include <QRegularExpression> #include <QThread>
#include <QTimer> #include <QTimer>
#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,36 +33,37 @@
#include "graphicalitem.h" #include "graphicalitem.h"
AWKeys::AWKeys(QObject *_parent) AWKeys::AWKeys(QObject *parent)
: QObject(_parent) : QObject(parent)
{ {
qSetMessagePattern(AWDebug::LOG_FORMAT); qSetMessagePattern(LOG_FORMAT);
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
for (auto &metadata : AWDebug::getBuildData()) for (auto metadata : getBuildData())
qCDebug(LOG_AW) << metadata; qCDebug(LOG_AW) << metadata;
m_aggregator = new AWKeysAggregator(this); // thread pool
m_dataAggregator = new AWDataAggregator(this); m_threadPool = new QThreadPool(this);
m_dataEngineAggregator = new AWDataEngineAggregator(this);
m_keyOperator = new AWKeyOperations(this); aggregator = new AWKeysAggregator(this);
dataAggregator = new AWDataAggregator(this);
dataEngineAggregator = new AWDataEngineAggregator(this);
keyOperator = new AWKeyOperations(this);
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, &AWKeyOperations::updateKeys, this, &AWKeys::reinitKeys); connect(keyOperator, SIGNAL(updateKeys(QStringList)), this,
connect(m_timer, &QTimer::timeout, this, &AWKeys::updateTextData); SLOT(reinitKeys(QStringList)));
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, &AWDataAggregator::toolTipPainted, connect(dataAggregator, SIGNAL(toolTipPainted(const QString)), this,
[this](const QString &_tooltip) { emit(needToolTipToBeUpdated(_tooltip)); }); SIGNAL(needToolTipToBeUpdated(const QString)));
connect(this, SIGNAL(dropSourceFromDataengine(QString)),
connect(this, &AWKeys::dropSourceFromDataengine, m_dataEngineAggregator, &AWDataEngineAggregator::dropSource); dataEngineAggregator, SLOT(dropSource(QString)));
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, &AWDataEngineAggregator::deviceAdded, m_keyOperator, &AWKeyOperations::addDevice); connect(dataEngineAggregator, SIGNAL(deviceAdded(const QString &)),
keyOperator, SLOT(addDevice(const QString &)));
} }
@ -71,159 +72,177 @@ AWKeys::~AWKeys()
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
m_timer->stop(); m_timer->stop();
// delete dbus session delete m_timer;
auto id = reinterpret_cast<qlonglong>(this);
QDBusConnection::sessionBus().unregisterObject(QString("/%1").arg(id)); // core
delete dataEngineAggregator;
delete m_threadPool;
delete aggregator;
delete dataAggregator;
delete 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); dataAggregator->setParameters(m_tooltipParams);
} }
void AWKeys::initKeys(const QString &_currentPattern, const int _interval, const bool _optimize) void AWKeys::initKeys(const QString currentPattern, const int interval,
const int limit, const bool optimize)
{ {
qCDebug(LOG_AW) << "Pattern" << _currentPattern << "with interval" << _interval << "with optimization" << _optimize; qCDebug(LOG_AW) << "Pattern" << currentPattern << "with interval"
<< interval << "and queue limit" << limit
<< "with optimization" << optimize;
// init // init
m_optimize = _optimize; m_optimize = optimize;
m_threadPool->setMaxThreadCount(limit == 0 ? QThread::idealThreadCount()
: limit);
// child objects // child objects
m_aggregator->initFormatters(); keyOperator->setPattern(currentPattern);
m_keyOperator->setPattern(_currentPattern); keyOperator->updateCache();
m_keyOperator->updateCache(); dataEngineAggregator->clear();
m_dataEngineAggregator->loadSources();
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); 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;
} }
void AWKeys::updateCache() void AWKeys::updateCache()
{ {
return m_keyOperator->updateCache(); return keyOperator->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" << _regexp; qCDebug(LOG_AW) << "Should be sorted" << sorted << "and filter applied"
<< regexp;
// check if functions asked QStringList allKeys = keyOperator->dictKeys();
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();
// sort if required // sort if required
if (_sorted) if (sorted)
allKeys.sort(); allKeys.sort();
return allKeys.filter(QRegularExpression(_regexp)); return allKeys.filter(QRegExp(regexp));
} }
QString AWKeys::infoByKey(const QString &_key) const QStringList AWKeys::getHddDevices() const
{ {
qCDebug(LOG_AW) << "Requested info for key" << _key; QStringList devices = keyOperator->devices(QString("hdd"));
// required by selector in the UI
devices.insert(0, QString("disable"));
devices.insert(0, QString("auto"));
return m_keyOperator->infoByKey(_key); return devices;
}
QString AWKeys::infoByKey(QString key) const
{
qCDebug(LOG_AW) << "Requested info for key" << key;
return 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(const QString &_key) const QString AWKeys::valueByKey(QString key) const
{ {
qCDebug(LOG_AW) << "Requested value for key" << _key; qCDebug(LOG_AW) << "Requested value for key" << key;
auto realKey = _key.startsWith("bar") ? m_keyOperator->infoByKey(_key) : _key; QString trueKey
= key.startsWith(QString("bar")) ? keyOperator->infoByKey(key) : key;
return m_aggregator->formatter(m_values[realKey], realKey, true); return aggregator->formatter(values[trueKey], trueKey);
} }
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 keyOperator->editItem(type);
} }
void AWKeys::dataUpdated(const QHash<QString, KSysGuard::SensorInfo> &_sensors, const KSysGuard::SensorDataList &_data) void AWKeys::dataUpdated(const QString &sourceName,
const Plasma::DataEngine::Data &data)
{ {
qCDebug(LOG_AW) << "Update data for" << _data.count() << "items"; // run concurrent data update
QtConcurrent::run(m_threadPool, this, &AWKeys::setDataBySource, sourceName,
for (auto &data : _data) { data);
if (!_sensors.contains(data.sensorProperty))
continue;
auto sensor = _sensors[data.sensorProperty];
setDataBySource(data.sensorProperty, sensor, data.payload);
}
} }
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(), _currentKeys, true); m_foundBars = AWPatternFunctions::findKeys(keyOperator->pattern(),
m_foundKeys = AWPatternFunctions::findKeys(m_keyOperator->pattern(), _currentKeys, false); currentKeys, true);
m_foundLambdas = AWPatternFunctions::findLambdas(m_keyOperator->pattern()); m_foundKeys = AWPatternFunctions::findKeys(keyOperator->pattern(),
currentKeys, false);
m_foundLambdas = AWPatternFunctions::findLambdas(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) {
auto item = m_keyOperator->giByKey(bar); GraphicalItem *item = keyOperator->giByKey(bar);
if (item->isCustom()) if (item->isCustom())
item->setUsedKeys(AWPatternFunctions::findKeys(item->bar(), _currentKeys, false)); item->setUsedKeys(
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_optimize ? AWKeyCache::getRequiredKeys(m_foundKeys, barKeys, m_tooltipParams, m_requiredKeys
m_keyOperator->requiredUserKeys(), _currentKeys) = m_optimize ? AWKeyCache::getRequiredKeys(m_foundKeys, barKeys,
m_tooltipParams, currentKeys)
: QStringList(); : QStringList();
// set key data to m_aggregator // set key data to aggregator
m_aggregator->setDevices(m_keyOperator->devices()); aggregator->setDevices(keyOperator->devices());
} }
void AWKeys::updateTextData() 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();
calculateValues(); calculateValues();
auto text = parsePattern(m_keyOperator->pattern()); QString text = parsePattern(keyOperator->pattern());
// update tooltip values under lock m_mutex.unlock();
m_dataAggregator->dataUpdate(m_values);
emit(needTextToBeUpdated(text)); emit(needTextToBeUpdated(text));
emit(dataAggregator->updateData(values));
} }
@ -231,99 +250,121 @@ void AWKeys::updateTextData()
// specified pattern. Usually they are values which depend on several others // specified pattern. Usually they are values which depend on several others
void AWKeys::calculateValues() void AWKeys::calculateValues()
{ {
auto devices = m_keyOperator->devices(); // hddtot*
QStringList mountDevices = keyOperator->devices(QString("mount"));
for (auto device : mountDevices) {
int index = mountDevices.indexOf(device);
values[QString("hddtotmb%1").arg(index)]
= values[QString("hddfreemb%1").arg(index)].toFloat()
+ values[QString("hddmb%1").arg(index)].toFloat();
values[QString("hddtotgb%1").arg(index)]
= values[QString("hddfreegb%1").arg(index)].toFloat()
+ values[QString("hddgb%1").arg(index)].toFloat();
}
// memtot*
values[QString("memtotmb")] = values[QString("memusedmb")].toInt()
+ values[QString("memfreemb")].toInt();
values[QString("memtotgb")] = values[QString("memusedgb")].toFloat()
+ values[QString("memfreegb")].toFloat();
// mem
values[QString("mem")] = 100.0f * values[QString("memmb")].toFloat()
/ values[QString("memtotmb")].toFloat();
// up, down, upkb, downkb, upunits, downunits // up, down, upkb, downkb, upunits, downunits
auto netIndex = devices.network.indexOf(m_values["netdev"].toString()); int netIndex = keyOperator->devices(QString("net"))
m_values["down"] = m_values[QString("down%1").arg(netIndex)]; .indexOf(values[QString("netdev")].toString());
m_values["downkb"] = m_values[QString("downkb%1").arg(netIndex)]; values[QString("down")] = values[QString("down%1").arg(netIndex)];
m_values["downtot"] = m_values[QString("downtot%1").arg(netIndex)]; values[QString("downkb")] = values[QString("downkb%1").arg(netIndex)];
m_values["downtotkb"] = m_values[QString("downtotkb%1").arg(netIndex)]; values[QString("downtotal")] = values[QString("downtotal%1").arg(netIndex)];
m_values["downunits"] = m_values[QString("downunits%1").arg(netIndex)]; values[QString("downtotalkb")]
m_values["up"] = m_values[QString("up%1").arg(netIndex)]; = values[QString("downtotalkb%1").arg(netIndex)];
m_values["upkb"] = m_values[QString("upkb%1").arg(netIndex)]; values[QString("downunits")] = values[QString("downunits%1").arg(netIndex)];
m_values["uptot"] = m_values[QString("uptot%1").arg(netIndex)]; values[QString("up")] = values[QString("up%1").arg(netIndex)];
m_values["uptotkb"] = m_values[QString("uptotkb%1").arg(netIndex)]; values[QString("upkb")] = values[QString("upkb%1").arg(netIndex)];
m_values["upunits"] = m_values[QString("upunits%1").arg(netIndex)]; values[QString("uptotal")] = values[QString("uptotal%1").arg(netIndex)];
values[QString("uptotalkb")] = values[QString("uptotalkb%1").arg(netIndex)];
values[QString("upunits")] = values[QString("upunits%1").arg(netIndex)];
// user defined keys // swaptot*
for (auto &key : m_keyOperator->userKeys()) values[QString("swaptotmb")] = values[QString("swapmb")].toInt()
m_values[key] = m_values[m_keyOperator->userKeySource(key)]; + values[QString("swapfreemb")].toInt();
values[QString("swaptotgb")] = values[QString("swapgb")].toFloat()
+ values[QString("swapfreegb")].toFloat();
// swap
values[QString("swap")] = 100.0f * values[QString("swapmb")].toFloat()
/ values[QString("swaptotmb")].toFloat();
// lambdas // lambdas
for (auto &key : m_foundLambdas) for (auto key : m_foundLambdas)
m_values[key] = AWPatternFunctions::expandLambdas(key, m_aggregator, m_values, m_foundKeys); values[key] = AWPatternFunctions::expandLambdas(key, aggregator, values,
m_foundKeys);
} }
void AWKeys::createDBusInterface() QString AWKeys::parsePattern(QString pattern) const
{
// get this object id
auto id = reinterpret_cast<qlonglong>(this);
// create session
auto 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
auto 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("$$", QChar(0x1d)); pattern.replace(QString("$$"), QString(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), values[key].toString());
// main keys // main keys
for (auto &key : m_foundKeys) for (auto key : m_foundKeys)
_pattern.replace(QString("$%1").arg(key), m_aggregator->formatter(m_values[key], key, true)); pattern.replace(QString("$%1").arg(key), [this](const QString &tag,
const QVariant &value) {
QString strValue = aggregator->formatter(value, tag);
if ((!tag.startsWith(QString("custom")))
&& (!tag.startsWith(QString("weather"))))
strValue.replace(QString(" "), QString("&nbsp;"));
return strValue;
}(key, values[key]));
// bars // bars
for (auto &bar : m_foundBars) { for (auto bar : m_foundBars) {
auto item = m_keyOperator->giByKey(bar); GraphicalItem *item = keyOperator->giByKey(bar);
auto image = item->isCustom() ? item->image( QString image
AWPatternFunctions::expandLambdas(item->bar(), m_aggregator, m_values, item->usedKeys())) = item->isCustom()
: item->image(m_values[item->bar()]); ? item->image(AWPatternFunctions::expandLambdas(
_pattern.replace(QString("$%1").arg(bar), image); item->bar(), aggregator, values, item->usedKeys()))
: item->image(values[item->bar()]);
pattern.replace(QString("$%1").arg(bar), image);
} }
// prepare strings // prepare strings
_pattern.replace(QChar(0x1d), "$"); pattern.replace(QString(0x1d), QString("$"));
if (m_wrapNewLines) if (m_wrapNewLines)
_pattern.replace("\n", "<br>"); pattern.replace(QString("\n"), QString("<br>"));
return _pattern; return pattern;
} }
void AWKeys::setDataBySource(const QString &_source, const KSysGuard::SensorInfo &_sensor, const QVariant &_value) void AWKeys::setDataBySource(const QString &sourceName, const QVariantMap &data)
{ {
qCDebug(LOG_AW) << "Source" << _source << _sensor.name << "with data" << _value; qCDebug(LOG_AW) << "Source" << sourceName << "with data" << data;
// first list init // first list init
auto tags = m_aggregator->keysFromSource(_source); QStringList tags = aggregator->keysFromSource(sourceName);
if (tags.isEmpty()) if (tags.isEmpty())
tags = m_aggregator->registerSource(_source, _sensor.unit, m_requiredKeys); tags = aggregator->registerSource(
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) << "Sensor" << _source << "not found"; qCInfo(LOG_AW) << "Source" << sourceName << "not found";
return emit(dropSourceFromDataengine(_source)); return emit(dropSourceFromDataengine(sourceName));
} }
std::for_each(tags.cbegin(), tags.cend(), [this, _value](const QString &tag) { m_values[tag] = _value; }); m_mutex.lock();
// HACK workaround for time values which are stored in the different path
std::for_each(tags.cbegin(), tags.cend(),
[this, &data, &sourceName](const QString &tag) {
values[tag] = sourceName == QString("Local")
? data[QString("DateTime")]
: data[QString("value")];
});
m_mutex.unlock();
} }

View File

@ -15,67 +15,85 @@
* 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 AWKEYS_H
#define AWKEYS_H
#include <Plasma/DataEngine>
#include <QMutex>
#include <QObject> #include <QObject>
#include <ksysguard/systemstats/SensorInfo.h>
class AWDataAggregator; class AWDataAggregator;
class AWDataEngineAggregator; class AWDataEngineAggregator;
class AWKeyOperations; class AWKeyOperations;
class AWKeysAggregator; class AWKeysAggregator;
class QThreadPool;
class QTimer; class QTimer;
class __attribute__((visibility("default"))) AWKeys : public QObject class AWKeys : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AWKeys(QObject *_parent = nullptr); explicit AWKeys(QObject *parent = nullptr);
~AWKeys() override; virtual ~AWKeys();
Q_INVOKABLE void initDataAggregator(const QVariantMap &_tooltipParams); Q_INVOKABLE void initDataAggregator(const QVariantMap tooltipParams);
Q_INVOKABLE void initKeys(const QString &_currentPattern, int _interval, bool _optimize); Q_INVOKABLE void initKeys(const QString currentPattern, const int interval,
Q_INVOKABLE void setAggregatorProperty(const QString &_key, const QVariant &_value); const int limit, const bool optimize);
Q_INVOKABLE void setWrapNewLines(bool _wrap); Q_INVOKABLE void setAggregatorProperty(const QString key,
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 [[nodiscard]] QStringList dictKeys(bool _sorted = false, const QString &_regexp = "") const; Q_INVOKABLE QStringList dictKeys(const bool sorted = false,
const QString regexp = QString()) const;
Q_INVOKABLE QStringList getHddDevices() const;
// values // values
Q_INVOKABLE [[nodiscard]] QString infoByKey(const QString &_key) const; Q_INVOKABLE QString infoByKey(QString key) const;
Q_INVOKABLE [[nodiscard]] QString valueByKey(const QString &_key) const; Q_INVOKABLE QString valueByKey(QString key) const;
// configuration // configuration
Q_INVOKABLE void editItem(const QString &_type); Q_INVOKABLE void editItem(const QString type);
public slots:
void dataUpdated(const QString &sourceName,
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 dataUpdated(const QHash<QString, KSysGuard::SensorInfo> &_sensors, const KSysGuard::SensorDataList &_data); void reinitKeys(const QStringList currentKeys);
void reinitKeys(const QStringList &_currentKeys);
void updateTextData(); void updateTextData();
private: private:
// methods // methods
void calculateValues(); void calculateValues();
void createDBusInterface(); QString parsePattern(QString pattern) const;
[[nodiscard]] QString parsePattern(QString _pattern) const; void setDataBySource(const QString &sourceName, const QVariantMap &data);
void setDataBySource(const QString &_source, const KSysGuard::SensorInfo &_sensor, const QVariant &_value);
// objects // objects
AWDataAggregator *m_dataAggregator = nullptr; AWDataAggregator *dataAggregator = nullptr;
AWDataEngineAggregator *m_dataEngineAggregator = nullptr; AWDataEngineAggregator *dataEngineAggregator = nullptr;
AWKeysAggregator *m_aggregator = nullptr; AWKeysAggregator *aggregator = nullptr;
AWKeyOperations *m_keyOperator = nullptr; AWKeyOperations *keyOperator = nullptr;
QTimer *m_timer = nullptr; QTimer *m_timer = nullptr;
// variables // variables
QVariantMap m_tooltipParams; QVariantMap m_tooltipParams;
QStringList m_foundBars, m_foundKeys, m_foundLambdas, m_requiredKeys; QStringList m_foundBars, m_foundKeys, m_foundLambdas, m_requiredKeys;
QVariantHash m_values; QVariantHash values;
bool m_optimize = false; bool m_optimize = false;
bool m_wrapNewLines = false; bool m_wrapNewLines = false;
// multithread features
QThreadPool *m_threadPool = nullptr;
QMutex m_mutex;
}; };
#endif /* AWKEYS_H */

View File

@ -17,143 +17,610 @@
#include "awkeysaggregator.h" #include "awkeysaggregator.h"
#include "awdataenginemapper.h" #include <KI18n/KLocalizedString>
#include <QDateTime>
#include <QLocale>
#include <QRegExp>
#include "awdebug.h" #include "awdebug.h"
#include "awformatterhelper.h" #include "awformatterhelper.h"
AWKeysAggregator::AWKeysAggregator(QObject *_parent) AWKeysAggregator::AWKeysAggregator(QObject *parent)
: QObject(_parent) : QObject(parent)
{ {
qCDebug(LOG_AW) << __PRETTY_FUNCTION__; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
m_settings.customFormatters = new AWFormatterHelper(this); // default formatters
m_mapper = new AWDataEngineMapper(this, m_settings.customFormatters); // memory
m_formatter[QString("mem")] = FormatterType::Float;
m_formatter[QString("memtotmb")] = FormatterType::MemMBFormat;
m_formatter[QString("memtotgb")] = FormatterType::MemGBFormat;
// network
m_formatter[QString("down")] = FormatterType::NetSmartFormat;
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;
m_customFormatters = new AWFormatterHelper(nullptr);
} }
void AWKeysAggregator::initFormatters() AWKeysAggregator::~AWKeysAggregator()
{ {
m_settings.customFormatters->initItems(); qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
delete m_customFormatters;
} }
QString AWKeysAggregator::acOffline() const QString AWKeysAggregator::formatter(const QVariant &data,
const QString &key) const
{ {
return m_settings.acOffline; qCDebug(LOG_AW) << "Data" << data << "for key" << key;
QString output;
QLocale loc = m_translate ? QLocale::system() : QLocale::c();
// case block
switch (m_formatter[key]) {
case FormatterType::Float:
output = QString("%1").arg(data.toFloat(), 5, 'f', 1);
break;
case FormatterType::FloatTwoSymbols:
output = QString("%1").arg(data.toFloat(), 5, 'f', 2);
break;
case FormatterType::Integer:
output = QString("%1").arg(data.toFloat(), 4, 'f', 0);
break;
case FormatterType::IntegerFive:
output = QString("%1").arg(data.toFloat(), 5, 'f', 0);
break;
case FormatterType::IntegerThree:
output = QString("%1").arg(data.toFloat(), 3, 'f', 0);
break;
case FormatterType::List:
output = data.toStringList().join(QChar(','));
break;
case FormatterType::ACFormat:
output = data.toBool() ? m_acOnline : m_acOffline;
break;
case FormatterType::MemGBFormat:
output
= QString("%1").arg(data.toFloat() / (1024.0 * 1024.0), 5, 'f', 1);
break;
case FormatterType::MemMBFormat:
output = QString("%1").arg(data.toFloat() / 1024.0, 5, 'f', 0);
break;
case FormatterType::NetSmartFormat:
output = [](const float value) {
if (value > 1024.0)
return QString("%1").arg(value / 1024.0, 4, 'f', 1);
else
return QString("%1").arg(value, 4, 'f', 0);
}(data.toFloat());
break;
case FormatterType::NetSmartUnits:
if (data.toFloat() > 1024.0)
output = m_translate ? i18n("MB/s") : QString("MB/s");
else
output = m_translate ? i18n("KB/s") : QString("KB/s");
break;
case FormatterType::Quotes:
// first cast
output = QString("%1").arg(data.toDouble(), 0, 'f');
output = output.rightJustified(8, QLatin1Char(' '), true);
break;
case FormatterType::Temperature:
output = QString("%1").arg(temperature(data.toFloat()), 5, 'f', 1);
break;
case FormatterType::Time:
output = data.toDateTime().toString();
break;
case FormatterType::TimeCustom:
output = m_customTime;
[&output, loc, this](const QDateTime dt) {
for (auto key : timeKeys)
output.replace(QString("$%1").arg(key), loc.toString(dt, key));
}(data.toDateTime());
break;
case FormatterType::TimeISO:
output = data.toDateTime().toString(Qt::ISODate);
break;
case FormatterType::TimeLong:
output = loc.toString(data.toDateTime(), QLocale::LongFormat);
break;
case FormatterType::TimeShort:
output = loc.toString(data.toDateTime(), QLocale::ShortFormat);
break;
case FormatterType::Timestamp:
output = QString("%1").arg(
data.toDateTime().toMSecsSinceEpoch() / 1000.0, 10, 'f', 0);
break;
case FormatterType::Uptime:
case FormatterType::UptimeCustom:
output =
[](QString source, const int uptime) {
int seconds = uptime - uptime % 60;
int minutes = seconds / 60 % 60;
int hours = ((seconds / 60) - minutes) / 60 % 24;
int days = (((seconds / 60) - minutes) / 60 - hours) / 24;
source.replace(QString("$dd"),
QString("%1").arg(days, 3, 10, QChar('0')));
source.replace(QString("$d"), QString("%1").arg(days));
source.replace(QString("$hh"),
QString("%1").arg(hours, 2, 10, QChar('0')));
source.replace(QString("$h"), QString("%1").arg(hours));
source.replace(QString("$mm"),
QString("%1").arg(minutes, 2, 10, QChar('0')));
source.replace(QString("$m"), QString("%1").arg(minutes));
return source;
}(m_formatter[key] == FormatterType::Uptime
? QString("$ddd$hhh$mmm")
: m_customUptime,
static_cast<int>(data.toFloat()));
break;
case FormatterType::NoFormat:
output = data.toString();
break;
case FormatterType::Custom:
output = m_customFormatters->convert(data, key);
break;
} }
QString AWKeysAggregator::acOnline() const
{
return m_settings.acOnline;
}
QString AWKeysAggregator::customTime() const
{
return m_settings.customTime;
}
QString AWKeysAggregator::customUptime() const
{
return m_settings.customUptime;
}
QString AWKeysAggregator::formatter(const QVariant &_data, const QString &_key, bool replaceSpace) const
{
qCDebug(LOG_AW) << "Data" << _data << "for key" << _key;
auto output = m_mapper->formatter(_key)->format(_data, _key, m_settings);
// 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_mapper->keysFromSource(_source); return m_map.values(source);
} }
QString AWKeysAggregator::tempUnits() const void AWKeysAggregator::setAcOffline(const QString inactive)
{ {
return m_settings.tempUnits; qCDebug(LOG_AW) << "Inactive AC string" << inactive;
m_acOffline = inactive;
} }
bool AWKeysAggregator::translate() const void AWKeysAggregator::setAcOnline(const QString active)
{ {
return m_settings.translate; qCDebug(LOG_AW) << "Active AC string" << active;
m_acOnline = active;
} }
void AWKeysAggregator::setAcOffline(const QString &_inactive) void AWKeysAggregator::setCustomTime(const QString customTime)
{ {
qCDebug(LOG_AW) << "Inactive AC string" << _inactive; qCDebug(LOG_AW) << "Format" << customTime;
m_settings.acOffline = _inactive; m_customTime = customTime;
} }
void AWKeysAggregator::setAcOnline(const QString &_active) void AWKeysAggregator::setCustomUptime(const QString customUptime)
{ {
qCDebug(LOG_AW) << "Active AC string" << _active; qCDebug(LOG_AW) << "Format" << customUptime;
m_settings.acOnline = _active; m_customUptime = customUptime;
} }
void AWKeysAggregator::setCustomTime(const QString &_customTime) void AWKeysAggregator::setDevices(const QHash<QString, QStringList> devices)
{ {
qCDebug(LOG_AW) << "Format" << _customTime; qCDebug(LOG_AW) << "Devices" << devices;
m_settings.customTime = _customTime; m_devices = devices;
} }
void AWKeysAggregator::setCustomUptime(const QString &_customUptime) void AWKeysAggregator::setTempUnits(const QString units)
{ {
qCDebug(LOG_AW) << "Format" << _customUptime; qCDebug(LOG_AW) << "Units" << units;
m_settings.customUptime = _customUptime; m_tempUnits = units;
} }
void AWKeysAggregator::setDevices(const AWPluginMatcherSettings &_settings) void AWKeysAggregator::setTranslate(const bool translate)
{ {
m_mapper->setDevices(_settings); qCDebug(LOG_AW) << "Translate" << translate;
m_translate = translate;
} }
void AWKeysAggregator::setTempUnits(const QString &_units) // HACK units required to define should the value be calculated as temperature
// or fan data
QStringList AWKeysAggregator::registerSource(const QString &source,
const QString &units,
const QStringList &keys)
{ {
qCDebug(LOG_AW) << "Units" << _units; qCDebug(LOG_AW) << "Source" << source << "with units" << units;
m_settings.tempUnits = _units; // regular expressions
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 = 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);
} }
void AWKeysAggregator::setTranslate(const bool _translate) float AWKeysAggregator::temperature(const float temp) const
{ {
qCDebug(LOG_AW) << "Translate" << _translate; qCDebug(LOG_AW) << "Temperature value" << temp;
m_settings.translate = _translate; float converted = temp;
if (m_tempUnits == QString("Celsius")) {
} else if (m_tempUnits == QString("Fahrenheit")) {
converted = temp * 9.0f / 5.0f + 32.0f;
} else if (m_tempUnits == QString("Kelvin")) {
converted = temp + 273.15f;
} else if (m_tempUnits == QString("Reaumur")) {
converted = temp * 0.8f;
} else if (m_tempUnits == QString("cm^-1")) {
converted = (temp + 273.15f) * 0.695f;
} else if (m_tempUnits == QString("kJ/mol")) {
converted = (temp + 273.15f) * 8.31f;
} else if (m_tempUnits == QString("kcal/mol")) {
converted = (temp + 273.15f) * 1.98f;
} else {
qCWarning(LOG_AW) << "Invalid units" << m_tempUnits;
} }
return converted;
QStringList AWKeysAggregator::registerSource(const QString &_source, const KSysGuard::Unit _units,
const QStringList &_keys)
{
qCDebug(LOG_AW) << "Source" << _source << "with units" << _units;
return m_mapper->registerSource(_source, _units, _keys);
} }

View File

@ -15,55 +15,91 @@
* 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
#include <ksysguard/formatter/Unit.h> #ifndef AWKEYSAGGREGATOR_H
#define AWKEYSAGGREGATOR_H
#include <QHash> #include <QHash>
#include <QObject> #include <QObject>
#include "formatters/awpluginformatsettings.h" #include "version.h"
#include "matchers/awpluginmatchersettings.h"
class AWDataEngineMapper; class AWFormatterHelper;
class AWKeysAggregator : public QObject class AWKeysAggregator : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString acOffline READ acOffline WRITE setAcOffline); Q_PROPERTY(QString acOffline MEMBER m_acOffline WRITE setAcOffline);
Q_PROPERTY(QString acOnline READ acOnline WRITE setAcOnline); Q_PROPERTY(QString acOnline MEMBER m_acOnline WRITE setAcOnline);
Q_PROPERTY(QString customTime READ customTime WRITE setCustomTime); Q_PROPERTY(QString customTime MEMBER m_customTime WRITE setCustomTime);
Q_PROPERTY(QString customUptime READ customUptime WRITE setCustomUptime); Q_PROPERTY(
Q_PROPERTY(QString tempUnits READ tempUnits WRITE setTempUnits); QString customUptime MEMBER m_customUptime WRITE setCustomUptime);
Q_PROPERTY(bool translate READ translate WRITE setTranslate); Q_PROPERTY(QString tempUnits MEMBER m_tempUnits WRITE setTempUnits);
Q_PROPERTY(bool translate MEMBER m_translate WRITE setTranslate);
enum class FormatterType {
// general formatters
Custom,
NoFormat,
Float,
FloatTwoSymbols,
Integer,
IntegerFive,
IntegerThree,
List,
// unit specific formatters
ACFormat,
MemGBFormat,
MemMBFormat,
NetSmartFormat,
NetSmartUnits,
Quotes,
Temperature,
Time,
TimeCustom,
TimeISO,
TimeLong,
TimeShort,
Timestamp,
Uptime,
UptimeCustom
};
public: public:
explicit AWKeysAggregator(QObject *_parent = nullptr); explicit AWKeysAggregator(QObject *parent = nullptr);
~AWKeysAggregator() override = default; virtual ~AWKeysAggregator();
void initFormatters();
// get methods // get methods
[[nodiscard]] QString acOffline() const; QString formatter(const QVariant &data, const QString &key) const;
[[nodiscard]] QString acOnline() const; QStringList keysFromSource(const QString &source) const;
[[nodiscard]] QString customTime() const;
[[nodiscard]] QString customUptime() const;
[[nodiscard]] QString formatter(const QVariant &_data, const QString &_key, bool replaceSpace) const;
[[nodiscard]] QStringList keysFromSource(const QString &_source) const;
[[nodiscard]] QString tempUnits() const;
[[nodiscard]] bool translate() 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 AWPluginMatcherSettings &_settings); void setDevices(const QHash<QString, QStringList> devices);
void setTempUnits(const QString &_units); void setTempUnits(const QString units);
void setTranslate(bool _translate); void setTranslate(const bool translate);
public slots: public slots:
QStringList registerSource(const QString &_source, KSysGuard::Unit _units, const QStringList &_keys); QStringList registerSource(const QString &source, const QString &units,
const QStringList &keys);
private: private:
AWPluginFormatSettings m_settings; float temperature(const float temp) const;
AWDataEngineMapper *m_mapper = nullptr; AWFormatterHelper *m_customFormatters = nullptr;
QStringList timeKeys = QString(TIME_KEYS).split(QChar(','));
// variables
QString m_acOffline;
QString m_acOnline;
QString m_customTime;
QString m_customUptime;
QHash<QString, QStringList> m_devices;
QHash<QString, FormatterType> m_formatter;
QHash<QString, QString> m_map;
QString m_tempUnits;
bool m_translate = false;
}; };
#endif /* AWKEYSAGGREGATOR_H */

View File

@ -1,32 +0,0 @@
/***************************************************************************
* 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/ *
***************************************************************************/
#pragma once
#include <QObject>
class AWPairConfigFactory : public QObject
{
Q_OBJECT
public:
explicit AWPairConfigFactory(QObject *_parent = nullptr);
~AWPairConfigFactory() override = default;
Q_INVOKABLE static void showFormatterDialog(const QStringList &_keys);
Q_INVOKABLE static void showKeysDialog(const QStringList &_keys);
};

View File

@ -24,65 +24,73 @@
#include "awkeysaggregator.h" #include "awkeysaggregator.h"
QString AWPatternFunctions::expandLambdas(QString _code, AWKeysAggregator *_aggregator, const QVariantHash &_metadata, QString AWPatternFunctions::expandLambdas(QString code,
const QStringList &_usedKeys) AWKeysAggregator *aggregator,
const QVariantHash &metadata,
const QStringList &usedKeys)
{ {
qCDebug(LOG_AW) << "Expand lambdas in" << _code; qCDebug(LOG_AW) << "Expand lamdas in" << code;
QJSEngine engine; QJSEngine engine;
// apply $this values // apply $this values
_code.replace("$this", _metadata[_code].toString()); code.replace(QString("$this"), metadata[code].toString());
// parsed values // parsed values
for (auto &lambdaKey : _usedKeys) for (auto lambdaKey : usedKeys)
_code.replace(QString("$%1").arg(lambdaKey), _aggregator->formatter(_metadata[lambdaKey], lambdaKey, false)); code.replace(QString("$%1").arg(lambdaKey),
qCInfo(LOG_AW) << "Expression" << _code; aggregator->formatter(metadata[lambdaKey], lambdaKey));
auto result = engine.evaluate(_code); qCInfo(LOG_AW) << "Expression" << code;
QJSValue result = engine.evaluate(code);
if (result.isError()) { if (result.isError()) {
qCWarning(LOG_AW) << "Uncaught exception at line" << result.property("lineNumber").toInt() << ":" qCWarning(LOG_AW) << "Uncaught exception at line"
<< result.property("lineNumber").toInt() << ":"
<< result.toString(); << result.toString();
return ""; return QString();
} 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}}
static QRegularExpression templatesRegexp(R"(\$template\{\{(?<body>.*?)\}\})"); QRegularExpression templatesRegexp(
templatesRegexp.setPatternOptions(QRegularExpression::DotMatchesEverythingOption); QString("\\$template\\{\\{(?<body>.*?)\\}\\}"));
templatesRegexp.setPatternOptions(
QRegularExpression::DotMatchesEverythingOption);
auto it = templatesRegexp.globalMatch(_code); QRegularExpressionMatchIterator it = templatesRegexp.globalMatch(code);
while (it.hasNext()) { while (it.hasNext()) {
auto match = it.next(); QRegularExpressionMatch match = it.next();
auto body = match.captured("body"); QString body = match.captured(QString("body"));
QJSEngine engine; QJSEngine engine;
qCInfo(LOG_AW) << "Expression" << body; qCInfo(LOG_AW) << "Expression" << body;
auto result = engine.evaluate(body); QJSValue result = engine.evaluate(body);
QString templateResult = ""; QString templateResult = QString("");
if (result.isError()) { if (result.isError()) {
qCWarning(LOG_AW) << "Uncaught exception at line" << result.property("lineNumber").toInt() << ":" qCWarning(LOG_AW) << "Uncaught exception at line"
<< 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> AWPatternFunctions::findFunctionCalls(const QString &_function, QList<AWPatternFunctions::AWFunction>
const QString &_code) AWPatternFunctions::findFunctionCalls(const QString function,
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}}
@ -90,32 +98,36 @@ QList<AWPatternFunctions::AWFunction> AWPatternFunctions::findFunctionCalls(cons
// 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(QString(R"(\$%1\<(?<args>.*?)\>\{\{(?<body>.*?)\}\})").arg(_function)); QRegularExpression regex(
QString("\\$%1\\<(?<args>.*?)\\>\\{\\{(?<body>.*?)\\}\\}")
.arg(function));
regex.setPatternOptions(QRegularExpression::DotMatchesEverythingOption); regex.setPatternOptions(QRegularExpression::DotMatchesEverythingOption);
QList<AWPatternFunctions::AWFunction> foundFunctions; QList<AWPatternFunctions::AWFunction> foundFunctions;
auto it = regex.globalMatch(_code); QRegularExpressionMatchIterator it = regex.globalMatch(code);
while (it.hasNext()) { while (it.hasNext()) {
auto match = it.next(); QRegularExpressionMatch match = it.next();
AWPatternFunctions::AWFunction metadata; AWPatternFunctions::AWFunction metadata;
// work with args // work with args
auto argsString = match.captured("args"); QString argsString = match.captured(QString("args"));
if (argsString.isEmpty()) { if (argsString.isEmpty()) {
metadata.args = QStringList(); metadata.args = QStringList();
} else { } else {
// replace '$,' to 0x1d // replace '$,' to 0x1d
argsString.replace("$,", QChar(0x1d)); argsString.replace(QString("$,"), QString(0x1d));
auto args = argsString.split(','); QStringList args = argsString.split(QChar(','));
std::for_each(args.begin(), args.end(), [](auto &arg) { arg.replace(QChar(0x1d), ","); }); std::for_each(args.begin(), args.end(), [](QString &arg) {
arg.replace(QString(0x1d), QString(","));
});
metadata.args = args; metadata.args = args;
} }
// other variables // other variables
metadata.body = match.captured("body"); metadata.body = match.captured(QString("body"));
metadata.what = match.captured(); metadata.what = match.captured();
// replace brackets // replace brackets
metadata.body.replace("${", "{"); metadata.body.replace(QString("${"), QString("{"));
metadata.body.replace("$}", "}"); metadata.body.replace(QString("$}"), QString("}"));
foundFunctions.append(metadata); foundFunctions.append(metadata);
} }
@ -123,119 +135,144 @@ QList<AWPatternFunctions::AWFunction> AWPatternFunctions::findFunctionCalls(cons
} }
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" << _keys; qCDebug(LOG_AW) << "Looking for keys in code" << code << "using list"
<< keys;
auto found = AWPatternFunctions::findFunctionCalls("aw_all", _code); QList<AWPatternFunctions::AWFunction> found
for (auto &function : found) { = AWPatternFunctions::findFunctionCalls(QString("aw_all"), code);
auto separator = function.args.isEmpty() ? "," : function.args.at(0); for (auto function : found) {
auto required = _keys.filter(QRegularExpression(function.body)); QString separator
std::for_each(required.begin(), required.end(), [](auto &value) { value = QString("%1: $%1").arg(value); }); = function.args.isEmpty() ? QString(",") : function.args.at(0);
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" << _keys; qCDebug(LOG_AW) << "Looking for count in code" << code << "using list"
<< keys;
auto found = AWPatternFunctions::findFunctionCalls("aw_count", _code); QList<AWPatternFunctions::AWFunction> found
for (auto &function : found) { = AWPatternFunctions::findFunctionCalls(QString("aw_count"), code);
auto count = _keys.filter(QRegularExpression(function.body)).count(); for (auto function : found) {
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" << _keys; qCDebug(LOG_AW) << "Looking for key names in code" << code << "using list"
<< keys;
auto found = AWPatternFunctions::findFunctionCalls("aw_names", _code); QList<AWPatternFunctions::AWFunction> found
for (auto &function : found) { = AWPatternFunctions::findFunctionCalls(QString("aw_names"), code);
auto separator = function.args.isEmpty() ? "," : function.args.at(0); for (auto function : found) {
auto required = _keys.filter(QRegularExpression(function.body)); QString separator
= 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" << _keys; qCDebug(LOG_AW) << "Looking for keys in code" << code << "using list"
<< keys;
auto found = AWPatternFunctions::findFunctionCalls("aw_keys", _code); QList<AWPatternFunctions::AWFunction> found
for (auto &function : found) { = AWPatternFunctions::findFunctionCalls(QString("aw_keys"), code);
auto separator = function.args.isEmpty() ? "," : function.args.at(0); for (auto function : found) {
auto required = _keys.filter(QRegularExpression(function.body)); QString separator
std::for_each(required.begin(), required.end(), [](auto &value) { value = QString("$%1").arg(value); }); = function.args.isEmpty() ? QString(",") : function.args.at(0);
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;
auto found = AWPatternFunctions::findFunctionCalls("aw_macro", _code); QList<AWPatternFunctions::AWFunction> found
for (auto &macro : found) { = AWPatternFunctions::findFunctionCalls(QString("aw_macro"), code);
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;
continue; continue;
} }
auto name = macro.args.takeFirst(); QString name = macro.args.takeFirst();
// find macro usage // find macro usage
auto macroUsage = AWPatternFunctions::findFunctionCalls(QString("aw_macro_%1").arg(name), _code); QList<AWPatternFunctions::AWFunction> macroUsage
for (auto &function : macroUsage) { = AWPatternFunctions::findFunctionCalls(
QString("aw_macro_%1").arg(name), code);
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" << function.what << "with macro" << macro.what; qCWarning(LOG_AW) << "Invalid args count found for call"
<< function.what << "with macro"
<< macro.what;
continue; continue;
} }
// generate body to replace // generate body to replace
auto result = macro.body; QString result = macro.body;
std::for_each(macro.args.cbegin(), macro.args.cend(), [&result, macro, function](auto &arg) { std::for_each(macro.args.cbegin(), macro.args.cend(),
auto index = macro.args.indexOf(arg); [&result, macro, function](const QString &arg) {
result.replace(QString("$%1").arg(arg), function.args.at(index)); int index = macro.args.indexOf(arg);
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, const QStringList &_keys, const bool _isBars) QStringList AWPatternFunctions::findKeys(const QString code,
const QStringList keys,
const bool isBars)
{ {
qCDebug(LOG_AW) << "Looking for keys in code" << _code << "using list" << _keys; qCDebug(LOG_AW) << "Looking for keys in code" << code << "using list"
<< keys;
QStringList selectedKeys; QStringList selectedKeys;
auto replacedCode = _code; for (auto key : keys)
for (auto &key : _keys) if ((key.startsWith(QString("bar")) == isBars)
if ((key.startsWith("bar") == _isBars) && (replacedCode.contains(QString("$%1").arg(key)))) { && (code.contains(QString("$%1").arg(key)))) {
qCInfo(LOG_AW) << "Found key" << key << "with bar enabled" << _isBars; qCInfo(LOG_AW) << "Found key" << key << "with bar enabled"
<< 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";
@ -244,19 +281,20 @@ QStringList AWPatternFunctions::findKeys(const QString &_code, const QStringList
} }
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}}
static QRegularExpression lambdaRegexp(R"(\$\{\{(?<body>.*?)\}\})"); QRegularExpression lambdaRegexp(QString("\\$\\{\\{(?<body>.*?)\\}\\}"));
lambdaRegexp.setPatternOptions(QRegularExpression::DotMatchesEverythingOption); lambdaRegexp.setPatternOptions(
QRegularExpression::DotMatchesEverythingOption);
auto it = lambdaRegexp.globalMatch(_code); QRegularExpressionMatchIterator it = lambdaRegexp.globalMatch(code);
while (it.hasNext()) { while (it.hasNext()) {
auto match = it.next(); QRegularExpressionMatch match = it.next();
auto lambda = match.captured("body"); QString lambda = match.captured(QString("body"));
// append // append
qCInfo(LOG_AW) << "Found lambda" << lambda; qCInfo(LOG_AW) << "Found lambda" << lambda;

View File

@ -15,7 +15,9 @@
* 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 AWPATTERNFUNCTIONS_H
#define AWPATTERNFUNCTIONS_H
#include <QString> #include <QString>
#include <QVariant> #include <QVariant>
@ -23,7 +25,7 @@
class AWKeysAggregator; class AWKeysAggregator;
namespace __attribute__((visibility("default"))) AWPatternFunctions namespace AWPatternFunctions
{ {
typedef struct { typedef struct {
QStringList args; QStringList args;
@ -32,16 +34,21 @@ typedef struct {
} AWFunction; } AWFunction;
// insert methods // insert methods
QString expandLambdas(QString _code, AWKeysAggregator *_aggregator, const QVariantHash &_metadata, QString expandLambdas(QString code, AWKeysAggregator *aggregator,
const QStringList &_usedKeys); const QVariantHash &metadata,
QString expandTemplates(QString _code); const QStringList &usedKeys);
QList<AWFunction> findFunctionCalls(const QString &_function, const QString &_code); QString expandTemplates(QString code);
QString insertAllKeys(QString _code, const QStringList &_keys); QList<AWFunction> findFunctionCalls(const QString function, const QString code);
QString insertKeyCount(QString _code, const QStringList &_keys); QString insertAllKeys(QString code, const QStringList keys);
QString insertKeyNames(QString _code, const QStringList &_keys); QString insertKeyCount(QString code, const QStringList keys);
QString insertKeys(QString _code, const QStringList &_keys); QString insertKeyNames(QString code, const QStringList keys);
QString insertMacros(QString _code); QString insertKeys(QString code, const QStringList keys);
QString insertMacros(QString code);
// find methods // find methods
QStringList findKeys(const QString &_code, const QStringList &_keys, bool _isBars); QStringList findKeys(const QString code, const QStringList keys,
QStringList findLambdas(const QString &_code); const bool isBars);
} // namespace AWPatternFunctions QStringList findLambdas(const QString code);
};
#endif /* AWPATTERNFUNCTIONS_H */

View File

@ -1,111 +0,0 @@
/***************************************************************************
* 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 <QSettings>
#include <QStandardPaths>
#include <QUuid>
#include "awdebug.h"
AWTelemetryHandler::AWTelemetryHandler(QObject *_parent)
: QObject(_parent)
{
qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
m_localFile = QString("%1/awesomewidgets/telemetry.ini")
.arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation));
}
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)
{
qCDebug(LOG_AW) << "Init telemetry with count" << _count;
m_storeCount = _count;
}
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) {
auto key = getKey(settings.childKeys().count());
settings.setValue(key, val);
}
// sync settings
settings.endGroup();
settings.sync();
// return status
return (settings.status() == QSettings::NoError);
}
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

@ -1,39 +0,0 @@
/***************************************************************************
* 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/ *
***************************************************************************/
#pragma once
#include <QObject>
class __attribute__((visibility("default"))) AWTelemetryHandler : public QObject
{
Q_OBJECT
public:
explicit AWTelemetryHandler(QObject *_parent = nullptr);
~AWTelemetryHandler() override = default;
Q_INVOKABLE [[nodiscard]] QStringList get(const QString &_group) const;
Q_INVOKABLE [[nodiscard]] QString getLast(const QString &_group) const;
Q_INVOKABLE void init(int _count);
Q_INVOKABLE [[nodiscard]] bool put(const QString &_group, const QString &_value) const;
private:
static QString getKey(int _count);
QString m_localFile;
int m_storeCount = 0;
};

View File

@ -17,42 +17,49 @@
#include "awupdatehelper.h" #include "awupdatehelper.h"
#ifndef NDEBUG
#define NDEBUG
#endif /* NDEBUG */
#include <KI18n/KLocalizedString> #include <KI18n/KLocalizedString>
#include <KNotifications/KNotification>
#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 <QStandardPaths> #include <QtConcurrent/QtConcurrent>
#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(QStandardPaths::GenericDataLocation)); .arg(QStandardPaths::writableLocation(
QStandardPaths::GenericDataLocation));
} }
void AWUpdateHelper::checkUpdates(const bool _showAnyway) AWUpdateHelper::~AWUpdateHelper()
{ {
qCDebug(LOG_AW) << "Show anyway" << _showAnyway; qCDebug(LOG_AW) << __PRETTY_FUNCTION__;
}
// showAnyway options required to show message if no updates found on direct
void AWUpdateHelper::checkUpdates(const bool showAnyway)
{
qCDebug(LOG_AW) << "Show anyway" << showAnyway;
// 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
auto manager = new QNetworkAccessManager(nullptr); QNetworkAccessManager *manager = new QNetworkAccessManager(nullptr);
connect(manager, &QNetworkAccessManager::finished, connect(manager, &QNetworkAccessManager::finished,
[_showAnyway, this](QNetworkReply *reply) { return versionReplyReceived(reply, _showAnyway); }); [showAnyway, this](QNetworkReply *reply) {
return versionReplyRecieved(reply, showAnyway);
});
manager->get(QNetworkRequest(QUrl(VERSION_API))); manager->get(QNetworkRequest(QUrl(VERSION_API)));
} }
@ -61,14 +68,19 @@ void AWUpdateHelper::checkUpdates(const bool _showAnyway)
bool AWUpdateHelper::checkVersion() bool AWUpdateHelper::checkVersion()
{ {
QSettings settings(m_genericConfig, QSettings::IniFormat); QSettings settings(m_genericConfig, QSettings::IniFormat);
auto version = QVersionNumber::fromString(settings.value("Version", QString(VERSION)).toString()); QVersionNumber version = QVersionNumber::fromString(
settings.value(QString("Version"), QString(VERSION)).toString());
// update version // update version
settings.setValue("Version", QString(VERSION)); settings.setValue(QString("Version"), QString(VERSION));
settings.sync(); settings.sync();
qCInfo(LOG_AW) << "Found version" << version << "actual one is" << m_foundVersion; qCInfo(LOG_AW) << "Found version" << version << "actual one is"
<< m_foundVersion;
if ((version != m_foundVersion) && (!QString(CHANGELOG).isEmpty())) { if ((version != m_foundVersion) && (!QString(CHANGELOG).isEmpty())) {
sendNotification(i18n("Changelog of %1", VERSION), QString(CHANGELOG).replace('@', '\n')); genMessageBox(i18n("Changelog of %1", QString(VERSION)),
QString(CHANGELOG).replace(QChar('@'), QChar('\n')),
QMessageBox::Ok)
->open();
return true; return true;
} else if (version != m_foundVersion) { } else if (version != m_foundVersion) {
qCWarning(LOG_AW) << "No changelog information provided"; qCWarning(LOG_AW) << "No changelog information provided";
@ -81,78 +93,100 @@ bool AWUpdateHelper::checkVersion()
} }
void AWUpdateHelper::openReleasesPage() void AWUpdateHelper::showInfo(const QVersionNumber version)
{ {
QDesktopServices::openUrl(QString(RELEASES) + m_foundVersion.toString()); qCDebug(LOG_AW) << "Version" << version;
}
QString text
void AWUpdateHelper::showInfo(const QVersionNumber &_version) = i18n("You are using the actual version %1", version.toString());
{
qCDebug(LOG_AW) << "Version" << _version;
auto text = 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));
sendNotification(i18n("No new version found"), text); return genMessageBox(i18n("No new version found"), text, QMessageBox::Ok)
->open();
} }
void AWUpdateHelper::showUpdates(const QVersionNumber &_version) const 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", VERSION); text += i18n("Current version : %1", QString(VERSION));
text += QString(COMMIT_SHA).isEmpty() ? "\n" : QString(" (%1)\n").arg(QString(COMMIT_SHA)); text += QString(COMMIT_SHA).isEmpty()
text += i18n("New version : %1", _version.toString()) + "\n\n"; ? QString("\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");
auto event = sendNotification(i18n("There are updates"), text); genMessageBox(i18n("There are updates"), text,
auto action = event->addAction(i18n("Details")); QMessageBox::Ok | QMessageBox::Cancel)
connect(action, &KNotificationAction::activated, this, &AWUpdateHelper::openReleasesPage); ->open(this, SLOT(userReplyOnUpdates(QAbstractButton *)));
} }
void AWUpdateHelper::versionReplyReceived(QNetworkReply *_reply, const bool _showAnyway) void AWUpdateHelper::userReplyOnUpdates(QAbstractButton *button)
{ {
qCDebug(LOG_AW) << "Show message anyway" << _showAnyway; QMessageBox::ButtonRole ret
if (_reply->error() != QNetworkReply::NoError) { = static_cast<QMessageBox *>(sender())->buttonRole(button);
qCWarning(LOG_AW) << "An error occurs" << _reply->error() << "with message" << _reply->errorString(); qCInfo(LOG_AW) << "User select" << ret;
return;
switch (ret) {
case QMessageBox::AcceptRole:
QDesktopServices::openUrl(QString(RELEASES)
+ m_foundVersion.toString());
break;
case QMessageBox::RejectRole:
default:
break;
}
} }
auto error = QJsonParseError();
auto jsonDoc = QJsonDocument::fromJson(_reply->readAll(), &error); void AWUpdateHelper::versionReplyRecieved(QNetworkReply *reply,
if (error.error != QJsonParseError::NoError) { const bool showAnyway)
{
qCDebug(LOG_AW) << "Return code" << reply->error() << "with message"
<< reply->errorString() << "and show anyway" << showAnyway;
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
if ((reply->error() != QNetworkReply::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();
_reply->manager()->deleteLater(); // remember to delete manager too
// convert to map // convert to map
auto firstRelease = jsonDoc.toVariant().toList().first().toMap(); QVariantMap firstRelease = jsonDoc.toVariant().toList().first().toMap();
auto version = firstRelease["tag_name"].toString(); QString version = firstRelease[QString("tag_name")].toString();
version.remove("V."); version.remove(QString("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;
auto 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
KNotification *AWUpdateHelper::sendNotification(const QString &_title, const QString &_body) QMessageBox *
AWUpdateHelper::genMessageBox(const QString title, const QString body,
const QMessageBox::StandardButtons buttons)
{ {
qCDebug(LOG_AW) << "Construct message box with title" << _title << "and body" << _body; qCDebug(LOG_AW) << "Construct message box with title" << title << "and body"
<< body;
auto event = KNotification::event("system", _title, _body); QMessageBox *msgBox = new QMessageBox(nullptr);
event->setComponentName("plasma-applet-org.kde.plasma.awesome-widget"); msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->setModal(false);
msgBox->setWindowTitle(title);
msgBox->setText(body);
msgBox->setStandardButtons(buttons);
msgBox->setIcon(QMessageBox::Information);
return event; return msgBox;
} }

View File

@ -15,33 +15,39 @@
* 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 AWUPDATEHELPER_H
#define AWUPDATEHELPER_H
#include <QMessageBox>
#include <QObject> #include <QObject>
#include <QVersionNumber> #include <QVersionNumber>
class KNotification;
class QNetworkReply; class QNetworkReply;
class __attribute__((visibility("default"))) AWUpdateHelper : public QObject class AWUpdateHelper : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AWUpdateHelper(QObject *_parent = nullptr); explicit AWUpdateHelper(QObject *parent = nullptr);
~AWUpdateHelper() override = default; virtual ~AWUpdateHelper();
void checkUpdates(bool _showAnyway = false); void checkUpdates(const bool showAnyway = false);
bool checkVersion(); bool checkVersion();
private slots: private slots:
void openReleasesPage(); void showInfo(const QVersionNumber version);
static void showInfo(const QVersionNumber &_version); void showUpdates(const QVersionNumber version);
void showUpdates(const QVersionNumber &_version) const; void userReplyOnUpdates(QAbstractButton *button);
void versionReplyReceived(QNetworkReply *_reply, bool _showAnyway); void versionReplyRecieved(QNetworkReply *reply, const bool showAnyway);
private: private:
static KNotification *sendNotification(const QString &_title, const QString &_body); QMessageBox *genMessageBox(const QString title, const QString body,
const QMessageBox::StandardButtons buttons);
QVersionNumber m_foundVersion; QVersionNumber m_foundVersion;
QString m_genericConfig; QString m_genericConfig;
}; };
#endif /* AWUPDATEHELPER_H */

View File

@ -1,37 +0,0 @@
/***************************************************************************
* 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/ *
***************************************************************************/
#pragma once
#include <QString>
class AWFormatterHelper;
struct AWPluginFormatSettings {
QString acOffline;
QString acOnline;
QString customTime;
QString customUptime;
QString tempUnits;
bool translate = false;
AWFormatterHelper *customFormatters = nullptr;
};

View File

@ -1,69 +0,0 @@
/***************************************************************************
* 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/ *
***************************************************************************/
#pragma once
#include <QLocale>
#include <QVariant>
#include <memory>
#include "awpluginformatsettings.h"
class AWPluginFormaterInterface
{
public:
virtual ~AWPluginFormaterInterface() = default;
[[nodiscard]] virtual QString format(const QVariant &_value, const QString &_key,
const AWPluginFormatSettings &_settings) const
= 0;
virtual void load(){};
};
template <typename Formatter> class AWPluginFormatter : public AWPluginFormaterInterface
{
public:
static constexpr double KBinBytes = 1024.0;
static constexpr double MBinBytes = 1024.0 * KBinBytes;
static constexpr double GBinBytes = 1024.0 * MBinBytes;
AWPluginFormatter(AWPluginFormatter &) = delete;
void operator=(const AWPluginFormatter &) = delete;
[[nodiscard]] static Formatter *instance()
{
static auto instance = loadInstance();
return instance.get();
};
[[nodiscard]] static QLocale locale(const AWPluginFormatSettings &_settings)
{
return _settings.translate ? QLocale::system() : QLocale::c();
};
protected:
AWPluginFormatter() = default;
[[nodiscard]] static std::unique_ptr<Formatter> loadInstance()
{
auto instance = std::make_unique<Formatter>();
instance->load();
return instance;
};
};

View File

@ -1,25 +0,0 @@
/***************************************************************************
* 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 "awpluginformatterac.h"
QString AWPluginFormatterAC::format(const QVariant &_value, const QString &,
const AWPluginFormatSettings &_settings) const
{
return _value.toBool() ? _settings.acOnline : _settings.acOffline;
}

View File

@ -1,28 +0,0 @@
/***************************************************************************
* 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/ *
***************************************************************************/
#pragma once
#include "awpluginformatter.h"
class AWPluginFormatterAC : public AWPluginFormatter<AWPluginFormatterAC>
{
public:
[[nodiscard]] QString format(const QVariant &_value, const QString &,
const AWPluginFormatSettings &_settings) const override;
};

View File

@ -1,29 +0,0 @@
/***************************************************************************
* 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 "awpluginformattercustom.h"
#include "awformatterhelper.h"
QString AWPluginFormatterCustom::format(const QVariant &_value, const QString &_key,
const AWPluginFormatSettings &_settings) const
{
if (_settings.customFormatters)
return _settings.customFormatters->convert(_value, _key);
return _value.toString();
}

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