├── screenshots ├── a.png └── b.png ├── .gitmodules ├── src ├── res.qrc ├── kcm_colorful.desktop ├── artworks │ ├── refresh.svg │ ├── pallete.svg │ └── gen-colors.svg ├── helper │ ├── CMakeLists.txt │ ├── mmcq.h │ ├── kcmcolorfulhelper.h │ ├── main.cpp │ ├── mmcq.cpp │ ├── colordata.h │ └── kcmcolorfulhelper.cpp ├── CMakeLists.txt ├── kcm_colorful.h ├── qml │ ├── Header.qml │ ├── colors.js │ ├── main.qml │ ├── WButton.qml │ ├── ColorUnitW.qml │ ├── ColorUnit.qml │ ├── ColorWidget.qml │ └── Wallpaper.qml └── kcm_colorful.cpp ├── .gitignore ├── CMakeLists.txt ├── po ├── kcm_colorful.pot ├── zh_TW.po ├── CMakeLists.txt └── zh_CN.po ├── extract-messages.sh ├── TRANSLATING.md ├── README.md ├── README.en.md ├── schemes ├── ColorfulDark.colors └── ColorfulLight.colors └── LICENSE /screenshots/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THMonster/kcm-colorful/HEAD/screenshots/a.png -------------------------------------------------------------------------------- /screenshots/b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THMonster/kcm-colorful/HEAD/screenshots/b.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "plasmathemes/kde-theme-backup"] 2 | path = plasmathemes/kde-theme-backup 3 | url = https://github.com/IsoaSFlus/kde-theme-backup 4 | -------------------------------------------------------------------------------- /src/res.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | qml/ColorUnit.qml 4 | qml/ColorWidget.qml 5 | qml/Header.qml 6 | qml/main.qml 7 | qml/Wallpaper.qml 8 | qml/WButton.qml 9 | artworks/gen-colors.svg 10 | artworks/refresh.svg 11 | qml/ColorUnitW.qml 12 | qml/colors.js 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/kcm_colorful.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Exec=kcmshell5 kcm_colorful 3 | Icon=kcolorchooser 4 | Type=Service 5 | 6 | X-KDE-ServiceTypes=KCModule 7 | X-KDE-Library=kcm_colorful 8 | X-KDE-ParentApp=kcontrol 9 | 10 | X-KDE-System-Settings-Parent-Category=appearance 11 | # X-KDE-Weight=60 12 | 13 | 14 | Name=Colorful 15 | Name[zh_CN]=多彩 16 | Name[zh_TW]=多彩 17 | Comment=Make your KDE Plasma colorful 18 | Comment[zh_CN]=让您的KDE Plasma丰富多彩 19 | Comment[zh_TW]=讓您的 KDE Plasma 更多彩 20 | X-KDE-Keywords=Color, Theme 21 | X-KDE-Keywords[zh_CN]=Color, Theme,色彩,颜色,主题 22 | X-KDE-Keywords[zh_TW]=Color, Theme, 色彩, 顏色, 主題 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | *.slo 3 | *.lo 4 | *.o 5 | *.a 6 | *.la 7 | *.lai 8 | *.so 9 | *.dll 10 | *.dylib 11 | 12 | # Qt-es 13 | object_script.*.Release 14 | object_script.*.Debug 15 | *_plugin_import.cpp 16 | /.qmake.cache 17 | /.qmake.stash 18 | *.pro.user 19 | *.pro.user.* 20 | *.qbs.user 21 | *.qbs.user.* 22 | *.moc 23 | moc_*.cpp 24 | moc_*.h 25 | qrc_*.cpp 26 | ui_*.h 27 | *.qmlc 28 | *.jsc 29 | Makefile* 30 | *build-* 31 | 32 | # Qt unit tests 33 | target_wrapper.* 34 | 35 | # QtCreator 36 | *.autosave 37 | 38 | # QtCreator Qml 39 | *.qmlproject.user 40 | *.qmlproject.user.* 41 | 42 | # QtCreator CMake 43 | CMakeLists.txt.user* 44 | 45 | # Mine 46 | build/ 47 | -------------------------------------------------------------------------------- /src/artworks/refresh.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/helper/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(kcmcolorfulhelper "main.cpp" 2 | "kcmcolorfulhelper.cpp" 3 | "mmcq.cpp") 4 | 5 | target_link_libraries(kcmcolorfulhelper Qt5::Core 6 | Qt5::DBus 7 | KF5::ConfigCore 8 | KF5::ConfigGui 9 | KF5::ConfigWidgets 10 | KF5::KCMUtils 11 | KF5::I18n 12 | KF5::KIOCore 13 | KF5::CoreAddons) 14 | 15 | install(TARGETS kcmcolorfulhelper DESTINATION ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) 16 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(helper) 2 | include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) 3 | 4 | #add_definitions(-DTRANSLATION_DOMAIN=\"kcm5_colorful\") 5 | 6 | set(kcm_file_SRCS 7 | kcm_colorful.cpp 8 | ) 9 | 10 | qt5_add_resources(kcm_file_SRCS res.qrc) 11 | add_library(kcm_colorful MODULE ${kcm_file_SRCS}) 12 | target_compile_definitions(kcm_colorful PRIVATE -DPROJECT_VERSION="${PROJECT_VERSION}") 13 | target_link_libraries(kcm_colorful 14 | KF5::KIOWidgets 15 | KF5::CoreAddons 16 | KF5::ConfigWidgets 17 | KF5::I18n 18 | KF5::Solid 19 | KF5::Declarative 20 | Qt5::Core 21 | Qt5::Gui 22 | Qt5::QuickControls2 23 | Qt5::Widgets 24 | Qt5::QuickWidgets 25 | ) 26 | 27 | 28 | 29 | install(FILES kcm_colorful.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) 30 | install(TARGETS kcm_colorful DESTINATION ${KDE_INSTALL_PLUGINDIR}) 31 | -------------------------------------------------------------------------------- /src/kcm_colorful.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class KCMColorful : public KCModule 10 | { 11 | Q_OBJECT 12 | public: 13 | KCMColorful(QWidget* parent, const QVariantList& args); 14 | ~KCMColorful(); 15 | void readConfig(); 16 | void saveConfig(); 17 | void addColorGV1(QString color); 18 | 19 | 20 | 21 | 22 | private: 23 | QQuickWidget *root_qml = nullptr; 24 | QString current_wallpaper; 25 | QStringList recent_colors; 26 | QStringList user_colors; 27 | bool extracted_flag = false; 28 | QStringList colors; 29 | QProcess *helper = nullptr; 30 | KDeclarative::KDeclarative *kdeclarative = nullptr; 31 | 32 | 33 | public Q_SLOTS: 34 | void apply_color(const QString &c); 35 | void loadExtractedColors(); 36 | void runHelper(); 37 | void set_wp_view(); 38 | }; 39 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | SET(CMAKE_INSTALL_PREFIX /usr CACHE PATH "Set install prefix.") 3 | project(kcm-colorful) 4 | set(PROJECT_VERSION "1.0.5") 5 | 6 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 7 | set(CMAKE_AUTOMOC ON) 8 | 9 | 10 | find_package(ECM 1.0.0 REQUIRED NO_MODULE) 11 | find_package( Gettext REQUIRED ) 12 | set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) 13 | include(KDEInstallDirs) 14 | include(ECMInstallIcons) 15 | include(KDECMakeSettings) 16 | include(KDECompilerSettings) 17 | include(FeatureSummary) 18 | 19 | find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS Core Gui Widgets X11Extras Quick QuickControls2 QuickWidgets DBus) 20 | find_package(KF5 REQUIRED COMPONENTS 21 | CoreAddons 22 | WidgetsAddons 23 | ConfigWidgets 24 | KIO 25 | KCMUtils 26 | I18n 27 | Declarative 28 | ) 29 | add_definitions(-DTRANSLATION_DOMAIN=\"kcm_colorful\") 30 | 31 | add_subdirectory(src) 32 | add_subdirectory(po) 33 | 34 | file(GLOB schemefiles schemes/*.colors) 35 | install( FILES ${schemefiles} DESTINATION ${KDE_INSTALL_DATADIR}/color-schemes ) 36 | install(DIRECTORY plasmathemes/kde-theme-backup/Colorful DESTINATION ${KDE_INSTALL_DATADIR}/plasma/desktoptheme) 37 | -------------------------------------------------------------------------------- /src/helper/mmcq.h: -------------------------------------------------------------------------------- 1 | #ifndef MMCQ_H 2 | #define MMCQ_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class VBox 10 | { 11 | public: 12 | VBox(); 13 | explicit VBox(int r1, int r2, int g1, int g2, int b1, int b2); 14 | ~VBox(); 15 | 16 | 17 | int r1, g1, b1, r2, g2, b2; 18 | }; 19 | 20 | 21 | class MMCQ 22 | { 23 | public: 24 | explicit MMCQ(QString file, bool debug_flag, bool kcm_flag); 25 | ~MMCQ(); 26 | 27 | QList get_palette(int color_count=10, int quality=10); 28 | int get_color_index(int r, int g, int b); 29 | 30 | private: 31 | bool debug_flag = false; 32 | bool kcm_flag = false; 33 | int sigbits = 5; 34 | int rshift = 8 - sigbits; 35 | double fract_by_populations = 0.75; 36 | int max_iter = 1000; 37 | QImage *img; 38 | int h = 0; 39 | int w = 0; 40 | std::vector pixels; 41 | std::unordered_map histo; 42 | 43 | int get_vbox_color_sum(VBox v); 44 | void calc_histo(); 45 | VBox gen_vbox(); 46 | std::vector do_median_cut(VBox v); 47 | QColor get_vbox_avg(VBox v); 48 | std::vector quantize(int max_color); 49 | 50 | template 51 | void quantize_iter(T &t, int target); 52 | 53 | }; 54 | 55 | 56 | 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/qml/Header.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.2 2 | 3 | import QtQuick.Layouts 1.1 4 | import QtQuick.Controls 1.4 5 | import QtQuick.Controls.Styles 1.4 6 | import QtGraphicalEffects 1.0 7 | 8 | import org.kde.plasma.core 2.0 as PlasmaCore 9 | import org.kde.plasma.components 2.0 as PlasmaComponents 10 | import org.kde.plasma.extras 2.0 as PlasmaExtras 11 | 12 | Item { 13 | property alias text: title.text 14 | id: root 15 | implicitHeight: title.height + 10 16 | 17 | PlasmaExtras.Heading { 18 | id: title 19 | text: 'Title' 20 | level: 2 21 | 22 | anchors { 23 | top: root.top 24 | topMargin: units.smallSpacing 25 | left: root.left 26 | right: root.right 27 | } 28 | 29 | /* horizontalAlignment: Text.AlignHCenter */ 30 | /* verticalAlignment: Text.AlignTop */ 31 | /* wrapMode: Text.WordWrap */ 32 | /* font.underline: root.activeFocus */ 33 | } 34 | 35 | /* Rectangle { */ 36 | /* id: line */ 37 | /* anchors { */ 38 | /* top: title.bottom */ 39 | /* /\* topMargin: units.smallSpacing *\/ */ 40 | /* left: root.left */ 41 | /* right: root.right */ 42 | /* } */ 43 | /* /\* width: root.width *\/ */ 44 | /* height: 1 */ 45 | /* color: "black" */ 46 | /* } */ 47 | 48 | } 49 | -------------------------------------------------------------------------------- /po/kcm_colorful.pot: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the kcm_colorful package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: kcm_colorful\n" 10 | "Report-Msgid-Bugs-To: me@isoasflus.com\n" 11 | "POT-Creation-Date: 2019-04-04 11:28+0800\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=CHARSET\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: src/kcm_colorful.cpp:33 21 | #, kde-format 22 | msgid "Author" 23 | msgstr "" 24 | 25 | #: src/kcm_colorful.cpp:29 26 | #, kde-format 27 | msgid "Colorful" 28 | msgstr "" 29 | 30 | #: src/qml/Wallpaper.qml:164 31 | #, kde-format 32 | msgid "Generate colors based on wallpaper" 33 | msgstr "" 34 | 35 | #: src/kcm_colorful.cpp:30 36 | #, kde-format 37 | msgid "Make your KDE Plasma colorful" 38 | msgstr "" 39 | 40 | #: src/qml/main.qml:44 41 | #, kde-format 42 | msgid "Recent Colors" 43 | msgstr "" 44 | 45 | #: src/qml/main.qml:64 46 | #, kde-format 47 | msgid "Recommended Colors" 48 | msgstr "" 49 | 50 | #: src/qml/Wallpaper.qml:150 51 | #, kde-format 52 | msgid "Refresh wallpaper" 53 | msgstr "" 54 | 55 | #: src/qml/main.qml:25 56 | #, kde-format 57 | msgid "Wallpaper" 58 | msgstr "" 59 | -------------------------------------------------------------------------------- /po/zh_TW.po: -------------------------------------------------------------------------------- 1 | # Chinese translations for kcm_colorful package. 2 | # Copyright (C) 2019 THE kcm_colorful'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the kcm_colorful package. 4 | # pan93412 , 2019. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: kcm_colorful\n" 9 | "Report-Msgid-Bugs-To: me@isoasflus.com\n" 10 | "POT-Creation-Date: 2019-04-04 15:13+0800\n" 11 | "PO-Revision-Date: 2019-04-04 15:10+0800\n" 12 | "Last-Translator: \n" 13 | "Language-Team: Chinese (traditional)\n" 14 | "Language: zh_TW\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: src/kcm_colorful.cpp:33 20 | #, kde-format 21 | msgid "Author" 22 | msgstr "作者" 23 | 24 | #: src/kcm_colorful.cpp:29 25 | #, kde-format 26 | msgid "Colorful" 27 | msgstr "多彩" 28 | 29 | #: src/qml/Wallpaper.qml:164 30 | #, kde-format 31 | msgid "Generate colors based on wallpaper" 32 | msgstr "產生基於桌布的顏色" 33 | 34 | #: src/kcm_colorful.cpp:30 35 | #, kde-format 36 | msgid "Make your KDE Plasma colorful" 37 | msgstr "讓您的 KDE Plasma 更加多彩" 38 | 39 | #: src/qml/main.qml:44 40 | #, kde-format 41 | msgid "Recent Colors" 42 | msgstr "最近顏色" 43 | 44 | #: src/qml/main.qml:64 45 | #, kde-format 46 | msgid "Recommended Colors" 47 | msgstr "建議顏色" 48 | 49 | #: src/qml/Wallpaper.qml:150 50 | #, kde-format 51 | msgid "Refresh wallpaper" 52 | msgstr "重新載入桌布" 53 | 54 | #: src/qml/main.qml:25 55 | #, kde-format 56 | msgid "Wallpaper" 57 | msgstr "桌布" 58 | -------------------------------------------------------------------------------- /po/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | FIND_PROGRAM(GETTEXT_MSGFMT_EXECUTABLE msgfmt) 2 | 3 | IF(NOT GETTEXT_MSGFMT_EXECUTABLE) 4 | MESSAGE( 5 | "------ 6 | NOTE: msgfmt not found. Translations will *not* be installed 7 | ------") 8 | ELSE(NOT GETTEXT_MSGFMT_EXECUTABLE) 9 | 10 | SET(catalogname kcm_colorful) 11 | 12 | ADD_CUSTOM_TARGET(translations ALL) 13 | FILE(GLOB PO_FILES *.po) 14 | # SET(GMO_FILES) 15 | 16 | FOREACH(_poFile ${PO_FILES}) 17 | GET_FILENAME_COMPONENT(_poFileName ${_poFile} NAME) 18 | STRING(REGEX REPLACE "^${catalogname}_?" "" _langCode ${_poFileName} ) 19 | STRING(REGEX REPLACE "\\.po$" "" _langCode ${_langCode} ) 20 | 21 | IF( _langCode ) 22 | GET_FILENAME_COMPONENT(_lang ${_poFile} NAME_WE) 23 | SET(_gmoFile ${CMAKE_CURRENT_BINARY_DIR}/${_lang}.gmo) 24 | 25 | ADD_CUSTOM_COMMAND(TARGET translations 26 | COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} --check -o ${_gmoFile} ${_poFile} 27 | DEPENDS ${_poFile}) 28 | INSTALL(FILES ${_gmoFile} DESTINATION ${LOCALE_INSTALL_DIR}/${_langCode}/LC_MESSAGES/ RENAME ${catalogname}.mo) 29 | LIST(APPEND GMO_FILES ${_gmoFile}) 30 | ENDIF( _langCode ) 31 | 32 | ENDFOREACH(_poFile ${PO_FILES}) 33 | 34 | # ADD_CUSTOM_TARGET(translations ALL DEPENDS ${GMO_FILES}) 35 | 36 | ENDIF(NOT GETTEXT_MSGFMT_EXECUTABLE) 37 | -------------------------------------------------------------------------------- /extract-messages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | BASEDIR=$(cd `dirname $0`; pwd) # root of translatable sources 3 | PROJECT="kcm_colorful" # project name 4 | WDIR="${BASEDIR}/po" # working dir 5 | 6 | 7 | echo "Preparing rc files" 8 | cd ${BASEDIR} 9 | # we use simple sorting to make sure the lines do not jump around too much from system to system 10 | find . -name '*.rc' -o -name '*.ui' -o -name '*.kcfg'| sort > ${WDIR}/rcfiles.list 11 | xargs --arg-file=${WDIR}/rcfiles.list extractrc > ${WDIR}/rc.cpp 12 | cd ${WDIR} 13 | echo "Done preparing rc files" 14 | 15 | 16 | echo "Extracting messages" 17 | cd ${BASEDIR} 18 | # see above on sorting 19 | find . -name '*.cpp' -o -name '*.h' -o -name '*.c' -o -name '*.qml' | sort > ${WDIR}/infiles.list 20 | echo "rc.cpp" >> ${WDIR}/infiles.list 21 | cd ${WDIR} 22 | xgettext --package-name=$PROJECT --add-comments --sort-output --msgid-bugs-address=me@isoasflus.com \ 23 | --from-code=UTF-8 -C --kde -ci18n -ki18n:1 -ki18nc:1c,2 -ki18np:1,2 -ki18ncp:1c,2,3 -ktr2i18n:1 \ 24 | -kI18N_NOOP:1 -kI18N_NOOP2:1c,2 -kaliasLocale -kki18n:1 -kki18nc:1c,2 -kki18np:1,2 -kki18ncp:1c,2,3 \ 25 | --files-from=infiles.list -D ${BASEDIR} -D ${WDIR} -o ${PROJECT}.pot || { echo "error while calling xgettext. aborting."; exit 1; } 26 | echo "Done extracting messages" 27 | 28 | 29 | echo "Merging translations" 30 | catalogs=`find . -name '*.po'` 31 | for cat in $catalogs; do 32 | echo $cat 33 | msgmerge -q --backup=none -U $cat ${PROJECT}.pot 34 | done 35 | echo "Done merging translations" 36 | 37 | 38 | echo "Cleaning up" 39 | cd ${WDIR} 40 | rm rcfiles.list infiles.list rc.cpp 41 | echo "All Done! :)" 42 | -------------------------------------------------------------------------------- /po/zh_CN.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the kcm_colorful package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: kcm_colorful\n" 9 | "Report-Msgid-Bugs-To: me@isoasflus.com\n" 10 | "POT-Creation-Date: 2019-04-04 11:28+0800\n" 11 | "PO-Revision-Date: 2019-04-04 11:30+0800\n" 12 | "Last-Translator: \n" 13 | "Language-Team: \n" 14 | "Language: zh_CN\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "X-Generator: Poedit 2.2.1\n" 19 | 20 | #: src/kcm_colorful.cpp:33 21 | #, kde-format 22 | msgid "Author" 23 | msgstr "作者" 24 | 25 | #: src/kcm_colorful.cpp:29 26 | #, kde-format 27 | msgid "Colorful" 28 | msgstr "多彩" 29 | 30 | #: src/qml/Wallpaper.qml:164 31 | #, kde-format 32 | msgid "Generate colors based on wallpaper" 33 | msgstr "根据当前壁纸生成色彩" 34 | 35 | #: src/kcm_colorful.cpp:30 36 | #, kde-format 37 | msgid "Make your KDE Plasma colorful" 38 | msgstr "让您的KDE丰富多彩" 39 | 40 | #: src/qml/main.qml:44 41 | #, kde-format 42 | msgid "Recent Colors" 43 | msgstr "最近使用" 44 | 45 | #: src/qml/main.qml:64 46 | #, kde-format 47 | msgid "Recommended Colors" 48 | msgstr "推荐色彩" 49 | 50 | #: src/qml/Wallpaper.qml:150 51 | #, kde-format 52 | msgid "Refresh wallpaper" 53 | msgstr "刷新壁纸" 54 | 55 | #: src/qml/main.qml:25 56 | #, kde-format 57 | msgid "Wallpaper" 58 | msgstr "壁纸" 59 | 60 | #~ msgctxt "EMAIL OF TRANSLATORS" 61 | #~ msgid "Your emails" 62 | #~ msgstr "您的邮箱" 63 | 64 | #~ msgctxt "NAME OF TRANSLATORS" 65 | #~ msgid "Your names" 66 | #~ msgstr "您的名字" 67 | -------------------------------------------------------------------------------- /src/qml/colors.js: -------------------------------------------------------------------------------- 1 | function color_table() 2 | { 3 | return [{"name": "default", "c": "#ffffff"}, 4 | {"name": "default", "c": "#000000"}, 5 | {"name": "default", "c": "#FFCCCC"}, 6 | {"name": "default", "c": "#FF9999"}, 7 | {"name": "default", "c": "#FF6666"}, 8 | {"name": "default", "c": "#CC3333"}, 9 | {"name": "default", "c": "#FF0033"}, 10 | {"name": "default", "c": "#FFCC99"}, 11 | {"name": "default", "c": "#FF9966"}, 12 | {"name": "default", "c": "#FF9900"}, 13 | {"name": "default", "c": "#FF6600"}, 14 | {"name": "default", "c": "#FFFF00"}, 15 | {"name": "default", "c": "#CCCC33"}, 16 | {"name": "default", "c": "#CCFF99"}, 17 | {"name": "default", "c": "#009966"}, 18 | {"name": "default", "c": "#339933"}, 19 | {"name": "default", "c": "#CCCC66"}, 20 | {"name": "default", "c": "#66CCCC"}, 21 | {"name": "default", "c": "#66CC99"}, 22 | {"name": "default", "c": "#339999"}, 23 | {"name": "default", "c": "#CCFFFF"}, 24 | {"name": "default", "c": "#3399CC"}, 25 | {"name": "default", "c": "#99CCFF"}, 26 | {"name": "default", "c": "#6699CC"}, 27 | {"name": "default", "c": "#9999FF"}, 28 | {"name": "default", "c": "#6666FF"}, 29 | {"name": "default", "c": "#6666FF"}, 30 | {"name": "default", "c": "#CCCCFF"}, 31 | {"name": "default", "c": "#9966CC"}, 32 | {"name": "default", "c": "#CC99CC"}, 33 | {"name": "default", "c": "#FF99CC"}, 34 | {"name": "default", "c": "#FF3399"}]; 35 | } 36 | -------------------------------------------------------------------------------- /src/helper/kcmcolorfulhelper.h: -------------------------------------------------------------------------------- 1 | #ifndef KCMCOLORFULHELPER_H 2 | #define KCMCOLORFULHELPER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "mmcq.h" 13 | 14 | class KcmColorfulHelper : public QObject 15 | { 16 | Q_OBJECT 17 | public: 18 | explicit KcmColorfulHelper(QStringList args, QObject *parent = nullptr); 19 | ~KcmColorfulHelper(); 20 | void run(); 21 | 22 | private: 23 | QList palette; 24 | QList palette_16; 25 | MMCQ *mmcq = nullptr; 26 | QColor *c = nullptr; 27 | QMap pt_and_color; 28 | QString colorSchemeName; 29 | QString prevColorSchemeName; 30 | KSharedConfigPtr mConfig; 31 | KSharedConfigPtr tConfig; 32 | QString wallpaperFilePath; 33 | int paletteNum = 8; 34 | int selectNum = 1; 35 | double theme_opacity = 0.6; 36 | uint run_type = 0x00; // bit 1 for theme opacity, bit 2 for theme color. 37 | bool kcm_flag = false; 38 | bool debug_flag = false; 39 | void getPrevCSName(); 40 | void readTemplateCS(); 41 | void changeColorScheme(); 42 | void changeColorSchemeB(); // change ColorScheme based on user's ColorScheme file 43 | void changeColorScheme(KSharedConfigPtr config); 44 | void save(); 45 | void genCSName(); 46 | void saveCSFile(); 47 | QColor addJitter(QColor color); // due to a stupid bug of kde; 48 | bool isDarkTheme(); 49 | void calcColor(); 50 | void setWallpaper(QString pic); 51 | QColor color_refine(QColor color); 52 | void changeThemeOpacity(); 53 | 54 | signals: 55 | 56 | public slots: 57 | // void dealStdOut(); 58 | }; 59 | 60 | #endif // KCMCOLORFULHELPER_H 61 | -------------------------------------------------------------------------------- /src/qml/main.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.2 2 | 3 | import QtQuick.Layouts 1.1 4 | import QtQuick.Controls 1.4 5 | import QtQuick.Controls.Styles 1.4 6 | import QtGraphicalEffects 1.0 7 | 8 | import org.kde.plasma.core 2.0 as PlasmaCore 9 | import org.kde.plasma.components 2.0 as PlasmaComponents 10 | import org.kde.plasma.extras 2.0 as PlasmaExtras 11 | 12 | Rectangle { 13 | id: root 14 | implicitWidth: 500 15 | implicitHeight: 700 16 | color: PlasmaCore.ColorScope.backgroundColor 17 | 18 | Header { 19 | anchors { 20 | top: parent.top 21 | left: parent.left 22 | right: parent.right 23 | } 24 | id: h1 25 | text: i18n("Wallpaper") 26 | } 27 | 28 | Wallpaper { 29 | anchors { 30 | top: h1.bottom 31 | left: parent.left 32 | right: parent.right 33 | } 34 | id: wp 35 | } 36 | 37 | Header { 38 | anchors { 39 | top: wp.bottom 40 | left: parent.left 41 | right: parent.right 42 | } 43 | id: h2 44 | text: i18n("Recent Colors") 45 | } 46 | 47 | ColorWidget { 48 | anchors { 49 | top: h2.bottom 50 | left: parent.left 51 | right: parent.right 52 | } 53 | id: recent_color 54 | cw_type: "cw1" 55 | } 56 | 57 | Header { 58 | anchors { 59 | top: recent_color.bottom 60 | left: parent.left 61 | right: parent.right 62 | } 63 | id: h3 64 | text: i18n("Recommended Colors") 65 | } 66 | 67 | ColorWidget { 68 | anchors { 69 | top: h3.bottom 70 | left: parent.left 71 | right: parent.right 72 | /* bottom: parent.bottom */ 73 | } 74 | height: (units.iconSizes.medium + units.smallSpacing) * 4 75 | id: recommended_color 76 | cw_type: "cw2" 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /TRANSLATING.md: -------------------------------------------------------------------------------- 1 | # `kcm-colorful` translate tutorial 2 | ## STEP TO TRANSLATE 3 | ### 1. TRANSLATE THE PO FILE (HIGH PRIORITY) 4 | The PO file stored the string which is in settings interface, for example: "Generate colors based on wallpaper". 5 | 6 | If your language has NEVER translated, you should generate the po file of your language: 7 | 8 | ``` 9 | [translate@tutorial kcm-colorful]$ bash extract-messages.sh 10 | [translate@tutorial kcm-colorful]$ cd po 11 | [translate@tutorial po]$ msginit -l (your_language) -i kcm_colorful.pot 12 | ``` 13 | 14 | and then, open that PO file with the PO editor you prefer to use. 15 | 16 | If your language has translated but not latest or incompleted, just run "extract-messages.sh" 17 | and that tool will merge the po file in `po` directory. 18 | 19 | ``` 20 | [translate@tutorial kcm-colorful]$ bash extract-messages.sh 21 | ``` 22 | 23 | and then, open the PO file of your language in `po` directory. 24 | 25 | ### 2. TRANSLATE THE DESKTOP FILE (MEDIUM PRIORITY) 26 | The desktop file stored the name and description of kcm-colorful in KDE System Settings. 27 | 28 | First, open `kcm_colorful.desktop` in `src` directory with the text editor you prefer to use. 29 | 30 | And then, you might see the following text: 31 | ```desktop 32 | [Desktop Entry] 33 | ...omitted 34 | 35 | Name=Colorful 36 | Name[zh_CN]=多彩 37 | Comment=Make your KDE Plasma colorful 38 | Comment[zh_CN]=让您的KDE Plasma丰富多彩 39 | X-KDE-Keywords=Color, Theme 40 | X-KDE-Keywords[zh_CN]=Color, Theme,色彩,颜色,主题 41 | ``` 42 | 43 | Just add the localized translation like `zh_CN` does, for example: 44 | ``` 45 | Name=Colorful 46 | Name[zh_CN]=多彩 47 | Name[LANG_CODE]=(Translation) 48 | Comment=Make your KDE Plasma colorful 49 | Comment[zh_CN]=让您的KDE Plasma丰富多彩 50 | Comment[LANG_CODE]=(Translation) 51 | X-KDE-Keywords=Color, Theme 52 | X-KDE-Keywords[zh_CN]=Color, Theme,色彩,颜色,主题 53 | X-KDE-Keywords[LANG_CODE]=(Translation) 54 | ``` 55 | 56 | > **NOTE**: The keywords use "," as the delimiter. 57 | 58 | ### 3. Push and Create a Pull Request 59 | And then, you just need to wait for approve :) 60 | -------------------------------------------------------------------------------- /src/artworks/pallete.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/qml/WButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.2 2 | 3 | import QtQuick.Layouts 1.1 4 | import QtQuick.Controls 1.4 5 | import QtQuick.Controls.Styles 1.4 6 | import QtGraphicalEffects 1.0 7 | 8 | import org.kde.plasma.core 2.0 as PlasmaCore 9 | import org.kde.plasma.components 2.0 as PlasmaComponents 10 | 11 | Item { 12 | id: root 13 | property string text: '' 14 | property alias iconSource: icon.source 15 | /* property alias containsMouse: mouseArea.containsMouse */ 16 | /* property alias onBtn: p.onButton */ 17 | /* property alias iconSource: icon.source */ 18 | /* property alias font: label.font */ 19 | signal clicked 20 | 21 | activeFocusOnTab: true 22 | 23 | property int iconSize: units.gridUnit * 2 24 | 25 | implicitWidth: iconSize + units.largeSpacing * 2 26 | implicitHeight: iconSize + units.smallSpacing 27 | 28 | /* Behavior on opacity { */ 29 | /* OpacityAnimator { */ 30 | /* duration: units.longDuration */ 31 | /* easing.type: Easing.InOutQuad */ 32 | /* } */ 33 | /* } */ 34 | 35 | PlasmaCore.IconItem { 36 | id: icon 37 | anchors { 38 | top: parent.top 39 | horizontalCenter: parent.horizontalCenter 40 | } 41 | width: iconSize 42 | height: iconSize 43 | /* source: './refresh.png' */ 44 | colorGroup: PlasmaCore.ColorScope.colorGroup 45 | /* active: mouseArea.containsMouse || root.activeFocus */ 46 | active: mouseArea.containsMouse 47 | /* ? onBtn = true : ((onBtn = false) == "This must be false!") */ 48 | } 49 | 50 | MouseArea { 51 | id: mouseArea 52 | hoverEnabled: true 53 | /* onClicked: root.clicked() */ 54 | onClicked: { 55 | root.clicked() 56 | } 57 | anchors.fill: parent 58 | 59 | onEntered: { 60 | label.text = root.text 61 | /* wallpaper.state = "on" */ 62 | } 63 | onExited: { 64 | label.text = '' 65 | /* wallpaper.state = "off" */ 66 | /* onBtn = false */ 67 | } 68 | } 69 | 70 | /* Keys.onEnterPressed: clicked() */ 71 | /* Keys.onReturnPressed: clicked() */ 72 | /* Keys.onSpacePressed: clicked() */ 73 | 74 | /* Accessible.onPressAction: clicked() */ 75 | /* Accessible.role: Accessible.Button */ 76 | /* Accessible.name: label.text */ 77 | } 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KCM-Colorful 2 | [English Version](https://github.com/IsoaSFlus/kcm-colorful/blob/master/README.en.md) 3 | 4 | 根据当前的壁纸改变KDE Plasma的颜色。 5 | 6 | ## Requirements 7 | * Qt5 8 | * KDE Frameworks 5 9 | * cmake 10 | * extra-cmake-modules 11 | * GNU gettext utilities 12 | 13 | ## Build 14 | ``` 15 | git clone --recursive https://github.com/IsoaSFlus/kcm-colorful.git 16 | cd kcm-colorful 17 | mkdir build 18 | cd ./build 19 | cmake ../ 20 | make 21 | sudo make install 22 | #Then set your plasma desktop theme to "Colorful" for best experience. 23 | ``` 24 | 25 | ## Installation 26 | ### Archlinux (AUR) 27 | ``` 28 | yaourt -S kcm-colorful-git # or any other aur helper 29 | ``` 30 | Thanks for [@VOID001](https://github.com/VOID001)'s maintenance. 31 | 32 | ### Archlinux ([ArchlinuxCN](https://wiki.archlinux.org/index.php/Unofficial_user_repositories#archlinuxcn) repo) 33 | ``` 34 | sudo pacman -S kcm-colorful-git 35 | ``` 36 | Thanks for [@MarvelousBlack](https://github.com/MarvelousBlack)'s maintenance. 37 | 38 | ## Screenshots 39 | ![a](https://raw.githubusercontent.com/IsoaSFlus/kcm-colorful/master/screenshots/a.png) 40 | ![b](https://raw.githubusercontent.com/IsoaSFlus/kcm-colorful/master/screenshots/b.png) 41 | 42 | ## TODO 43 | - [x] 实现命令行helper 44 | - [x] 将颜色提取算法移植至C++并剔除Python依赖 45 | - [x] 实现KCM集成至KDE设置 46 | - [ ] 利用机器学习算法进一步优化主题色选择 47 | 48 | ## Postscript 49 | 除了KCM,本项目还提供了一个cli的程序,可以供用户配合脚本使用: 50 | 51 | ``` 52 | Usage: kcmcolorfulhelper [options] 53 | Helper for kcm-colorful. 54 | Project address: https://github.com/IsoaSFlus/kcm-colorful 55 | 56 | Options: 57 | -h, --help Displays this help. 58 | -p, --picture Picture to extract color. 59 | -c, --color Set color manually, eg: #1234ef. 60 | -s, --set-as-wallpaper Set picture specified by "-p" as wallpaper. 61 | -d, --debug Show debug info. 62 | -n, --number Select the Nth color in candidate list. Default is 63 | 1. 64 | -o, --opacity Set the opacity of theme, from 0 to 1(1 is opaque). 65 | ``` 66 | 67 | **如果你想实现像我截图中一样的效果,那么还需要一些额外的设置。** 68 | 69 | 首先,打开KDE的系统设置->桌面行为->桌面特效,找到“模糊”项并使能(可根据个人喜好调整该项设置中的模糊程度以及噪点厚度),依据个人喜好开启或关闭“背景对比度”项。 70 | 71 | 之后,打开KDE的系统设置->工作空间主题->桌面主题,设置主题为“Colorful”(当然,前提是你安装了本项目)。 72 | 73 | 第三,安装[BreezeBlurred](https://github.com/alex47/BreezeBlurred),这个项目在原版Breeze窗口装饰主题的基础上提供透明效果。在安装完成后打开KDE的系统设置->应用程序风格->窗口装饰,找到该主题“微风”(注意,你会发现你其中有复数个“微风”因为原版也叫“微风”)并打开其配置菜单,关闭绘制窗口背景渐变并调整透明度(推荐60%,因为这与桌面主题一致),如下图。 74 | ![](https://i.loli.net/2018/09/04/5b8e0ce1a79a7.png) 75 | 76 | 最后,如果你对我截图左侧的dock感兴趣,请安装[Latte-Dock](https://github.com/psifidotos/Latte-Dock)。 77 | -------------------------------------------------------------------------------- /src/helper/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "kcmcolorfulhelper.h" 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | QCoreApplication a(argc, argv); 7 | 8 | QCommandLineParser parser; 9 | parser.setApplicationDescription("Helper for kcm-colorful.\nProject address: https://github.com/IsoaSFlus/kcm-colorful"); 10 | parser.addHelpOption(); 11 | // parser.addVersionOption(); 12 | 13 | QCommandLineOption pictureOption(QStringList() << "p" << "picture", "Picture to extract color.", "file", "kcmcolorful-NOPIC"); 14 | parser.addOption(pictureOption); 15 | QCommandLineOption colorOption(QStringList() << "c" << "color", "Set color manually, eg: #1234ef.", "colorcode", "kcmcolorful-NOCOLOR"); 16 | parser.addOption(colorOption); 17 | QCommandLineOption paletteOption("palette-number", "Set the number of colors of palette in the first color extraction. Valid number is between 1 to 16, default is 8.", "int", "8"); 18 | paletteOption.setFlags(QCommandLineOption::HiddenFromHelp); 19 | parser.addOption(paletteOption); 20 | QCommandLineOption setWPOption(QStringList() << "s" << "set-as-wallpaper", "Set picture specified by \"-p\" as wallpaper."); 21 | parser.addOption(setWPOption); 22 | QCommandLineOption debugOption(QStringList() << "d" << "debug", "Show debug info."); 23 | parser.addOption(debugOption); 24 | QCommandLineOption kcmOption("kcm"); 25 | kcmOption.setFlags(QCommandLineOption::HiddenFromHelp); 26 | parser.addOption(kcmOption); 27 | QCommandLineOption colorNumOption(QStringList() << "n" << "number", "Select the Nth color in candidate list. Default is 1.", "int", "1"); 28 | parser.addOption(colorNumOption); 29 | QCommandLineOption opacityOption(QStringList() << "o" << "opacity", "Set the opacity of theme, from 0 to 1(1 is opaque).", "float", "notset"); 30 | parser.addOption(opacityOption); 31 | 32 | 33 | parser.process(a); 34 | 35 | if (QCoreApplication::arguments().size() <= 1) { 36 | qDebug().noquote() << "Error: You should at least specify one argument."; 37 | parser.showHelp(); 38 | } 39 | 40 | QStringList args; 41 | args << parser.value(pictureOption); 42 | args << parser.value(colorOption); 43 | args << parser.value(paletteOption); 44 | args << (parser.isSet(setWPOption) ? "true" : " false"); 45 | args << (parser.isSet(debugOption) ? "true" : " false"); 46 | args << (parser.isSet(kcmOption) ? "true" : " false"); 47 | args << parser.value(colorNumOption); 48 | args << parser.value(opacityOption); 49 | KcmColorfulHelper kch(args); 50 | kch.run(); 51 | 52 | // return a.exec(); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /src/qml/ColorUnitW.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.2 2 | 3 | import QtQuick.Layouts 1.1 4 | import QtQuick.Controls 1.4 5 | import QtQuick.Controls.Styles 1.4 6 | import QtGraphicalEffects 1.0 7 | 8 | import org.kde.plasma.core 2.0 as PlasmaCore 9 | import org.kde.plasma.components 2.0 as PlasmaComponents 10 | 11 | Item { 12 | id: root 13 | width: units.iconSizes.large 14 | height: width 15 | property alias inner_color: inner.color 16 | property string c_name: "null" 17 | state: "off" 18 | states: [ 19 | State { 20 | name: "on" 21 | PropertyChanges { 22 | target: root 23 | scale: 1.3 24 | } 25 | }, 26 | State { 27 | name: "off" 28 | PropertyChanges { 29 | target: root 30 | scale: 1 31 | } 32 | } 33 | ] 34 | transitions: [ 35 | Transition { 36 | from: "off" 37 | to: "on" 38 | NumberAnimation { 39 | target: root 40 | property: "scale" 41 | duration: 200 42 | /* easing.type: Easing.InOutQuad */ 43 | easing.type: Easing.OutCubic 44 | } 45 | }, 46 | Transition { 47 | from: "on" 48 | to: "off" 49 | NumberAnimation { 50 | target: root 51 | property: "scale" 52 | duration: 200 53 | /* easing.type: Easing.InOutQuad */ 54 | easing.type: Easing.OutCubic 55 | } 56 | } 57 | ] 58 | 59 | Rectangle { 60 | id: inner 61 | width: units.iconSizes.large 62 | height: width 63 | radius: width / 2 64 | border.width: width * 0.03 65 | border.color: PlasmaCore.ColorScope.textColor 66 | /* border.width: width / 10 */ 67 | /* border.color: "transparent" */ 68 | 69 | /* Behavior on border.color { */ 70 | /* ColorAnimation { */ 71 | /* duration: units.longDuration * 2 */ 72 | /* /\* easing.type: Easing.InOutQuad *\/ */ 73 | /* } */ 74 | /* } */ 75 | 76 | MouseArea { 77 | id: ma 78 | anchors.fill: parent 79 | hoverEnabled: true 80 | onEntered: { 81 | /* inner.border.color = PlasmaCore.ColorScope.highlightColor */ 82 | /* wallpaper.state = "on" */ 83 | root.state = "on" 84 | } 85 | onExited: { 86 | /* inner.border.color = "transparent" */ 87 | root.state = "off" 88 | /* wallpaper.state = "off" */ 89 | } 90 | onClicked: cuw_row.cuw_clicked(inner.color) 91 | } 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /README.en.md: -------------------------------------------------------------------------------- 1 | # KCM-Colorful 2 | Change your KDE Plasma's color based on your wallpaper. 3 | 4 | ## Requirements 5 | * Qt5 6 | * KDE Frameworks 5 7 | * cmake 8 | * extra-cmake-modules 9 | * GNU gettext utilities 10 | 11 | ## Build 12 | ``` 13 | git clone --recursive https://github.com/IsoaSFlus/kcm-colorful.git 14 | cd kcm-colorful 15 | mkdir build 16 | cd ./build 17 | cmake ../ 18 | make 19 | sudo make install 20 | #Then set your plasma desktop theme to "Colorful" for best experience. 21 | ``` 22 | 23 | ## Installation 24 | ### Archlinux (AUR) 25 | ``` 26 | yaourt -S kcm-colorful-git # or any other aur helper 27 | ``` 28 | Thanks for [@VOID001](https://github.com/VOID001)'s work. 29 | 30 | ### Archlinux ([ArchlinuxCN](https://wiki.archlinux.org/index.php/Unofficial_user_repositories#archlinuxcn) repo) 31 | ``` 32 | sudo pacman -S kcm-colorful-git 33 | ``` 34 | Thanks for [@MarvelousBlack](https://github.com/MarvelousBlack)'s maintenance. 35 | 36 | ## Screenshots 37 | ![a](https://raw.githubusercontent.com/IsoaSFlus/kcm-colorful/master/screenshots/a.png) 38 | ![b](https://raw.githubusercontent.com/IsoaSFlus/kcm-colorful/master/screenshots/b.png) 39 | 40 | ## TODO 41 | - [x] Implement CLI helper 42 | - [x] Port color extraction code to C++ 43 | - [x] Implement KCM 44 | - [ ] Improve color selection by ML 45 | 46 | ## Postscript 47 | Besides KCM, this project also provides a CLI program that could be used by your script: 48 | ``` 49 | Usage: kcmcolorfulhelper [options] 50 | Helper for kcm-colorful. 51 | Project address: https://github.com/IsoaSFlus/kcm-colorful 52 | 53 | Options: 54 | -h, --help Displays this help. 55 | -p, --picture Picture to extract color. 56 | -c, --color Set color manually, eg: #1234ef. 57 | -s, --set-as-wallpaper Set picture specified by "-p" as wallpaper. 58 | -d, --debug Show debug info. 59 | -n, --number Select the Nth color in candidate list. Default is 60 | 1. 61 | -o, --opacity Set the opacity of theme, from 0 to 1(1 is opaque). 62 | ``` 63 | 64 | **If you want to make your KDE look like the screenshots above, just follow these steps.** 65 | 66 | First,open KDE's systemsettings->Desktop Behavior->Desktop Effects. Find "blur" and enable it(You can set the Blur strength and Noise strength to preferable value). 67 | 68 | Then,open KDE's systemsettings->Workspace Theme->Desktop Theme, set your desktop theme to “Colorful”. 69 | 70 | Third,install [BreezeBlurred](https://github.com/alex47/BreezeBlurred),this project provide a blurred version of Breeze window decoration. After installation, open KDE's systemsettings->Application Style->Window Decorations. Find the item named "BreezeBlur" and click "Configure BleezeBlur". Disable "Draw window backbround gradient" and set the Opacity(I'll recommend 60%, because it is the same as desktop theme's). 71 | 72 | Finally,if your are curious about the dock on the Screenshots,just check out [Latte-Dock](https://github.com/psifidotos/Latte-Dock). 73 | -------------------------------------------------------------------------------- /schemes/ColorfulDark.colors: -------------------------------------------------------------------------------- 1 | [ColorEffects:Disabled] 2 | Color=56,56,56 3 | ColorAmount=0 4 | ColorEffect=0 5 | ContrastAmount=0.65 6 | ContrastEffect=1 7 | IntensityAmount=0.1 8 | IntensityEffect=2 9 | 10 | [ColorEffects:Inactive] 11 | ChangeSelectionColor=true 12 | Color=112,111,110 13 | ColorAmount=0.025 14 | ColorEffect=2 15 | ContrastAmount=0.1 16 | ContrastEffect=2 17 | Enable=false 18 | IntensityAmount=0 19 | IntensityEffect=0 20 | 21 | [Colors:Button] 22 | BackgroundAlternate=77,77,77 23 | BackgroundNormal=49,54,59 24 | DecorationFocus=61,174,233 25 | DecorationHover=61,174,233 26 | ForegroundActive=61,174,233 27 | ForegroundInactive=189,195,199 28 | ForegroundLink=41,128,185 29 | ForegroundNegative=218,68,83 30 | ForegroundNeutral=246,116,0 31 | ForegroundNormal=239,240,241 32 | ForegroundPositive=39,174,96 33 | ForegroundVisited=127,140,141 34 | 35 | [Colors:Complementary] 36 | BackgroundAlternate=59,64,69 37 | BackgroundNormal=49,54,59 38 | DecorationFocus=30,146,255 39 | DecorationHover=61,174,230 40 | ForegroundActive=246,116,0 41 | ForegroundInactive=175,176,179 42 | ForegroundLink=61,174,230 43 | ForegroundNegative=237,21,21 44 | ForegroundNeutral=201,206,59 45 | ForegroundNormal=239,240,241 46 | ForegroundPositive=17,209,22 47 | ForegroundVisited=61,174,230 48 | 49 | [Colors:Selection] 50 | BackgroundAlternate=29,153,243 51 | BackgroundNormal=61,174,233 52 | DecorationFocus=61,174,233 53 | DecorationHover=61,174,233 54 | ForegroundActive=252,252,252 55 | ForegroundInactive=239,240,241 56 | ForegroundLink=253,188,75 57 | ForegroundNegative=218,68,83 58 | ForegroundNeutral=246,116,0 59 | ForegroundNormal=239,240,241 60 | ForegroundPositive=39,174,96 61 | ForegroundVisited=189,195,199 62 | 63 | [Colors:Tooltip] 64 | BackgroundAlternate=77,77,77 65 | BackgroundNormal=49,54,59 66 | DecorationFocus=61,174,233 67 | DecorationHover=61,174,233 68 | ForegroundActive=61,174,233 69 | ForegroundInactive=189,195,199 70 | ForegroundLink=41,128,185 71 | ForegroundNegative=218,68,83 72 | ForegroundNeutral=246,116,0 73 | ForegroundNormal=239,240,241 74 | ForegroundPositive=39,174,96 75 | ForegroundVisited=127,140,141 76 | 77 | [Colors:View] 78 | BackgroundAlternate=49,54,59 79 | BackgroundNormal=35,38,41 80 | DecorationFocus=61,174,233 81 | DecorationHover=61,174,233 82 | ForegroundActive=61,174,233 83 | ForegroundInactive=189,195,199 84 | ForegroundLink=41,128,185 85 | ForegroundNegative=218,68,83 86 | ForegroundNeutral=246,116,0 87 | ForegroundNormal=230,230,230 88 | ForegroundPositive=39,174,96 89 | ForegroundVisited=127,140,141 90 | 91 | [Colors:Window] 92 | BackgroundAlternate=77,77,77 93 | BackgroundNormal=49,54,59 94 | DecorationFocus=61,174,233 95 | DecorationHover=61,174,233 96 | ForegroundActive=61,174,233 97 | ForegroundInactive=189,195,199 98 | ForegroundLink=41,128,185 99 | ForegroundNegative=218,68,83 100 | ForegroundNeutral=246,116,0 101 | ForegroundNormal=230,230,230 102 | ForegroundPositive=39,174,96 103 | ForegroundVisited=127,140,141 104 | 105 | [General] 106 | ColorScheme=Breeze Dark 107 | Name=ColorfulDark 108 | shadeSortColumn=true 109 | 110 | [KDE] 111 | contrast=4 112 | 113 | [WM] 114 | activeBackground=49,54,59 115 | activeBlend=255,255,255 116 | activeForeground=239,240,241 117 | inactiveBackground=49,54,59 118 | inactiveBlend=75,71,67 119 | inactiveForeground=127,140,141 120 | -------------------------------------------------------------------------------- /schemes/ColorfulLight.colors: -------------------------------------------------------------------------------- 1 | [ColorEffects:Disabled] 2 | Color=56,56,56 3 | ColorAmount=0 4 | ColorEffect=0 5 | ContrastAmount=0.65 6 | ContrastEffect=1 7 | IntensityAmount=0.1 8 | IntensityEffect=2 9 | 10 | [ColorEffects:Inactive] 11 | ChangeSelectionColor=true 12 | Color=112,111,110 13 | ColorAmount=0.025 14 | ColorEffect=2 15 | ContrastAmount=0.1 16 | ContrastEffect=2 17 | Enable=false 18 | IntensityAmount=0 19 | IntensityEffect=0 20 | 21 | [Colors:Button] 22 | BackgroundAlternate=189,195,199 23 | BackgroundNormal=239,240,241 24 | DecorationFocus=61,174,233 25 | DecorationHover=147,206,233 26 | ForegroundActive=61,174,233 27 | ForegroundInactive=127,140,141 28 | ForegroundLink=41,128,185 29 | ForegroundNegative=218,68,83 30 | ForegroundNeutral=246,116,0 31 | ForegroundNormal=35,38,39 32 | ForegroundPositive=39,174,96 33 | ForegroundVisited=127,140,141 34 | 35 | [Colors:Complementary] 36 | BackgroundAlternate=59,64,69 37 | BackgroundNormal=49,54,59 38 | DecorationFocus=30,146,255 39 | DecorationHover=61,174,230 40 | ForegroundActive=147,206,233 41 | ForegroundInactive=175,176,179 42 | ForegroundLink=61,174,230 43 | ForegroundNegative=231,76,60 44 | ForegroundNeutral=253,188,75 45 | ForegroundNormal=239,240,241 46 | ForegroundPositive=46,204,113 47 | ForegroundVisited=61,174,230 48 | 49 | [Colors:Selection] 50 | BackgroundAlternate=29,153,243 51 | BackgroundNormal=61,174,233 52 | DecorationFocus=61,174,233 53 | DecorationHover=147,206,233 54 | ForegroundActive=252,252,252 55 | ForegroundInactive=239,240,241 56 | ForegroundLink=253,188,75 57 | ForegroundNegative=218,68,83 58 | ForegroundNeutral=246,116,0 59 | ForegroundNormal=252,252,252 60 | ForegroundPositive=39,174,96 61 | ForegroundVisited=189,195,199 62 | 63 | [Colors:Tooltip] 64 | BackgroundAlternate=77,77,77 65 | BackgroundNormal=35,38,39 66 | DecorationFocus=61,174,233 67 | DecorationHover=147,206,233 68 | ForegroundActive=61,174,233 69 | ForegroundInactive=189,195,199 70 | ForegroundLink=41,128,185 71 | ForegroundNegative=218,68,83 72 | ForegroundNeutral=246,116,0 73 | ForegroundNormal=252,252,252 74 | ForegroundPositive=39,174,96 75 | ForegroundVisited=127,140,141 76 | 77 | [Colors:View] 78 | BackgroundAlternate=239,240,241 79 | BackgroundNormal=252,252,252 80 | DecorationFocus=61,174,233 81 | DecorationHover=147,206,233 82 | ForegroundActive=61,174,233 83 | ForegroundInactive=127,140,141 84 | ForegroundLink=41,128,185 85 | ForegroundNegative=218,68,83 86 | ForegroundNeutral=246,116,0 87 | ForegroundNormal=35,38,39 88 | ForegroundPositive=39,174,96 89 | ForegroundVisited=127,140,141 90 | 91 | [Colors:Window] 92 | BackgroundAlternate=189,195,199 93 | BackgroundNormal=239,240,241 94 | DecorationFocus=61,174,233 95 | DecorationHover=147,206,233 96 | ForegroundActive=61,174,233 97 | ForegroundInactive=127,140,141 98 | ForegroundLink=41,128,185 99 | ForegroundNegative=218,68,83 100 | ForegroundNeutral=246,116,0 101 | ForegroundNormal=35,38,39 102 | ForegroundPositive=39,174,96 103 | ForegroundVisited=127,140,141 104 | 105 | [General] 106 | ColorScheme=Breeze 107 | Name=ColorfulLight 108 | shadeSortColumn=true 109 | 110 | [KDE] 111 | contrast=4 112 | 113 | [WM] 114 | activeBackground=71,80,87 115 | activeBlend=252,252,252 116 | activeForeground=252,252,252 117 | inactiveBackground=239,240,241 118 | inactiveBlend=75,71,67 119 | inactiveForeground=189,195,199 120 | -------------------------------------------------------------------------------- /src/qml/ColorUnit.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.2 2 | 3 | import QtQuick.Layouts 1.1 4 | import QtQuick.Controls 1.4 5 | import QtQuick.Controls.Styles 1.4 6 | import QtQuick.Dialogs 1.0 7 | import QtGraphicalEffects 1.0 8 | 9 | import org.kde.plasma.core 2.0 as PlasmaCore 10 | import org.kde.plasma.components 2.0 as PlasmaComponents 11 | 12 | Item { 13 | id: root 14 | property alias inner_color: inner.color 15 | property string c_name: "null" 16 | property int cu_index 17 | width: inner.width * 1.3 18 | height: width 19 | state: "off" 20 | states: [ 21 | State { 22 | name: "on" 23 | PropertyChanges { 24 | target: root 25 | scale: 1.3 26 | } 27 | }, 28 | State { 29 | name: "off" 30 | PropertyChanges { 31 | target: root 32 | scale: 1 33 | } 34 | } 35 | ] 36 | transitions: [ 37 | Transition { 38 | from: "off" 39 | to: "on" 40 | NumberAnimation { 41 | target: root 42 | property: "scale" 43 | duration: 200 44 | easing.type: Easing.OutCubic 45 | } 46 | }, 47 | Transition { 48 | from: "on" 49 | to: "off" 50 | NumberAnimation { 51 | target: root 52 | property: "scale" 53 | duration: 200 54 | easing.type: Easing.OutCubic 55 | } 56 | } 57 | ] 58 | Rectangle { 59 | id: inner 60 | width: units.iconSizes.medium * 1.2 61 | height: width 62 | radius: width / 2 63 | border.width: width * 0.03 64 | border.color: PlasmaCore.ColorScope.textColor 65 | anchors.centerIn: parent 66 | 67 | MouseArea { 68 | id: ma 69 | anchors.fill: parent 70 | hoverEnabled: true 71 | acceptedButtons: Qt.LeftButton | Qt.RightButton 72 | onEntered: { 73 | root.state = "on" 74 | } 75 | onExited: { 76 | root.state = "off" 77 | } 78 | onClicked: { 79 | if(mouse.button & Qt.RightButton) { 80 | if (root.c_name != "own" && root.c_name != "default") { 81 | gv.remove_color(root.cu_index); 82 | } 83 | } else { 84 | if (root.c_name != "own") { 85 | gv.cu_clicked(c) 86 | } else { 87 | colorDialog.open() 88 | } 89 | } 90 | } 91 | } 92 | 93 | ColorDialog { 94 | id: colorDialog 95 | /* title: "Please choose a color" */ 96 | onAccepted: { 97 | /* console.log("You chose: " + colorDialog.color) */ 98 | gv.add_color("" + colorDialog.color) 99 | Qt.quit() 100 | } 101 | onRejected: { 102 | /* console.log("Canceled") */ 103 | Qt.quit() 104 | } 105 | /* Component.onCompleted: visible = true */ 106 | } 107 | 108 | PlasmaCore.IconItem { 109 | id: icon 110 | anchors { 111 | /* top: parent.top */ 112 | /* horizontalCenter: parent.horizontalCenter */ 113 | centerIn: parent 114 | } 115 | source: 'kcolorchooser' 116 | width: parent.width * 0.7 117 | height: width 118 | /* source: './refresh.png' */ 119 | colorGroup: PlasmaCore.ColorScope.colorGroup 120 | /* active: mouseArea.containsMouse || root.activeFocus */ 121 | visible: root.c_name != "own" ? false : true 122 | } 123 | 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/artworks/gen-colors.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/qml/ColorWidget.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.2 2 | 3 | import QtQuick.Layouts 1.1 4 | import QtQuick.Controls 1.4 5 | import QtQuick.Controls.Styles 1.4 6 | import QtGraphicalEffects 1.0 7 | 8 | import org.kde.plasma.core 2.0 as PlasmaCore 9 | import org.kde.plasma.components 2.0 as PlasmaComponents 10 | 11 | import "./colors.js" as ColorTable 12 | 13 | 14 | Rectangle { 15 | id: root 16 | property string cw_type 17 | implicitHeight: gv.cellWidth 18 | /* + units.smallSpacing */ 19 | color: "transparent" 20 | 21 | ListModel { 22 | id: colorModel 23 | /* objectName: "gv_model" */ 24 | 25 | /* ListElement { */ 26 | /* name: "Apple" */ 27 | /* c: "red" */ 28 | /* } */ 29 | /* ListElement { */ 30 | /* name: "Orange" */ 31 | /* c: "orange" */ 32 | /* } */ 33 | /* ListElement { */ 34 | /* name: "own" */ 35 | /* c: "yellow" */ 36 | /* } */ 37 | 38 | } 39 | 40 | Component { 41 | id: colorDelegate 42 | ColorUnit { 43 | cu_index: index 44 | inner_color: c 45 | c_name: name 46 | } 47 | } 48 | 49 | /* ColorUnit { */ 50 | /* id: colorDelegate */ 51 | /* cu_index: index */ 52 | /* inner_color: c */ 53 | /* c_name: name */ 54 | /* } */ 55 | 56 | GridView { 57 | id: gv 58 | objectName: "grid_view" 59 | /* Layout.alignment: Qt.AlignCenter */ 60 | signal cu_clicked(string color) 61 | clip: true 62 | 63 | anchors { 64 | fill: parent 65 | /* topMargin: units.smallSpacing * 1.3 */ 66 | } 67 | cellWidth: units.iconSizes.medium * 1.5+ units.smallSpacing 68 | cellHeight: cellWidth 69 | /* anchors.fill: parent */ 70 | model: colorModel 71 | delegate: colorDelegate 72 | remove: Transition { 73 | ParallelAnimation { 74 | NumberAnimation { property: "opacity"; from: 1.0; to: 0; duration: 200} 75 | NumberAnimation { property: "scale"; to: 0; duration: 300; easing.type: Easing.OutCubic} 76 | } 77 | } 78 | add: Transition { 79 | ParallelAnimation { 80 | NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 200} 81 | NumberAnimation { property: "scale"; from: 0; to: 1.0; duration: 300; easing.type: Easing.OutCubic} 82 | } 83 | } 84 | displaced: Transition { 85 | NumberAnimation { properties: "x,y"; duration: 300; easing.type: Easing.OutCubic} 86 | } 87 | move: Transition { 88 | NumberAnimation { properties: "x,y"; duration: 300; easing.type: Easing.OutCubic} 89 | } 90 | 91 | function add_user_color(color_code) { 92 | if (root.cw_type == "cw2") { 93 | colorModel.insert(colorModel.count - 1, {"name": "user", "c": color_code}) 94 | } 95 | } 96 | function prepend_color(color_code) { 97 | if (root.cw_type == "cw1") { 98 | var i = 0; 99 | while (i < 10 && i < colorModel.count) { 100 | if (colorModel.get(i).c == color_code) { 101 | colorModel.move(i, 0, 1); 102 | return; 103 | } 104 | i++; 105 | } 106 | colorModel.insert(0, {"name": "user", "c": color_code}); 107 | while (colorModel.count > 10) { 108 | colorModel.remove(i); 109 | } 110 | } else { 111 | colorModel.insert(0, {"name": "user", "c": color_code}); 112 | } 113 | } 114 | function add_color(color_code) { 115 | var i = colorModel.count - 1; 116 | if (colorModel.get(i).name == "own") { 117 | colorModel.insert(i, {"name": "user", "c": color_code}) 118 | } else { 119 | colorModel.append({"name": "user", "c": color_code}) 120 | } 121 | } 122 | function get_colors() { 123 | var i = colorModel.count - 1; 124 | var r = ""; 125 | while (i >= 0) { 126 | if (colorModel.get(i).name != "user") { 127 | if (colorModel.get(i).name == "own") { 128 | i--; 129 | continue; 130 | } else { 131 | break; 132 | } 133 | } else { 134 | r = colorModel.get(i).c + "," + r; 135 | } 136 | i--; 137 | } 138 | return r; 139 | } 140 | function remove_color(index) { 141 | colorModel.remove(index); 142 | } 143 | 144 | Component.onCompleted: { 145 | if (root.cw_type == "cw2") { 146 | var default_colors = ColorTable.color_table() 147 | for (var i = default_colors.length; i > 0; --i) { 148 | colorModel.insert(0, default_colors[i-1]) 149 | } 150 | colorModel.append({"name": "own", "c": "grey"}) 151 | } 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/qml/Wallpaper.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.2 2 | 3 | import QtQuick.Layouts 1.1 4 | import QtQuick.Controls 1.4 5 | import QtQuick.Controls.Styles 1.4 6 | import QtGraphicalEffects 1.0 7 | 8 | import org.kde.plasma.core 2.0 as PlasmaCore 9 | import org.kde.plasma.components 2.0 as PlasmaComponents 10 | import org.kde.plasma.extras 2.0 as PlasmaExtras 11 | 12 | 13 | Item { 14 | id: root 15 | /* width: 1280 */ 16 | /* height: 720 */ 17 | implicitHeight: wallpaper.height + label.height 18 | Image { 19 | property real factor: 0 20 | property bool onButton: false 21 | id: wallpaper 22 | objectName: "wp_view" 23 | smooth: true 24 | height: units.largeSpacing * 10 25 | anchors { 26 | /* fill: parent */ 27 | top: root.top 28 | left: root.left 29 | right: root.right 30 | /* bottom: label.top */ 31 | } 32 | fillMode: Image.PreserveAspectCrop 33 | state: "off" 34 | 35 | states: [ 36 | State { 37 | name: "on" 38 | PropertyChanges { 39 | target: wallpaper 40 | factor: 1 41 | } 42 | }, 43 | State { 44 | name: "off" 45 | PropertyChanges { 46 | target: wallpaper 47 | factor: 0 48 | } 49 | }, 50 | State { 51 | name: "busy" 52 | PropertyChanges { 53 | target: wallpaper 54 | factor: 1 55 | } 56 | }, 57 | State { 58 | name: "generated" 59 | PropertyChanges { 60 | target: wallpaper 61 | factor: 1 62 | } 63 | } 64 | ] 65 | 66 | transitions: [ 67 | Transition { 68 | from: "off" 69 | to: "on" 70 | ParallelAnimation { 71 | NumberAnimation { 72 | target: wallpaper 73 | property: "factor" 74 | duration: 200 75 | /* easing.type: Easing.InOutQuad */ 76 | } 77 | } 78 | }, 79 | Transition { 80 | from: "on" 81 | to: "off" 82 | ParallelAnimation { 83 | NumberAnimation { 84 | target: wallpaper 85 | property: "factor" 86 | duration: 200 87 | /* easing.type: Easing.InOutQuad */ 88 | } 89 | } 90 | } 91 | ] 92 | } 93 | 94 | FastBlur { 95 | source: wallpaper 96 | id: blur 97 | anchors.fill: wallpaper 98 | radius: 60 * wallpaper.factor 99 | } 100 | 101 | MouseArea { 102 | id: mArea 103 | anchors.fill: wallpaper 104 | hoverEnabled: true 105 | 106 | onEntered: { 107 | if (wallpaper.state == "off") { 108 | wallpaper.state = "on" 109 | } 110 | } 111 | onExited: { 112 | if (wallpaper.state == "on" || wallpaper.state == "generated") { 113 | wallpaper.state = "off" 114 | } 115 | } 116 | 117 | /* onClicked: { */ 118 | /* if (wallpaper.state == "off") { */ 119 | /* wallpaper.state = "on" */ 120 | /* } else { */ 121 | /* wallpaper.state = "off" */ 122 | /* } */ 123 | /* } */ 124 | 125 | BusyIndicator { 126 | running: wallpaper.state == "busy" 127 | /* running: false */ 128 | anchors.centerIn: parent 129 | } 130 | 131 | Row { 132 | opacity: wallpaper.state == "on" ? 1 : 0 133 | visible: opacity == 0 ? false : true 134 | spacing: units.smallSpacing 135 | 136 | Behavior on opacity { 137 | OpacityAnimator { 138 | duration: units.longDuration 139 | easing.type: Easing.InOutQuad 140 | } 141 | } 142 | 143 | anchors { 144 | /* horizontalCenter: wallpaper.horizontalCenter */ 145 | centerIn: parent 146 | } 147 | WButton { 148 | id: wb_refresh 149 | objectName: "wb_refresh" 150 | text: i18n("Refresh wallpaper") 151 | anchors { 152 | /* horizontalCenter: wallpaper.horizontalCenter */ 153 | /* centerIn: wallpaper */ 154 | } 155 | iconSource: ':/artworks/refresh.svg' 156 | /* opacity: wallpaper.state == "on" ? 1 : 0 */ 157 | onClicked: { 158 | /* wallpaper.state = "busy" */ 159 | } 160 | } 161 | WButton { 162 | id: wb_generate 163 | objectName: "wb_generate" 164 | text: i18n("Generate colors based on wallpaper") 165 | iconSource: ':/artworks/gen-colors.svg' 166 | onClicked: { 167 | wallpaper.state = "generated" 168 | } 169 | } 170 | } 171 | 172 | Row { 173 | id: cuw_row 174 | objectName: "cuw_row" 175 | opacity: wallpaper.state == "generated" ? 1 : 0 176 | visible: opacity == 0 ? false : true 177 | spacing: units.smallSpacing 178 | 179 | signal cuw_clicked(string color) 180 | 181 | Behavior on opacity { 182 | OpacityAnimator { 183 | duration: units.longDuration 184 | /* easing.type: Easing.InOutQuad */ 185 | } 186 | } 187 | anchors { 188 | centerIn: parent 189 | } 190 | 191 | ColorUnitW { 192 | objectName: "cuw" 193 | inner_color: "white" 194 | } 195 | ColorUnitW { 196 | objectName: "cuw" 197 | inner_color: "white" 198 | } 199 | ColorUnitW { 200 | objectName: "cuw" 201 | inner_color: "white" 202 | } 203 | ColorUnitW { 204 | objectName: "cuw" 205 | inner_color: "white" 206 | } 207 | 208 | } 209 | } 210 | 211 | 212 | PlasmaExtras.DescriptiveLabel { 213 | id: label 214 | /* text: 'testttttt' */ 215 | anchors { 216 | top: wallpaper.bottom 217 | topMargin: units.smallSpacing 218 | left: parent.left 219 | right: parent.right 220 | } 221 | horizontalAlignment: Text.AlignHCenter 222 | verticalAlignment: Text.AlignTop 223 | /* wrapMode: Text.WordWrap */ 224 | /* font.underline: root.activeFocus */ 225 | } 226 | 227 | } 228 | -------------------------------------------------------------------------------- /src/kcm_colorful.cpp: -------------------------------------------------------------------------------- 1 | #include "kcm_colorful.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | 22 | 23 | K_PLUGIN_FACTORY(KCMColorfulFactory, registerPlugin();) 24 | //K_EXPORT_PLUGIN(KCMColorfulFactory("kcm_colorful")) 25 | 26 | 27 | 28 | KCMColorful::KCMColorful(QWidget *parent, const QVariantList &args) 29 | : KCModule(parent) 30 | { 31 | KAboutData* aboutData = new KAboutData(QStringLiteral("kcm-colorful"), i18n("Colorful"), QLatin1String(PROJECT_VERSION)); 32 | aboutData->setShortDescription(i18n("Make your KDE Plasma colorful")); 33 | aboutData->setLicense(KAboutLicense::GPL_V2); 34 | aboutData->setHomepage(QStringLiteral("https://github.com/IsoaSFlus/kcm-colorful")); 35 | aboutData->addAuthor(QStringLiteral("IsoaSFlus"), i18n("Author"), QStringLiteral("me@isoasflus.com")); 36 | setAboutData(aboutData); 37 | QVBoxLayout *vb; 38 | vb = new QVBoxLayout(this); 39 | 40 | root_qml = new QQuickWidget; 41 | kdeclarative = new KDeclarative::KDeclarative(); 42 | kdeclarative->setTranslationDomain(QStringLiteral("kcm_colorful")); 43 | kdeclarative->setDeclarativeEngine(root_qml->engine()); 44 | kdeclarative->setupContext(); 45 | root_qml->setSource(QUrl(QStringLiteral("qrc:/qml/main.qml"))); 46 | root_qml->setResizeMode(QQuickWidget::SizeRootObjectToView); 47 | 48 | vb->addWidget(root_qml); 49 | setLayout(vb); 50 | 51 | set_wp_view(); 52 | 53 | helper = new QProcess(this); 54 | QObject::connect(helper, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(loadExtractedColors())); 55 | 56 | QQuickItem *object = root_qml->rootObject(); 57 | QQuickItem *wb_generate = object->findChild(QStringLiteral("wb_generate")); 58 | QQuickItem *wb_refresh = object->findChild(QStringLiteral("wb_refresh")); 59 | QQuickItem *cuw_row = object->findChild(QStringLiteral("cuw_row")); 60 | QList gv = object->findChildren(QStringLiteral("grid_view")); 61 | QObject::connect(wb_generate, SIGNAL(clicked()), this, SLOT(runHelper())); 62 | QObject::connect(wb_refresh, SIGNAL(clicked()), this, SLOT(set_wp_view())); 63 | QObject::connect(cuw_row, SIGNAL(cuw_clicked(QString)), this, SLOT(apply_color(QString))); 64 | QObject::connect(gv[0], SIGNAL(cu_clicked(QString)), this, SLOT(apply_color(QString))); 65 | QObject::connect(gv[1], SIGNAL(cu_clicked(QString)), this, SLOT(apply_color(QString))); 66 | 67 | readConfig(); 68 | } 69 | 70 | KCMColorful::~KCMColorful() 71 | { 72 | saveConfig(); 73 | delete root_qml; 74 | delete kdeclarative; 75 | } 76 | 77 | void KCMColorful::readConfig() 78 | { 79 | KSharedConfigPtr cfg; 80 | cfg = KSharedConfig::openConfig(); 81 | KConfigGroup kcg(cfg, "KCMColorful"); 82 | // kcg.writeEntry(QStringLiteral("test"), QStringLiteral("test")); 83 | auto out = kcg.readEntry(QStringLiteral("RecentColors"), QStringLiteral("")); 84 | recent_colors = out.split(QStringLiteral(","), QString::SkipEmptyParts); 85 | out = kcg.readEntry(QStringLiteral("UserColors"), QStringLiteral("")); 86 | user_colors = out.split(QStringLiteral(","), QString::SkipEmptyParts); 87 | cfg->sync(); 88 | cfg->markAsClean(); 89 | 90 | for (auto c = recent_colors.rbegin(); c != recent_colors.rend(); ++c) { 91 | addColorGV1(*c); 92 | } 93 | QList gv = root_qml->rootObject()->findChildren(QStringLiteral("grid_view")); 94 | QVariant color_code; 95 | for (auto c : user_colors) { 96 | color_code = c; 97 | QMetaObject::invokeMethod(gv[1], "add_color", 98 | Q_ARG(QVariant, color_code)); 99 | } 100 | } 101 | 102 | void KCMColorful::saveConfig() 103 | { 104 | QList gv = root_qml->rootObject()->findChildren(QStringLiteral("grid_view")); 105 | QVariant returnedValue1; 106 | QVariant returnedValue2; 107 | QMetaObject::invokeMethod(gv[0], "get_colors", 108 | Q_RETURN_ARG(QVariant, returnedValue1)); 109 | QMetaObject::invokeMethod(gv[1], "get_colors", 110 | Q_RETURN_ARG(QVariant, returnedValue2)); 111 | 112 | KSharedConfigPtr cfg; 113 | cfg = KSharedConfig::openConfig(); 114 | // qDebug() << cfg->groupList(); 115 | KConfigGroup kcg(cfg, "KCMColorful"); 116 | kcg.writeEntry(QStringLiteral("RecentColors"), returnedValue1); 117 | kcg.writeEntry(QStringLiteral("UserColors"), returnedValue2); 118 | cfg->sync(); 119 | cfg->markAsClean(); 120 | } 121 | 122 | void KCMColorful::addColorGV1(QString color) 123 | { 124 | // QList gv_model = root_qml->rootObject()->findChildren(QStringLiteral("gv_model")); 125 | QList gv = root_qml->rootObject()->findChildren(QStringLiteral("grid_view")); 126 | QVariant color_code(color); 127 | QVariant returnedValue; 128 | QMetaObject::invokeMethod(gv[0], "prepend_color", 129 | Q_RETURN_ARG(QVariant, returnedValue), 130 | Q_ARG(QVariant, color_code)); 131 | } 132 | 133 | void KCMColorful::set_wp_view() 134 | { 135 | QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.plasmashell"), 136 | QStringLiteral("/PlasmaShell"), 137 | QStringLiteral("org.kde.PlasmaShell"), 138 | QStringLiteral("evaluateScript")); 139 | message.setArguments({ 140 | QStringLiteral("var d = desktops();\ 141 | d[0].currentConfigGroup = Array(\"Wallpaper\", \"org.kde.image\", \"General\");\ 142 | a = d[0].readConfig(\"Image\");a.a()") 143 | }); 144 | 145 | auto rep = QDBusConnection::sessionBus().call(message); 146 | QRegularExpression re(QStringLiteral(".*(file://.+) is not a function.*")); 147 | auto match = re.match(rep.arguments()[0].toString()); 148 | if (match.hasMatch()) { 149 | current_wallpaper = match.captured(1); 150 | qDebug() << current_wallpaper; 151 | extracted_flag = false; 152 | QQuickItem *wp = root_qml->rootObject()->findChild(QStringLiteral("wp_view")); 153 | wp->setProperty("source", current_wallpaper); 154 | } 155 | 156 | // QProcess p; 157 | // p.start(QStringLiteral("bash"), QStringList() << QStringLiteral("-c") << 158 | // QStringLiteral("qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript \"var d = desktops();\ 159 | // d[0].currentConfigGroup = Array(\\\"Wallpaper\\\", \\\"org.kde.image\\\", \\\"General\\\");\ 160 | // a = d[0].readConfig(\\\"Image\\\");a.a()\" | sed -n 's/.*\\(file:\\/\\/.*\\) is not a function.*/\\1/p'")); 161 | // p.waitForFinished(); 162 | // QByteArray stdout = p.readAll(); 163 | // stdout.chop(1); 164 | 165 | } 166 | 167 | void KCMColorful::runHelper() 168 | { 169 | if (!extracted_flag) { 170 | helper->start(QStringLiteral("kcmcolorfulhelper"), QStringList() << QStringLiteral("--kcm") << QStringLiteral("-p") << current_wallpaper.mid(7)); 171 | // QQuickItem *object = root_qml->rootObject(); 172 | QQuickItem *wp = root_qml->rootObject()->findChild(QStringLiteral("wp_view")); 173 | wp->setProperty("state", QStringLiteral("busy")); 174 | } else { 175 | loadExtractedColors(); 176 | } 177 | } 178 | 179 | void KCMColorful::loadExtractedColors() 180 | { 181 | if (!extracted_flag) { 182 | int i = 0; 183 | QByteArray stdout(helper->readAll()); 184 | stdout.chop(1); 185 | colors = QString::fromUtf8(stdout).split(QStringLiteral(","), QString::SkipEmptyParts); 186 | QList cuw = root_qml->rootObject()->findChildren(QStringLiteral("cuw")); 187 | for (auto c : colors) { 188 | cuw[i++]->setProperty("inner_color", c); 189 | } 190 | extracted_flag = true; 191 | } 192 | QQuickItem *wp = root_qml->rootObject()->findChild(QStringLiteral("wp_view")); 193 | wp->setProperty("state", QStringLiteral("generated")); 194 | } 195 | 196 | void KCMColorful::apply_color(const QString &c) 197 | { 198 | qDebug() << c; 199 | QProcess::startDetached(QStringLiteral("kcmcolorfulhelper"), QStringList() << QStringLiteral("-c") << c); 200 | addColorGV1(c); 201 | } 202 | #include "kcm_colorful.moc" 203 | -------------------------------------------------------------------------------- /src/helper/mmcq.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "mmcq.h" 7 | 8 | 9 | MMCQ::MMCQ(QString file, bool debug_flag, bool kcm_flag) 10 | { 11 | 12 | QImage i(file); 13 | if (i.isNull()) { 14 | qDebug() << "ERROR: Invalid image file!"; //Invalid image file. 15 | exit(1); 16 | } 17 | img = new QImage(i.convertToFormat(QImage::Format_RGBA8888)); 18 | h = img->height(); 19 | w = img->width(); 20 | this->debug_flag = debug_flag; 21 | this->kcm_flag = kcm_flag; 22 | } 23 | 24 | MMCQ::~MMCQ() 25 | { 26 | delete img; 27 | } 28 | 29 | QList MMCQ::get_palette(int color_count, int quality) 30 | { 31 | pixels.clear(); 32 | histo.clear(); 33 | QList ret; 34 | for (int i = 0; i < w; i = i + quality) 35 | for (int j = 0; j < h; j++) { 36 | if (qAlpha(img->pixel(i, j)) >= 125) { 37 | if (qRed(img->pixel(i, j)) <= 250 && qGreen(img->pixel(i, j)) <= 250 && qBlue(img->pixel(i, j)) <= 250) { 38 | pixels.push_back(img->pixel(i, j)); 39 | } 40 | } 41 | } 42 | 43 | auto colors = quantize(color_count); 44 | for (const auto &c : colors) { 45 | ret.push_back(get_vbox_avg(c)); 46 | } 47 | return ret; 48 | } 49 | 50 | int MMCQ::get_color_index(int r, int g, int b) 51 | { 52 | return (r << (2 * sigbits)) + (g << sigbits) + b; 53 | } 54 | 55 | int MMCQ::get_vbox_color_sum(VBox v) 56 | { 57 | int npix = 0; 58 | int index = 0; 59 | for (int i = v.r1; i <= v.r2; i++) 60 | for (int j = v.g1; j <= v.g2; j++) 61 | for (int k = v.b1; k <= v.b2; k++) { 62 | index = get_color_index(i, j, k); 63 | npix += histo[index]; 64 | } 65 | return npix; 66 | } 67 | 68 | void MMCQ::calc_histo() 69 | { 70 | int index = 0; 71 | for (unsigned int i = 0; i < pixels.size(); i++) { 72 | index = get_color_index(qRed(pixels[i]) >> rshift, qGreen(pixels[i]) >> rshift, qBlue(pixels[i]) >> rshift); 73 | histo[index]++; 74 | } 75 | 76 | } 77 | 78 | VBox MMCQ::gen_vbox() 79 | { 80 | int rval, gval, bval; 81 | int rmin = 1000000; 82 | int rmax = 0; 83 | int gmin = 1000000; 84 | int gmax = 0; 85 | int bmin = 1000000; 86 | int bmax = 0; 87 | for (unsigned int i = 0; i < pixels.size(); i++) { 88 | rval = qRed(pixels[i]) >> rshift; 89 | gval = qGreen(pixels[i]) >> rshift; 90 | bval = qBlue(pixels[i]) >> rshift; 91 | 92 | rmin = std::min(rval, rmin); 93 | rmax = std::max(rval, rmax); 94 | gmin = std::min(gval, gmin); 95 | gmax = std::max(gval, gmax); 96 | bmin = std::min(bval, bmin); 97 | bmax = std::max(bval, bmax); 98 | } 99 | 100 | VBox vbox(rmin, rmax, gmin, gmax, bmin, bmax); 101 | return vbox; 102 | } 103 | 104 | std::vector MMCQ::do_median_cut(VBox v) 105 | { 106 | std::vector ret; 107 | 108 | if (get_vbox_color_sum(v) == 1) { 109 | ret.push_back(v); 110 | return ret; 111 | } 112 | 113 | std::vector side; 114 | side.push_back(v.r2 - v.r1); 115 | side.push_back(v.g2 - v.g1); 116 | side.push_back(v.b2 - v.b1); 117 | 118 | auto max_side = std::max_element(side.begin(), side.end()); 119 | 120 | int sub_sum = 0; 121 | int total = 0; 122 | std::unordered_map partial_sum; 123 | int index = 0; 124 | int dim1 = 0; 125 | int dim2 = 0; 126 | 127 | if (*max_side == side[0]) { 128 | dim1 = v.r1; 129 | dim2 = v.r2; 130 | for (int i = v.r1; i <= v.r2; i++) { 131 | for (int j = v.g1; j <= v.g2; j++) 132 | for (int k = v.b1; k <= v.b2; k++) { 133 | index = get_color_index(i, j, k); 134 | sub_sum += histo[index]; 135 | } 136 | total += sub_sum; 137 | partial_sum[i] = total; 138 | } 139 | } else if (*max_side == side[1]) { 140 | dim1 = v.g1; 141 | dim2 = v.g2; 142 | for (int i = v.g1; i <= v.g2; i++) { 143 | for (int j = v.r1; j <= v.r2; j++) 144 | for (int k = v.b1; k <= v.b2; k++) { 145 | index = get_color_index(i, j, k); 146 | sub_sum += histo[index]; 147 | } 148 | total += sub_sum; 149 | partial_sum[i] = total; 150 | } 151 | } else { 152 | dim1 = v.b1; 153 | dim2 = v.b2; 154 | for (int i = v.b1; i <= v.b2; i++) { 155 | for (int j = v.r1; j <= v.r2; j++) 156 | for (int k = v.g1; k <= v.g2; k++) { 157 | index = get_color_index(i, j, k); 158 | sub_sum += histo[index]; 159 | } 160 | total += sub_sum; 161 | partial_sum[i] = total; 162 | } 163 | } 164 | 165 | 166 | for (int i = dim1; i <= dim2; i++) { 167 | if (partial_sum[i] > (total / 2)) { 168 | int left = i - dim1; 169 | int right = dim2 - i; 170 | int d2 = dim1; 171 | if (left <= right) { 172 | if ((dim2 - 1) > (i + (right / 2))) { 173 | d2 = i + (right / 2); 174 | } else { 175 | d2 = dim2 -1; 176 | } 177 | } else { 178 | if ((dim1) < (i - 1 - (left / 2))) { 179 | d2 = i - 1 - (left / 2); 180 | } else { 181 | d2 = dim1; 182 | } 183 | } 184 | 185 | int count2 = 0; 186 | while (!partial_sum[d2]) { 187 | d2++; 188 | count2 = total - partial_sum[d2]; 189 | } 190 | while ((count2 == 0) && partial_sum[d2]) { 191 | d2--; 192 | count2 = total - partial_sum[d2]; 193 | } 194 | 195 | VBox v1 = v; 196 | VBox v2 = v; 197 | if (*max_side == side[0]) { 198 | v1.r2 = d2; 199 | v2.r1 = d2 + 1; 200 | } else if (*max_side == side[1]) { 201 | v1.g2 = d2; 202 | v2.g1 = d2 + 1; 203 | } else { 204 | v1.b2 = d2; 205 | v2.b1 = d2 + 1; 206 | } 207 | ret.push_back(v1); 208 | ret.push_back(v2); 209 | return ret; 210 | } 211 | } 212 | return ret; 213 | } 214 | 215 | QColor MMCQ::get_vbox_avg(VBox v) 216 | { 217 | int ntot = 0; 218 | int mult = 1 << (8 - sigbits); 219 | int r_sum = 0; 220 | int g_sum = 0; 221 | int b_sum = 0; 222 | int r_avg = 0; 223 | int g_avg = 0; 224 | int b_avg = 0; 225 | 226 | int index = 0; 227 | int hval = 0; 228 | for (int i = v.r1; i <= v.r2; i++) 229 | for (int j = v.g1; j <= v.g2; j++) 230 | for (int k = v.b1; k <= v.b2; k++) { 231 | index = get_color_index(i, j, k); 232 | hval = histo[index]; 233 | ntot += hval; 234 | r_sum += hval * (i + 0.5) * mult; 235 | g_sum += hval * (j + 0.5) * mult; 236 | b_sum += hval * (k + 0.5) * mult; 237 | } 238 | if (ntot) { 239 | r_avg = int(r_sum / ntot); 240 | g_avg = int(g_sum / ntot); 241 | b_avg = int(b_sum / ntot); 242 | } else { 243 | r_avg = int(mult * (v.r1 + v.r2 + 1) / 2); 244 | g_avg = int(mult * (v.g1 + v.g2 + 1) / 2); 245 | b_avg = int(mult * (v.b1 + v.b2 + 1) / 2); 246 | } 247 | 248 | QColor c(r_avg, g_avg, b_avg); 249 | return c; 250 | } 251 | 252 | std::vector MMCQ::quantize(int max_color) 253 | { 254 | std::vector ret; 255 | calc_histo(); 256 | 257 | auto vbox = gen_vbox(); 258 | 259 | auto cmp1 = [&](VBox left, VBox right) { 260 | auto left_val = get_vbox_color_sum(left); 261 | auto right_val = get_vbox_color_sum(right); 262 | return left_val < right_val; 263 | }; 264 | std::priority_queue, decltype(cmp1)> pq1(cmp1); 265 | pq1.push(vbox); 266 | 267 | quantize_iter(pq1, max_color * fract_by_populations); 268 | 269 | auto cmp2 = [&](VBox left, VBox right) { 270 | auto left_val = get_vbox_color_sum(left); 271 | auto right_val = get_vbox_color_sum(right); 272 | left_val = left_val * (left.r2 - left.r1) * (left.g2 - left.g1) * (left.b2 - left.b1); 273 | right_val = right_val * (right.r2 - right.r1) * (right.g2 - right.g1) * (right.b2 - right.b1); 274 | return left_val < right_val; 275 | }; 276 | std::priority_queue, decltype(cmp2)> pq2(cmp2); 277 | while (!pq1.empty()) { 278 | pq2.push(pq1.top()); 279 | pq1.pop(); 280 | } 281 | quantize_iter(pq2, max_color - pq2.size() + 1); 282 | 283 | while (!pq2.empty()) { 284 | ret.push_back(pq2.top()); 285 | pq2.pop(); 286 | } 287 | return ret; 288 | } 289 | 290 | template 291 | void MMCQ::quantize_iter(T &t, int target) 292 | { 293 | int n_color = 1; 294 | int i = 0; 295 | while (i < max_iter) { 296 | 297 | auto v = t.top(); 298 | t.pop(); 299 | if (!get_vbox_color_sum(v)) { 300 | t.push(v); 301 | i++; 302 | continue; 303 | } 304 | auto vboxes = do_median_cut(v); 305 | if (vboxes.empty()) { 306 | return; 307 | } 308 | t.push(vboxes[0]); 309 | if (vboxes.size() > 1) { 310 | t.push(vboxes[1]); 311 | n_color++; 312 | } 313 | 314 | if (n_color >= target) { 315 | return; 316 | } 317 | 318 | if (i > max_iter) { 319 | qDebug() << "meet max"; 320 | return; 321 | } 322 | i++; 323 | } 324 | } 325 | 326 | 327 | VBox::VBox() 328 | { 329 | r1 = 0; 330 | g1 = 0; 331 | b1 = 0; 332 | r2 = 0; 333 | g2 = 0; 334 | b2 = 0; 335 | } 336 | 337 | VBox::VBox(int r1, int r2, int g1, int g2, int b1, int b2) 338 | { 339 | this->r1 = r1; 340 | this->g1 = g1; 341 | this->b1 = b1; 342 | this->r2 = r2; 343 | this->g2 = g2; 344 | this->b2 = b2; 345 | } 346 | 347 | VBox::~VBox() 348 | { 349 | 350 | } 351 | 352 | 353 | -------------------------------------------------------------------------------- /src/helper/colordata.h: -------------------------------------------------------------------------------- 1 | #ifndef _COLORDATA 2 | #define _COLORDATA 3 | 4 | const int colordata[256][3] = {{247, 172, 188}, 5 | {222, 171, 138}, 6 | {129, 121, 54}, 7 | {68, 70, 147}, 8 | {239, 91, 156}, 9 | {254, 220, 189}, 10 | {127, 117, 34}, 11 | {43, 68, 144}, 12 | {254, 238, 237}, 13 | {244, 121, 32}, 14 | {128, 117, 44}, 15 | {42, 92, 170}, 16 | {240, 91, 114}, 17 | {144, 90, 61}, 18 | {135, 132, 59}, 19 | {34, 75, 143}, 20 | {241, 91, 108}, 21 | {143, 75, 46}, 22 | {114, 105, 48}, 23 | {0, 58, 108}, 24 | {248, 171, 166}, 25 | {135, 72, 31}, 26 | {69, 73, 38}, 27 | {16, 43, 106}, 28 | {246, 156, 159}, 29 | {95, 60, 35}, 30 | {46, 58, 31}, 31 | {66, 106, 179}, 32 | {245, 143, 152}, 33 | {107, 71, 60}, 34 | {77, 79, 54}, 35 | {70, 72, 95}, 36 | {202, 134, 135}, 37 | {250, 167, 85}, 38 | {183, 186, 107}, 39 | {78, 114, 184}, 40 | {243, 145, 169}, 41 | {250, 178, 123}, 42 | {178, 210, 53}, 43 | {24, 29, 75}, 44 | {189, 103, 88}, 45 | {245, 130, 32}, 46 | {92, 122, 41}, 47 | {26, 41, 51}, 48 | {215, 19, 69}, 49 | {132, 57, 0}, 50 | {190, 215, 66}, 51 | {18, 26, 42}, 52 | {214, 79, 68}, 53 | {144, 93, 29}, 54 | {127, 184, 14}, 55 | {12, 33, 43}, 56 | {217, 58, 73}, 57 | {138, 93, 25}, 58 | {163, 207, 98}, 59 | {106, 109, 169}, 60 | {179, 66, 74}, 61 | {140, 83, 27}, 62 | {118, 145, 73}, 63 | {88, 94, 170}, 64 | {199, 105, 104}, 65 | {130, 104, 88}, 66 | {109, 131, 70}, 67 | {73, 78, 143}, 68 | {187, 80, 93}, 69 | {100, 73, 43}, 70 | {120, 163, 85}, 71 | {175, 180, 219}, 72 | {152, 113, 101}, 73 | {174, 102, 66}, 74 | {171, 200, 139}, 75 | {155, 149, 201}, 76 | {172, 103, 103}, 77 | {86, 69, 45}, 78 | {116, 144, 93}, 79 | {105, 80, 161}, 80 | {151, 60, 63}, 81 | {150, 88, 42}, 82 | {205, 230, 199}, 83 | {111, 96, 170}, 84 | {178, 44, 70}, 85 | {112, 86, 40}, 86 | {29, 149, 63}, 87 | {134, 120, 146}, 88 | {167, 50, 74}, 89 | {74, 49, 19}, 90 | {119, 172, 152}, 91 | {145, 133, 151}, 92 | {170, 54, 61}, 93 | {65, 47, 31}, 94 | {0, 125, 101}, 95 | {111, 109, 133}, 96 | {237, 25, 65}, 97 | {132, 85, 56}, 98 | {132, 191, 150}, 99 | {89, 76, 109}, 100 | {242, 101, 34}, 101 | {142, 116, 55}, 102 | {69, 185, 124}, 103 | {105, 77, 159}, 104 | {210, 85, 61}, 105 | {105, 84, 27}, 106 | {34, 90, 31}, 107 | {111, 89, 156}, 108 | {180, 83, 75}, 109 | {213, 197, 159}, 110 | {54, 116, 89}, 111 | {133, 82, 161}, 112 | {239, 65, 54}, 113 | {205, 154, 91}, 114 | {0, 121, 71}, 115 | {84, 48, 68}, 116 | {198, 60, 38}, 117 | {205, 154, 91}, 118 | {64, 131, 94}, 119 | {99, 67, 79}, 120 | {243, 113, 92}, 121 | {179, 109, 65}, 122 | {43, 100, 71}, 123 | {125, 88, 134}, 124 | {167, 87, 59}, 125 | {223, 148, 100}, 126 | {0, 88, 49}, 127 | {64, 28, 68}, 128 | {170, 33, 22}, 129 | {183, 111, 64}, 130 | {0, 108, 84}, 131 | {71, 45, 86}, 132 | {182, 69, 51}, 133 | {173, 139, 61}, 134 | {55, 88, 48}, 135 | {69, 34, 74}, 136 | {181, 67, 52}, 137 | {222, 163, 44}, 138 | {39, 77, 61}, 139 | {65, 20, 69}, 140 | {133, 63, 4}, 141 | {209, 146, 63}, 142 | {55, 88, 48}, 143 | {75, 47, 61}, 144 | {132, 2, 40}, 145 | {200, 132, 0}, 146 | {39, 52, 43}, 147 | {64, 46, 76}, 148 | {122, 23, 35}, 149 | {195, 126, 0}, 150 | {101, 194, 148}, 151 | {199, 126, 181}, 152 | {160, 57, 57}, 153 | {195, 126, 0}, 154 | {115, 185, 162}, 155 | {234, 102, 166}, 156 | {138, 46, 59}, 157 | {224, 134, 26}, 158 | {114, 186, 167}, 159 | {241, 115, 172}, 160 | {142, 69, 63}, 161 | {255, 206, 123}, 162 | {0, 83, 68}, 163 | {255, 255, 251}, 164 | {143, 75, 74}, 165 | {252, 175, 23}, 166 | {18, 46, 41}, 167 | {255, 254, 249}, 168 | {137, 47, 27}, 169 | {186, 132, 72}, 170 | {41, 48, 71}, 171 | {246, 245, 236}, 172 | {107, 44, 37}, 173 | {137, 106, 69}, 174 | {0, 174, 157}, 175 | {217, 214, 195}, 176 | {115, 58, 49}, 177 | {118, 98, 76}, 178 | {80, 138, 136}, 179 | {209, 199, 183}, 180 | {84, 33, 29}, 181 | {109, 88, 38}, 182 | {112, 161, 159}, 183 | {242, 234, 218}, 184 | {120, 51, 30}, 185 | {255, 194, 14}, 186 | {80, 183, 193}, 187 | {211, 215, 212}, 188 | {83, 38, 31}, 189 | {253, 185, 51}, 190 | {0, 166, 172}, 191 | {153, 157, 156}, 192 | {241, 90, 34}, 193 | {211, 198, 166}, 194 | {120, 205, 209}, 195 | {161, 163, 166}, 196 | {180, 83, 60}, 197 | {199, 162, 82}, 198 | {0, 135, 146}, 199 | {157, 144, 135}, 200 | {132, 51, 31}, 201 | {222, 198, 116}, 202 | {148, 214, 218}, 203 | {138, 140, 142}, 204 | {244, 122, 85}, 205 | {182, 153, 104}, 206 | {175, 223, 228}, 207 | {116, 120, 124}, 208 | {241, 90, 34}, 209 | {193, 161, 115}, 210 | {94, 124, 133}, 211 | {124, 133, 119}, 212 | {243, 112, 75}, 213 | {219, 206, 143}, 214 | {118, 190, 204}, 215 | {114, 119, 123}, 216 | {218, 118, 91}, 217 | {255, 212, 0}, 218 | {144, 215, 236}, 219 | {119, 120, 123}, 220 | {200, 93, 68}, 221 | {255, 212, 0}, 222 | {0, 154, 214}, 223 | {79, 85, 85}, 224 | {174, 80, 57}, 225 | {255, 230, 0}, 226 | {20, 91, 125}, 227 | {108, 76, 73}, 228 | {106, 52, 39}, 229 | {240, 220, 112}, 230 | {17, 38, 79}, 231 | {86, 54, 36}, 232 | {143, 75, 56}, 233 | {252, 241, 110}, 234 | {123, 191, 234}, 235 | {62, 65, 69}, 236 | {142, 62, 31}, 237 | {222, 203, 0}, 238 | {51, 163, 220}, 239 | {60, 54, 69}, 240 | {243, 108, 33}, 241 | {203, 197, 71}, 242 | {34, 143, 189}, 243 | {70, 69, 71}, 244 | {180, 83, 42}, 245 | {110, 107, 65}, 246 | {36, 104, 162}, 247 | {19, 12, 14}, 248 | {183, 112, 79}, 249 | {89, 96, 50}, 250 | {37, 112, 161}, 251 | {40, 31, 29}, 252 | {222, 119, 63}, 253 | {82, 95, 66}, 254 | {37, 133, 166}, 255 | {47, 39, 29}, 256 | {201, 153, 121}, 257 | {95, 93, 70}, 258 | {27, 49, 94}, 259 | {29, 22, 38}}; 260 | #endif 261 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /src/helper/kcmcolorfulhelper.cpp: -------------------------------------------------------------------------------- 1 | #include "kcmcolorfulhelper.h" 2 | #include "colordata.h" 3 | #include "mmcq.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | KcmColorfulHelper::KcmColorfulHelper(QStringList args, QObject *parent) : QObject(parent) 17 | { 18 | QTime time = QTime::currentTime(); 19 | qsrand(static_cast(time.msec())); 20 | mConfig = KSharedConfig::openConfig(QStringLiteral("kdeglobals")); 21 | 22 | if (args[4] == "true") { 23 | debug_flag = true; 24 | } 25 | if (args[5] == "true") { 26 | kcm_flag = true; 27 | } 28 | bool ok = false; 29 | paletteNum = args[2].toInt(&ok); 30 | if (ok == true) { 31 | if (paletteNum < 1 || paletteNum > 16) { 32 | paletteNum = 8; 33 | } 34 | } else { 35 | paletteNum = 8; 36 | } 37 | ok = false; 38 | selectNum = args[6].toInt(&ok); 39 | if (ok != true) { 40 | selectNum = 1; 41 | } 42 | if (args[0] == QString("kcmcolorful-NOPIC")) { 43 | if (args[1] != QString("kcmcolorful-NOCOLOR")) { 44 | c = new QColor(args[1]); 45 | run_type = run_type | 0x02u; 46 | } else { 47 | run_type = run_type & (~0x02u); 48 | } 49 | } else { 50 | wallpaperFilePath = args[0]; 51 | mmcq = new MMCQ(wallpaperFilePath, debug_flag, kcm_flag); 52 | if (args[3] == "true") { 53 | setWallpaper(args[0]); 54 | } 55 | run_type = run_type | 0x02u; 56 | } 57 | 58 | ok = false; 59 | theme_opacity = args[7].toDouble(&ok); 60 | run_type = run_type | 0x01u; 61 | if (ok != true) { 62 | theme_opacity = 0.6; 63 | run_type = run_type & (~0x01u); 64 | } 65 | 66 | // genCSName(); 67 | // getPrevCSName(); 68 | // readDefaultCS(); 69 | } 70 | 71 | KcmColorfulHelper::~KcmColorfulHelper() 72 | { 73 | delete c; 74 | delete mmcq; 75 | } 76 | 77 | void KcmColorfulHelper::run() 78 | { 79 | // for theme color 80 | if ((run_type & 0x02u) != 0) { 81 | if (mmcq != nullptr) { 82 | palette = mmcq->get_palette(paletteNum); 83 | palette_16 = mmcq->get_palette(16); 84 | calcColor(); 85 | } 86 | int i = 1; 87 | if (kcm_flag == true) { 88 | QStringList colors; 89 | while (i <= 4) { 90 | colors << color_refine((pt_and_color.cend() - i).value()).name(); 91 | if (pt_and_color.cend() - i == pt_and_color.cbegin()) { 92 | break; 93 | } 94 | i++; 95 | } 96 | for (auto color : colors) { 97 | std::cout << color.toStdString() << ","; 98 | } 99 | std::cout << std::endl; 100 | } else { 101 | if (!c) { 102 | while (i <= 4) { 103 | auto it = pt_and_color.cend() - i; 104 | QColor color = it.value(); 105 | color = color_refine(color); 106 | if (selectNum == i) { 107 | c = new QColor(color); 108 | } 109 | qDebug().noquote() << QString("Candidate: %4, %1, %2, %3 \033[48;2;%1;%2;%3m \033[0m").arg(QString::number(color.red()), QString::number(color.green()), QString::number(color.blue()), QString::number(it.key())); 110 | if (it == pt_and_color.cbegin()) { 111 | c = new QColor(color); 112 | break; 113 | } 114 | i++; 115 | } 116 | qDebug().noquote() << QString("Choose: %1, %2, %3 \033[48;2;%1;%2;%3m \033[0m").arg(QString::number(c->red()), QString::number(c->green()), QString::number(c->blue())); 117 | } 118 | readTemplateCS(); 119 | // changeColorScheme(tConfig); 120 | changeColorSchemeB(); 121 | save(); 122 | mConfig->markAsClean(); 123 | tConfig->markAsClean(); 124 | } 125 | } 126 | // for theme opacity 127 | if ((run_type & 0x01u) != 0) { 128 | changeThemeOpacity(); 129 | } 130 | } 131 | 132 | void KcmColorfulHelper::getPrevCSName() 133 | { 134 | KSharedConfigPtr cfg = KSharedConfig::openConfig(QStringLiteral("kdeglobals")); 135 | KConfigGroup groupOut(cfg, "General"); 136 | prevColorSchemeName = groupOut.readEntry("ColorScheme"); 137 | } 138 | 139 | void KcmColorfulHelper::readTemplateCS() 140 | { 141 | QString tName; 142 | if (isDarkTheme()) { 143 | tName = "ColorfulDark"; 144 | } else { 145 | tName = "ColorfulLight"; 146 | } 147 | 148 | QString schemeFile; 149 | 150 | schemeFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "color-schemes/" + tName + ".colors"); 151 | QFile file(schemeFile); 152 | 153 | if (!file.exists()) { 154 | schemeFile = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) 155 | + "/color-schemes/" + "BreezeIso.colors"; 156 | } 157 | debug_flag ? qDebug().noquote() << schemeFile : qDebug(); 158 | tConfig = KSharedConfig::openConfig(schemeFile); 159 | } 160 | 161 | void KcmColorfulHelper::changeColorScheme() 162 | { 163 | KConfigGroup group(mConfig, "Colors:View"); 164 | // qDebug() << group.readEntry("ForegroundNormal"); 165 | 166 | group.writeEntry("ForegroundNormal", addJitter(group.readEntry("ForegroundNormal"))); 167 | group.writeEntry("DecorationHover", *c); 168 | 169 | 170 | // KConfigGroup groupWMTheme(config, "WM"); 171 | KConfigGroup groupWMOut(mConfig, "WM"); 172 | 173 | QStringList colorItemListWM; 174 | colorItemListWM << "activeBackground" 175 | << "activeForeground" 176 | << "inactiveBackground" 177 | << "inactiveForeground"; 178 | // << "activeBlend" 179 | // << "inactiveBlend"; 180 | 181 | QVector defaultWMColors; 182 | defaultWMColors << *c 183 | << QColor(239,240,241) 184 | << *c 185 | << QColor(189,195,199) 186 | /* << QColor(255,255,255) 187 | << QColor(75,71,67)*/; 188 | 189 | int i = 0; 190 | for (const QString &coloritem : colorItemListWM) 191 | { 192 | groupWMOut.writeEntry(coloritem, defaultWMColors.value(i)); 193 | ++i; 194 | } 195 | } 196 | 197 | void KcmColorfulHelper::changeColorSchemeB() 198 | { 199 | KConfigGroup group(mConfig, "Colors:View"); 200 | group.writeEntry("ForegroundLink", *c); 201 | group.writeEntry("DecorationHover", *c); 202 | KConfigGroup groupWM(mConfig, "WM"); 203 | groupWM.writeEntry("activeBackground", *c); 204 | groupWM.writeEntry("inactiveBackground", *c); 205 | } 206 | 207 | void KcmColorfulHelper::changeColorScheme(KSharedConfigPtr config) 208 | { 209 | // // store colorscheme name in global settings 210 | // mConfig = KSharedConfig::openConfig(QStringLiteral("kdeglobals")); 211 | // KConfigGroup groupOut(mConfig, "General"); 212 | // qDebug() << groupOut.readEntry("ColorScheme"); 213 | // groupOut.writeEntry("ColorScheme", colorSchemeName); 214 | 215 | QStringList colorItemList; 216 | colorItemList << "BackgroundNormal" 217 | << "BackgroundAlternate" 218 | << "ForegroundNormal" 219 | << "ForegroundInactive" 220 | << "ForegroundActive" 221 | << "ForegroundLink" 222 | << "ForegroundVisited" 223 | << "ForegroundNegative" 224 | << "ForegroundNeutral" 225 | << "ForegroundPositive" 226 | << "DecorationFocus" 227 | << "DecorationHover"; 228 | 229 | QStringList colorSetGroupList; 230 | colorSetGroupList << "Colors:View" 231 | << "Colors:Window" 232 | << "Colors:Button" 233 | << "Colors:Selection" 234 | << "Colors:Tooltip" 235 | << "Colors:Complementary"; 236 | 237 | QList colorSchemes; 238 | 239 | colorSchemes.append(KColorScheme(QPalette::Active, KColorScheme::View, config)); 240 | colorSchemes.append(KColorScheme(QPalette::Active, KColorScheme::Window, config)); 241 | colorSchemes.append(KColorScheme(QPalette::Active, KColorScheme::Button, config)); 242 | colorSchemes.append(KColorScheme(QPalette::Active, KColorScheme::Selection, config)); 243 | colorSchemes.append(KColorScheme(QPalette::Active, KColorScheme::Tooltip, config)); 244 | colorSchemes.append(KColorScheme(QPalette::Active, KColorScheme::Complementary, config)); 245 | 246 | for (int i = 0; i < colorSchemes.length(); ++i) 247 | { 248 | KConfigGroup group(mConfig, colorSetGroupList.value(i)); 249 | group.writeEntry("BackgroundNormal", addJitter(colorSchemes[i].background(KColorScheme::NormalBackground).color())); 250 | group.writeEntry("BackgroundAlternate", colorSchemes[i].background(KColorScheme::AlternateBackground).color()); 251 | group.writeEntry("ForegroundNormal", addJitter(colorSchemes[i].foreground(KColorScheme::NormalText).color())); 252 | group.writeEntry("ForegroundInactive", colorSchemes[i].foreground(KColorScheme::InactiveText).color()); 253 | group.writeEntry("ForegroundActive", colorSchemes[i].foreground(KColorScheme::ActiveText).color()); 254 | group.writeEntry("ForegroundLink", colorSchemes[i].foreground(KColorScheme::LinkText).color()); 255 | group.writeEntry("ForegroundVisited", colorSchemes[i].foreground(KColorScheme::VisitedText).color()); 256 | group.writeEntry("ForegroundNegative", colorSchemes[i].foreground(KColorScheme::NegativeText).color()); 257 | group.writeEntry("ForegroundNeutral", colorSchemes[i].foreground(KColorScheme::NeutralText).color()); 258 | group.writeEntry("ForegroundPositive", colorSchemes[i].foreground(KColorScheme::PositiveText).color()); 259 | group.writeEntry("DecorationFocus", colorSchemes[i].decoration(KColorScheme::FocusColor).color()); 260 | if (i == 0) { 261 | group.writeEntry("DecorationHover", *c); 262 | } else { 263 | group.writeEntry("DecorationHover", colorSchemes[i].decoration(KColorScheme::HoverColor).color()); 264 | } 265 | } 266 | 267 | KConfigGroup groupWMTheme(config, "WM"); 268 | KConfigGroup groupWMOut(mConfig, "WM"); 269 | 270 | QStringList colorItemListWM; 271 | colorItemListWM << "activeBackground" 272 | << "activeForeground" 273 | << "inactiveBackground" 274 | << "inactiveForeground" 275 | << "activeBlend" 276 | << "inactiveBlend"; 277 | 278 | QVector defaultWMColors; 279 | defaultWMColors << *c 280 | << colorSchemes[1].foreground(KColorScheme::NormalText).color() 281 | << *c 282 | << colorSchemes[1].foreground(KColorScheme::NormalText).color() 283 | << QColor(255,255,255) 284 | << QColor(75,71,67); 285 | 286 | int i = 0; 287 | for (const QString &coloritem : colorItemListWM) 288 | { 289 | groupWMOut.writeEntry(coloritem, defaultWMColors.value(i)); 290 | ++i; 291 | } 292 | 293 | QStringList groupNameList; 294 | groupNameList << "ColorEffects:Inactive" << "ColorEffects:Disabled"; 295 | 296 | QStringList effectList; 297 | effectList << "Enable" 298 | << "ChangeSelectionColor" 299 | << "IntensityEffect" 300 | << "IntensityAmount" 301 | << "ColorEffect" 302 | << "ColorAmount" 303 | << "Color" 304 | << "ContrastEffect" 305 | << "ContrastAmount"; 306 | 307 | for (const QString &groupName : groupNameList) 308 | { 309 | 310 | KConfigGroup groupEffectOut(mConfig, groupName); 311 | KConfigGroup groupEffectTheme(config, groupName); 312 | 313 | for (const QString &effect : effectList) { 314 | groupEffectOut.writeEntry(effect, groupEffectTheme.readEntry(effect)); 315 | } 316 | } 317 | } 318 | 319 | void KcmColorfulHelper::save() 320 | { 321 | mConfig->sync(); 322 | 323 | // KConfig cfg(QStringLiteral("kcmdisplayrc"), KConfig::NoGlobals); 324 | // KConfigGroup displayGroup(&cfg, "X11"); 325 | 326 | // displayGroup.writeEntry("exportKDEColors", true); 327 | 328 | // cfg.sync(); 329 | 330 | // QSettings* settings = new QSettings(QLatin1String("Trolltech")); 331 | // KSharedConfigPtr kglobalcfg = KSharedConfig::openConfig( "kdeglobals" ); 332 | // KConfigGroup kglobals(kglobalcfg, "KDE"); 333 | // QPalette newPal = KColorScheme::createApplicationPalette(kglobalcfg); 334 | // applyQtColors(kglobalcfg, *settings, newPal); 335 | // delete settings; 336 | // runRdb(KRdbExportQtColors | KRdbExportGtkTheme | KRdbExportColors); 337 | 338 | 339 | QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KGlobalSettings"), 340 | QStringLiteral("org.kde.KGlobalSettings"), 341 | QStringLiteral("notifyChange")); 342 | message.setArguments({ 343 | 0, //previous KGlobalSettings::PaletteChanged. This is now private API in khintsettings 344 | 0 //unused in palette changed but needed for the DBus signature 345 | }); 346 | QDBusConnection::sessionBus().send(message); 347 | 348 | // QDBusMessage message_2 = QDBusMessage::createSignal(QStringLiteral("/KWin"), QStringLiteral("org.kde.KWin"), QStringLiteral("reloadConfig")); 349 | // QDBusConnection::sessionBus().send(message_2); 350 | 351 | // QThread::sleep(1); 352 | // QDBusConnection::sessionBus().send(message_2); 353 | } 354 | 355 | void KcmColorfulHelper::genCSName() 356 | { 357 | colorSchemeName = "" + QUuid::createUuid().toString(QUuid::WithoutBraces).mid(0, 6); 358 | } 359 | 360 | void KcmColorfulHelper::saveCSFile() 361 | { 362 | 363 | QString newpath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) 364 | + "/color-schemes/"; 365 | QProcess::execute(QString("bash -c \"rm '%1Colorful-*'\"").arg(newpath)); 366 | QDir dir; 367 | dir.mkpath(newpath); 368 | newpath += colorSchemeName + ".colors"; 369 | 370 | 371 | KConfig *config = mConfig->copyTo(newpath); 372 | // mConfig->markAsClean(); 373 | // m_config->reparseConfiguration(); 374 | KConfigGroup groupA(config, "General"); 375 | groupA.writeEntry("Name", colorSchemeName); 376 | 377 | KConfigGroup group(config, "Colors:View"); 378 | group.writeEntry("DecorationHover", *c); 379 | 380 | 381 | // KConfigGroup groupWMTheme(config, "WM"); 382 | KConfigGroup groupWMOut(config, "WM"); 383 | 384 | QStringList colorItemListWM; 385 | colorItemListWM << "activeBackground" 386 | << "activeForeground" 387 | << "inactiveBackground" 388 | << "inactiveForeground"; 389 | // << "activeBlend" 390 | // << "inactiveBlend"; 391 | 392 | QVector defaultWMColors; 393 | defaultWMColors << *c 394 | << QColor(239,240,241) 395 | << *c 396 | << QColor(189,195,199) 397 | /* << QColor(255,255,255) 398 | << QColor(75,71,67)*/; 399 | 400 | int i = 0; 401 | for (const QString &coloritem : colorItemListWM) 402 | { 403 | groupWMOut.writeEntry(coloritem, defaultWMColors.value(i)); 404 | ++i; 405 | } 406 | 407 | 408 | // sync it and delete pointer 409 | config->sync(); 410 | // changeColorScheme(config); 411 | delete config; 412 | KSharedConfigPtr rConfig = KSharedConfig::openConfig(newpath); 413 | changeColorScheme(rConfig); 414 | 415 | } 416 | 417 | QColor KcmColorfulHelper::addJitter(QColor color) 418 | { 419 | return QColor(color.red() + (qrand()%5 - 2), color.green() + (qrand()%5 - 2), color.blue() + (qrand()%5 - 2)); 420 | } 421 | 422 | bool KcmColorfulHelper::isDarkTheme() 423 | { 424 | if (c->red() < 66 && c->green() < 66 && c->blue() < 80) { 425 | return true; 426 | } else { 427 | return false; 428 | } 429 | } 430 | 431 | void KcmColorfulHelper::calcColor() 432 | { 433 | double pt = 0; 434 | double pt_val = 0; 435 | double pt_sat = 0; 436 | double pt_hue = 0; 437 | double hue = 0; 438 | double sat = 0; 439 | double val = 0; 440 | double A = 0; 441 | int i = 0; 442 | int j = 0; 443 | 444 | double weight_of_order[8] = {1, 1, 1, 0.95, 0.9, 0.8, 0.7, 0.6}; 445 | QList colors; 446 | 447 | // QList::iterator it; 448 | i = 0; 449 | for (auto it = palette.begin(); it != palette.end() && (it - palette.begin()) < 8; ++it) { 450 | colors << *it; 451 | i++; 452 | } 453 | for (auto it = palette_16.begin(); it != palette_16.end() && (it - palette_16.begin()) < 8; ++it) { 454 | colors << *it; 455 | } 456 | 457 | j = 0; 458 | for (auto color : colors) { 459 | pt = 0; 460 | pt_val = 0; 461 | pt_sat = 0; 462 | pt_hue = 0; 463 | val = color.value(); 464 | sat = color.saturation(); 465 | hue = color.hue(); 466 | 467 | A = 220.0 + (0.137 * (255.0 - sat)); 468 | if (val < A) { 469 | pt_val = 80.0 - ((A - val) / A * 80.0); 470 | } else { 471 | pt_val = 80.0 + ((val - A) / (255.0 - A) * 20.0); 472 | } 473 | 474 | if (sat < 70) { 475 | pt_sat = 100.0 - ((70.0 - sat) / 70.0 * 100.0); 476 | } else if (sat > 220) { 477 | pt_sat = 100.0 - ((sat - 220.0) / 35.0 * 100.0); 478 | } else { 479 | pt_sat = 100; 480 | } 481 | 482 | if (hue > 159 && hue < 196) { 483 | if (hue < 180) { 484 | pt_hue = 100.0 - (50.0 * (hue - 159.0) / 21.0); 485 | } else { 486 | pt_hue = 100.0 - (50.0 * (196.0 - hue) / 16.0); 487 | } 488 | } else { 489 | pt_hue = 100; 490 | } 491 | 492 | pt = (pt_val + pt_sat + pt_hue) / 3; 493 | pt = weight_of_order[j] * pt; 494 | 495 | pt_and_color.insert(pt, color); 496 | debug_flag ? qDebug().noquote() << QString("%1, %2, %3 \033[48;2;%1;%2;%3m \033[0m %5, %6, %7, weight: %4").arg(QString::number(color.red()), QString::number(color.green()), QString::number(color.blue()), QString::number(pt), QString::number(pt_val), QString::number(pt_sat), QString::number(pt_hue)) : qDebug(); 497 | j++; 498 | if (j >= i) { 499 | debug_flag ? qDebug().noquote() << "================" : qDebug(); 500 | j = 0; 501 | i = 114514; 502 | } 503 | } 504 | } 505 | 506 | void KcmColorfulHelper::setWallpaper(QString pic) 507 | { 508 | QProcess::execute("qdbus", QStringList() << "org.kde.plasmashell" << "/PlasmaShell" << "org.kde.PlasmaShell.evaluateScript" << QString("var a = desktops();\ 509 | for(i = 0; i < a.length; i++){\ 510 | d = a[i];d.wallpaperPlugin = \"org.kde.image\";\ 511 | d.currentConfigGroup = Array(\"Wallpaper\", \"org.kde.image\", \"General\");\ 512 | d.writeConfig(\"Image\", \"file://%1\");\ 513 | d.writeConfig(\"FillMode\", 2);\ 514 | d.writeConfig(\"Color\", \"#000\");\ 515 | }").arg(QFileInfo(pic).canonicalFilePath())); 516 | } 517 | 518 | QColor KcmColorfulHelper::color_refine(QColor color) 519 | { 520 | double A = 220.0 + (0.137 * (255.0 - color.saturation())); 521 | debug_flag ? qDebug() << A : qDebug(); 522 | if (color.value() < A) { 523 | if ((A - color.value()) <= 80) { 524 | color.setHsv(color.hue(), color.saturation(), static_cast(A)); 525 | } else if (((A - color.value()) > 80) && ((A - color.value()) <= 130)) { 526 | // qDebug() << (((0.5 + (0.5 * ((color.value() - (A - 130)) / 50))) * (A - color.value())) + color.value()); 527 | color.setHsv(color.hue(), color.saturation(), static_cast(((0.5 + (0.5 * ((color.value() - (A - 130)) / 50))) * (A - color.value())) + color.value())); 528 | } else { 529 | color.setHsv(color.hue(), color.saturation(), static_cast(((A - color.value()) / 2) + color.value())); 530 | } 531 | } 532 | return color; 533 | } 534 | 535 | void KcmColorfulHelper::changeThemeOpacity() 536 | { 537 | auto edit_svg = [](QString file_name, double opacity) { 538 | QFile f(file_name); 539 | if (!f.open(QIODevice::ReadWrite | QIODevice::Text)) 540 | return; 541 | QString svg_text; 542 | svg_text = f.readAll(); 543 | f.resize(0); 544 | QTextStream out(&f); 545 | svg_text.replace(QRegularExpression("([^-]+opacity[:\\s]+)[.0-9]+([^>]+?ColorScheme-ViewHover)"), "\\1" + QString::number(opacity) + "\\2"); 546 | out << svg_text; 547 | f.flush(); 548 | f.close(); 549 | }; 550 | 551 | QStringList svg_files; 552 | svg_files = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "plasma/desktoptheme/Colorful/metadata.desktop"); 553 | qDebug() << svg_files; 554 | 555 | if (svg_files.length() != 0) { 556 | if (svg_files[0].contains(".local/share")) { 557 | QFileInfo info(svg_files[0]); 558 | edit_svg(info.canonicalPath() + "/dialogs/background.svg", theme_opacity); 559 | edit_svg(info.canonicalPath() + "/widgets/panel-background.svg", theme_opacity); 560 | edit_svg(info.canonicalPath() + "/widgets/tooltip.svg", theme_opacity); 561 | } else { 562 | QDir dir; 563 | QString base_dir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); 564 | // qDebug() << base_dir; 565 | if (!QFile::exists(base_dir + "/.local/share/plasma")) { 566 | dir.mkpath(base_dir + "/.local/share/plasma"); 567 | } 568 | if (!QFile::exists(base_dir + "/.local/share/plasma/desktoptheme")) { 569 | dir.mkpath(base_dir + "/.local/share/plasma/desktoptheme"); 570 | } 571 | QFileInfo info(svg_files[0]); 572 | QProcess::execute("cp \"" + info.canonicalPath() + "\" \"" + base_dir + "/.local/share/plasma/desktoptheme/Colorful\" -rf"); 573 | QString new_location = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "plasma/desktoptheme/Colorful/metadata.desktop"); 574 | if (new_location.contains(".local/share")) { 575 | QFileInfo new_info(new_location); 576 | edit_svg(new_info.canonicalPath() + "/dialogs/background.svg", theme_opacity); 577 | edit_svg(new_info.canonicalPath() + "/widgets/panel-background.svg", theme_opacity); 578 | edit_svg(new_info.canonicalPath() + "/widgets/tooltip.svg", theme_opacity); 579 | } else { 580 | qDebug() << "Copy theme files failed!"; 581 | } 582 | } 583 | } 584 | } 585 | --------------------------------------------------------------------------------