diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c2b8d84..b144e104 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,118 +1,129 @@ cmake_minimum_required(VERSION 3.0) set(KF5_VERSION "5.39.0") # handled by release scripts set(KF5_DEP_VERSION "5.38.0") # handled by release scripts project(kirigami2 VERSION ${KF5_VERSION}) set(REQUIRED_QT_VERSION "5.7.0") ################# Disallow in-source build ################# if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") message(FATAL_ERROR "kirigami requires an out of source build. Please create a separate build directory and run 'cmake path_to_kirigami [options]' there.") endif() option(PLASMA_ENABLED "Build and install The Plasma style" ON) option(DESKTOP_ENABLED "Build and install The Desktop style" ON) option(STATIC_LIBRARY "Build as a static library" OFF) option(BUILD_EXAMPLES "Build and install examples" OFF) # Make CPack available to easy generate binary packages include(CPack) include(FeatureSummary) IF(STATIC_LIBRARY) set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) ADD_DEFINITIONS(-DKIRIGAMI_BUILD_TYPE_STATIC) find_package(Qt5 ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE COMPONENTS Core Quick Test Gui Svg) add_subdirectory(src) ELSE(STATIC_LIBRARY) ################# set KDE specific information ################# find_package(ECM 5.38.0 NO_MODULE) set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://projects.kde.org/projects/kdesupport/extra-cmake-modules") # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) +include(GenerateExportHeader) include(ECMSetupVersion) include(ECMGenerateHeaders) include(CMakePackageConfigHelpers) include(ECMPoQmTools) include(ECMQMLModules) include(KDEInstallDirs) include(KDECMakeSettings) +include(ECMQtDeclareLoggingCategory) +include(ECMAddQch) include(KDECompilerSettings NO_POLICY_SCOPE) set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5Kirigami2") +option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)" OFF) +add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)") + configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/KF5Kirigami2Config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KF5Kirigami2Config.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} PATH_VARS KF5_INCLUDE_INSTALL_DIR CMAKE_INSTALL_PREFIX ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KF5Kirigami2Config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KF5Kirigami2ConfigVersion.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/KF5Kirigami2Macros.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) +install(EXPORT KF5Kirigami2Targets + DESTINATION "${CMAKECONFIG_INSTALL_DIR}" + FILE KF5Kirigami2Targets.cmake + NAMESPACE KF5::) + ecm_setup_version(${KF5_VERSION} - VARIABLE_PREFIX KIRIGAMI + VARIABLE_PREFIX KIRIGAMI2 VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kirigami_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5Kirigami2ConfigVersion.cmake" SOVERSION 5) find_package(Qt5 ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE COMPONENTS Core Quick Test Gui Svg QuickControls2) if(BUILD_EXAMPLES AND CMAKE_SYSTEM_NAME STREQUAL "Android") # treat plasma as an optinal dep: full functionality is expected with only Qt find_package(Qt5AndroidExtras ${REQUIRED_QT_VERSION} REQUIRED) endif() if(PLASMA_ENABLED) # treat plasma as an optional dep: full functionality is expected with only Qt find_package(KF5 ${KF5_DEP_VERSION} COMPONENTS Plasma) set_package_properties(KF5Plasma PROPERTIES DESCRIPTION "Plasma framework" TYPE OPTIONAL PURPOSE "Optional Look and feel integration with Plasma Mobile." ) endif() ecm_find_qmlmodule(QtGraphicalEffects 1.0) ################# Enable C++11 features for clang and gcc ################# if(UNIX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++0x") endif() ######################################################################### add_definitions(-DQT_NO_URL_CAST_FROM_STRING) add_subdirectory(autotests) add_subdirectory(src) if (BUILD_EXAMPLES) add_subdirectory(examples) endif() ENDIF(STATIC_LIBRARY) if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po") ecm_install_po_files_as_qm(po) endif() feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/KF5Kirigami2Config.cmake.in b/KF5Kirigami2Config.cmake.in index 89cdcd14..3196055b 100644 --- a/KF5Kirigami2Config.cmake.in +++ b/KF5Kirigami2Config.cmake.in @@ -1,11 +1,15 @@ @PACKAGE_INIT@ +include(CMakeFindDependencyMacro) +find_dependency(Qt5Core @REQUIRED_QT_VERSION@) + # Any changes in this ".cmake" file will be overwritten by CMake, the source is the ".cmake.in" file. -#include("${CMAKE_CURRENT_LIST_DIR}/KF5KirigamiTargets.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/KF5Kirigami2Targets.cmake") -set(Kirigami_INSTALL_PREFIX "@PACKAGE_CMAKE_INSTALL_PREFIX@") +set(Kirigami2_INSTALL_PREFIX "@PACKAGE_CMAKE_INSTALL_PREFIX@") -#set(Kirigami_LIBRARIES KF5::Kirigami) +#set(Kirigami2_LIBRARIES KF5::Kirigami2) include("${CMAKE_CURRENT_LIST_DIR}/KF5Kirigami2Macros.cmake") +@PACKAGE_INCLUDE_QCHTARGETS@ diff --git a/KF5Kirigami2Macros.cmake b/KF5Kirigami2Macros.cmake index 58244480..85f849d6 100644 --- a/KF5Kirigami2Macros.cmake +++ b/KF5Kirigami2Macros.cmake @@ -1,82 +1,85 @@ include(CMakeParseArguments) include(ExternalProject) find_package(Git) function(kirigami_package_breeze_icons) set(_multiValueArgs ICONS) cmake_parse_arguments(ARG "" "" "${_multiValueArgs}" ${ARGN} ) if(NOT ARG_ICONS) message(FATAL_ERROR "No ICONS argument given to kirigami_package_breeze_icons") endif() #include icons used by Kirigami components themselves - set(ARG_ICONS ${ARG_ICONS} go-next go-previous go-up handle-left handle-right) + set(ARG_ICONS ${ARG_ICONS} go-next go-previous go-up handle-left handle-right go-next-symbolic go-next-symbolic-rtl go-previous-symbolic go-previous-symbolic-rtl) function(_find_breeze_icon icon varName) #HACKY SET(path "") file(GLOB_RECURSE path ${_BREEZEICONS_DIR}/icons/*/48/${icon}.svg ) #seach in other sizes as well if (NOT EXISTS ${path}) file(GLOB_RECURSE path ${_BREEZEICONS_DIR}/icons/*/32/${icon}.svg ) if (NOT EXISTS ${path}) file(GLOB_RECURSE path ${_BREEZEICONS_DIR}/icons/*/22/${icon}.svg ) endif() endif() + if (NOT EXISTS ${path}) + file(GLOB_RECURSE path ${_BREEZEICONS_DIR}/icons/*/symbolic/${icon}.svg ) + endif() if (NOT EXISTS ${path}) return() endif() get_filename_component(path "${path}" REALPATH) SET(${varName} ${path} PARENT_SCOPE) endfunction() if (BREEZEICONS_DIR AND NOT EXISTS ${BREEZEICONS_DIR}) message(FATAL_ERROR "BREEZEICONS_DIR variable does not point to existing dir: \"${BREEZEICONS_DIR}\"") endif() set(_BREEZEICONS_DIR "${BREEZEICONS_DIR}") #FIXME: this is a terrible hack if(NOT _BREEZEICONS_DIR) set(_BREEZEICONS_DIR "${CMAKE_BINARY_DIR}/breeze-icons/src/breeze-icons") # replacement for ExternalProject_Add not yet working # first time config? if (NOT EXISTS ${_BREEZEICONS_DIR}) execute_process(COMMAND ${GIT_EXECUTABLE} clone --depth 1 git://anongit.kde.org/breeze-icons.git ${_BREEZEICONS_DIR}) endif() # external projects are only pulled at make time, not configure time # so this is too late to work with the _find_breeze_icon() method # _find_breeze_icon() would need to be turned into a target/command if (FALSE) ExternalProject_Add( breeze-icons PREFIX breeze-icons GIT_REPOSITORY git://anongit.kde.org/breeze-icons.git CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" LOG_DOWNLOAD ON ) endif() endif() message (STATUS "Found external breeze icons:") foreach(_iconName ${ARG_ICONS}) set(_iconPath "") _find_breeze_icon(${_iconName} _iconPath) message (STATUS ${_iconPath}) if (EXISTS ${_iconPath}) install(FILES ${_iconPath} DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigami.2/icons/ RENAME ${_iconName}.svg) endif() endforeach() endfunction() diff --git a/README.md b/README.md index cdf10245..58a24269 100644 --- a/README.md +++ b/README.md @@ -1,108 +1,112 @@ # Kirigami ## Build examples to desktop Build all examples available ```sh mkdir build cd build cmake .. -DBUILD_EXAMPLES=ON make ``` Than, you can run: ```sh ./examples/applicationitemapp/applicationitemapp # or ./examples/galleryapp/kirigami2gallery ``` ## Build the gallery example app on Android: Make sure to install **android-sdk**, **android-ndk** and **android-qt5-arch**, where **arch** should be the same architecture that you aim to deploy. ```sh mkdir build cd build cmake .. \ -DQTANDROID_EXPORTED_TARGET=kirigami2gallery \ + -DBUILD_EXAMPLES=on \ -DANDROID_APK_DIR=../examples/galleryapp \ -DECM_DIR=/path/to/share/ECM/cmake \ -DCMAKE_TOOLCHAIN_FILE=/usr/share/ECM/toolchain/Android.cmake \ -DECM_ADDITIONAL_FIND_ROOT_PATH=/path/to/Qt5.7.0/5.7/{arch} \ - -DCMAKE_PREFIX_PATH=/path/to/Qt5.7.0/5.7/{arch}/path/to/Qt5Core + -DCMAKE_PREFIX_PATH=/path/to/Qt5.7.0/5.7/{arch}/path/to/Qt5Core \ + -DANDROID_NDK=/path/to/Android/Sdk/ndk-bundle \ + -DANDROID_SDK_ROOT=/path/to/Android/Sdk/ \ + -DANDROID_SDK_BUILD_TOOLS_REVISION=26.0.2 ``` You need a `-DCMAKE_INSTALL_PREFIX` to somewhere in your home, but using an absolute path. If you have a local checkout of the breeze-icons repo, you can avoid the cloning of the build dir by passing also `-DBREEZEICONS_DIR=/path/to/existing/sources/of/breeze-icons` ``` make create-apk-kirigami2gallery ``` `./kirigami2gallery_build_apk/build/outputs/apk/kirigami2gallery_build_apk-debug.apk` will be generated To directly install on a phone: ``` adb install -r ./kirigami2gallery_build_apk/build/outputs/apk/kirigami2gallery_build_apk-debug.apk ``` To perform this, your device need to be configureted with `USB debugging` and `install via USB` in `Developer options`. > Some ambient variables must be set before the process: `ANDROID_NDK`, `ANDROID_SDK_ROOT`, `Qt5_android` and `JAVA_HOME` ``` export ANDROID_NDK=/path/to/android-ndk export ANDROID_SDK_ROOT=/path/to/android-sdk export Qt5_android=/path/to/android-qt5/5.7.0/{arch} export PATH=$ANDROID_SDK_ROOT/platform-tools/:$PATH # adapt the following path to your ant installation export ANT=/usr/bin/ant export JAVA_HOME=/path/to/lib/jvm/java-8-openjdk/ ``` # Build on your application Android, ship it together Kirigami 1) Build kirigami ``` use the same procedure mentioned above (but without BUILD_EXAMPLES switch cd into kirigami sources directory. mkdir build cd build cmake .. -DCMAKE_TOOLCHAIN_FILE=/path/to/share/ECM/toolchain/Android.cmake -DCMAKE_PREFIX_PATH=/path/to/Qt5.7.0/5.7/android_armv7/ -DCMAKE_INSTALL_PREFIX=/path/to/dummy/install/prefix -DECM_DIR=/path/to/share/ECM/cmake ``` make make install ``` (note, omit the make create-apk-kirigami2gallery step) 2) Build your application ``` This guide assumes you build your application with CMake and use Extra-cmake-modules from KDE frameworks. cd into your application sources directory. mkdir build cd build cmake .. -DCMAKE_TOOLCHAIN_FILE=/path/to/share/ECM/toolchain/Android.cmake -DQTANDROID_EXPORTED_TARGET=yourapp -DANDROID_APK_DIR=../examples/galleryapp/ -DCMAKE_PREFIX_PATH=/path/to/Qt5.7.0/5.7/android_armv7/ -DCMAKE_INSTALL_PREFIX=/path/to/dummy/install/prefix Note, -DCMAKE_INSTALL_PREFIX folder will be the same as where kirigami was installed, since you need to create an apk package that contains both the kirigami build and the build of your application. ``` make make install make create-apk-yourapp ``` where make create-apk-yourapp dependes from the actual name of your application # Build a QMake-based application * Base upon the example in examples/minimalqmake * on android, it builds it statically, on desktop systems it uses the one distribution provided (static linking mode may be useful for other systems such as iOS or Windows) * in order to have static linking working, clone kirigami.git and breeze-icons.git under the 3rdparty folder * in your main.cpp you'll have, only on android KirigamiPlugin::getInstance().registerTypes(); which will make the import work * qtcreator should be able to do deployment on android out of the box diff --git a/autotests/tst_keynavigation.qml b/autotests/tst_keynavigation.qml index 40e9ddbc..02821042 100644 --- a/autotests/tst_keynavigation.qml +++ b/autotests/tst_keynavigation.qml @@ -1,68 +1,68 @@ /* * Copyright 2016 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Window 2.1 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami import QtTest 1.0 import "../tests" TestCase { id: testCase width: 400 height: 400 when: mainWindow.visible name: "KeyboardNavigation" KeyboardTest { id: mainWindow width: 480 height: 360 visible: true } SignalSpy { id: spyActive target: mainWindow signalName: "activeChanged" } SignalSpy { id: spyLastKey target: mainWindow.pageStack.currentItem signalName: "lastKeyChanged" } function test_press() { compare(mainWindow.pageStack.depth, 2) compare(mainWindow.pageStack.currentIndex, 1) if (!mainWindow.active) spyActive.wait(5000) verify(mainWindow.active) keyClick("A") spyLastKey.wait() compare(mainWindow.pageStack.currentItem.lastKey, "A") keyClick(Qt.Key_Left, Qt.AltModifier) compare(mainWindow.pageStack.currentIndex, 0) compare(mainWindow.pageStack.currentItem.lastKey, "") keyClick("B") spyLastKey.wait() compare(mainWindow.pageStack.currentItem.lastKey, "B") } } diff --git a/autotests/tst_listskeynavigation.qml b/autotests/tst_listskeynavigation.qml index d5f77aba..89295cbb 100644 --- a/autotests/tst_listskeynavigation.qml +++ b/autotests/tst_listskeynavigation.qml @@ -1,64 +1,64 @@ /* * Copyright 2016 Aleix Pol Gonzalez * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Window 2.1 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami import QtTest 1.0 import "../tests" TestCase { id: testCase width: 400 height: 400 when: mainWindow.visible name: "KeyboardListsNavigation" KeyboardListTest { id: mainWindow width: 480 height: 360 visible: true } SignalSpy { id: spyActive target: mainWindow signalName: "activeChanged" } SignalSpy { id: spyCurrentIndex target: mainWindow.pageStack.currentItem.flickable signalName: "currentIndexChanged" } function test_press() { compare(mainWindow.pageStack.depth, 1) compare(mainWindow.pageStack.currentIndex, 0) if (!mainWindow.active) spyActive.wait(5000) verify(mainWindow.active) compare(mainWindow.pageStack.currentItem.flickable.currentIndex, 0) keyClick(Qt.Key_Down) spyCurrentIndex.wait() compare(mainWindow.pageStack.currentItem.flickable.currentIndex, 1) } } diff --git a/autotests/tst_pagerow.qml b/autotests/tst_pagerow.qml index 8705616b..4c136fb0 100644 --- a/autotests/tst_pagerow.qml +++ b/autotests/tst_pagerow.qml @@ -1,141 +1,141 @@ /* * Copyright 2016 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Window 2.1 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami import QtTest 1.0 TestCase { id: testCase // when: mainWindow.visible width: 400 height: 400 // visible: true when: mainWindow.visible name: "GoBack" function applicationWindow() { return mainWindow; } Kirigami.ApplicationWindow { id: mainWindow width: 480 height: 360 visible: true pageStack.initialPage: Kirigami.Page { Rectangle { anchors.fill: parent color: "green" } } } Component { id: randomPage Kirigami.Page { Rectangle { anchors.fill: parent color: "red" } } } SignalSpy { id: spyCurrentIndex target: mainWindow.pageStack signalName: "currentIndexChanged" } SignalSpy { id: spyActive target: mainWindow signalName: "activeChanged" } function init() { mainWindow.pageStack.clear() spyActive.clear() spyCurrentIndex.clear() } function test_pop() { compare(mainWindow.pageStack.depth, 0) mainWindow.pageStack.push(randomPage) compare(mainWindow.pageStack.depth, 1) mainWindow.pageStack.pop() compare(mainWindow.pageStack.depth, 0) } function test_goBack() { compare(mainWindow.pageStack.depth, 0) mainWindow.pageStack.push(randomPage) mainWindow.pageStack.push(randomPage) compare(mainWindow.pageStack.depth, 2) compare(mainWindow.pageStack.currentIndex, 1) compare(spyCurrentIndex.count, 2) spyActive.clear() mainWindow.requestActivate() spyCurrentIndex.clear() if (!mainWindow.active) spyActive.wait() verify(mainWindow.active) keyClick(Qt.Key_Left, Qt.AltModifier) spyCurrentIndex.wait() compare(mainWindow.pageStack.depth, 2) compare(mainWindow.pageStack.currentIndex, 0) compare(spyCurrentIndex.count, 1) mainWindow.pageStack.pop() compare(mainWindow.pageStack.depth, 1) } property int destructions: 0 Component { id: destroyedPage Kirigami.Page { id: page Rectangle { anchors.fill: parent color: "blue" Component.onDestruction: { console.log("ko", page) testCase.destructions++ } } } } SignalSpy { id: spyDestructions target: testCase signalName: "destructionsChanged" } function test_clearPages() { mainWindow.pageStack.push(destroyedPage) mainWindow.pageStack.push(destroyedPage) mainWindow.pageStack.push(destroyedPage) compare(mainWindow.pageStack.depth, 3) mainWindow.pageStack.clear() compare(mainWindow.pageStack.depth, 0) console.log(spyDestructions.wait()) compare(testCase.destructions, 3) } } diff --git a/examples/applicationitemapp/main.qml b/examples/applicationitemapp/main.qml index 0f23e920..8aaa2b5c 100644 --- a/examples/applicationitemapp/main.qml +++ b/examples/applicationitemapp/main.qml @@ -1,81 +1,81 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 -import org.kde.kirigami 2.1 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ApplicationItem { id: root globalDrawer: Kirigami.GlobalDrawer { title: "Hello App" titleIcon: "applications-graphics" actions: [ Kirigami.Action { text: "View" iconName: "view-list-icons" Kirigami.Action { text: "action 1" } Kirigami.Action { text: "action 2" } Kirigami.Action { text: "action 3" } }, Kirigami.Action { text: "action 3" }, Kirigami.Action { text: "action 4" } ] handleVisible: true } contextDrawer: Kirigami.ContextDrawer { id: contextDrawer } pageStack.initialPage: mainPageComponent Component { id: mainPageComponent Kirigami.Page { title: "Hello" actions { contextualActions: [ Kirigami.Action { text: "action 1" }, Kirigami.Action { text: "action 2" } ] } Rectangle { color: "red" anchors.fill: parent } } } } diff --git a/examples/galleryapp/CMakeLists.txt b/examples/galleryapp/CMakeLists.txt index d4c8e461..78d7f78d 100644 --- a/examples/galleryapp/CMakeLists.txt +++ b/examples/galleryapp/CMakeLists.txt @@ -1,42 +1,70 @@ +find_package(KF5Kirigami2 ${KF5_DEP_VERSION}) + set(kirigami2gallery_SRCS main.cpp ) qt5_add_resources(RESOURCES resources.qrc) if (CMAKE_SYSTEM_NAME STREQUAL "Android") - set(kirigami2gallery_EXTRA_LIBS Qt5::AndroidExtras Qt5::QuickControls2) + set(kirigami2gallery_EXTRA_LIBS Qt5::AndroidExtras + #FIXME: we shouldn't have to link to it but otherwise the lib won't be packaged on Android + Qt5::QuickControls2 KF5::Kirigami2) +endif() + +find_program(kpackagetool_cmd kpackagetool5) +if (kpackagetool_cmd) + set(component org.kde.kirigami2.gallery) + set(APPDATAFILE "${CMAKE_CURRENT_BINARY_DIR}/${component}.appdata.xml") + + message(STATUS "${kpackagetool_cmd} --appstream-metainfo ${CMAKE_CURRENT_SOURCE_DIR}/../gallerydata --appstream-metainfo-output ${APPDATAFILE}") + execute_process( + COMMAND ${kpackagetool_cmd} --appstream-metainfo ${CMAKE_CURRENT_SOURCE_DIR}/../gallerydata --appstream-metainfo-output ${APPDATAFILE} + ERROR_VARIABLE appstreamerror + RESULT_VARIABLE result) + if (NOT result EQUAL 0) + message(WARNING "couldn't generate metainfo for ${component}: ${appstreamerror}") + else() + if(appstreamerror) + message(WARNING "warnings during generation of metainfo for ${component}: ${appstreamerror}") + endif() + + # OPTIONAL because desktop files can be NoDisplay so they render no XML. + install(FILES ${APPDATAFILE} DESTINATION ${KDE_INSTALL_METAINFODIR} OPTIONAL) + endif() +else() + message(WARNING "KPackage components should be specified in reverse domain notation. Appstream information won't be generated for ${component}.") endif() find_program(kpackagetool_cmd kpackagetool5) if (kpackagetool_cmd) set(component org.kde.kirigami2.gallery) set(APPDATAFILE "${CMAKE_CURRENT_BINARY_DIR}/${component}.appdata.xml") message(STATUS "${kpackagetool_cmd} --appstream-metainfo ${CMAKE_CURRENT_SOURCE_DIR}/../gallerydata --appstream-metainfo-output ${APPDATAFILE}") execute_process( COMMAND ${kpackagetool_cmd} --appstream-metainfo ${CMAKE_CURRENT_SOURCE_DIR}/../gallerydata --appstream-metainfo-output ${APPDATAFILE} ERROR_VARIABLE appstreamerror RESULT_VARIABLE result) if (NOT result EQUAL 0) message(WARNING "couldn't generate metainfo for ${component}: ${appstreamerror}") else() if(appstreamerror) message(WARNING "warnings during generation of metainfo for ${component}: ${appstreamerror}") endif() # OPTIONAL because desktop files can be NoDisplay so they render no XML. install(FILES ${APPDATAFILE} DESTINATION ${KDE_INSTALL_METAINFODIR} OPTIONAL) endif() else() message(WARNING "KPackage components should be specified in reverse domain notation. Appstream information won't be generated for ${component}.") endif() add_executable(kirigami2gallery ${kirigami2gallery_SRCS} ${RESOURCES}) target_link_libraries(kirigami2gallery Qt5::Core Qt5::Qml Qt5::Quick Qt5::Svg ${kirigami2gallery_EXTRA_LIBS}) install(TARGETS kirigami2gallery ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) include(${CMAKE_SOURCE_DIR}/KF5Kirigami2Macros.cmake) -kirigami_package_breeze_icons(ICONS applications-graphics view-list-icons folder-sync view-list-details configure document-edit dialog-cancel document-decrypt mail-reply-sender bookmarks folder) +kirigami_package_breeze_icons(ICONS applications-graphics view-list-icons folder-sync view-list-details configure document-edit dialog-cancel document-decrypt mail-reply-sender bookmarks folder media-record-symbolic) diff --git a/examples/galleryapp/resources.qrc b/examples/galleryapp/resources.qrc index f3d3cc8b..3fa0c30c 100644 --- a/examples/galleryapp/resources.qrc +++ b/examples/galleryapp/resources.qrc @@ -1,26 +1,27 @@ ../gallerydata/contents/ui/MainPage.qml ../gallerydata/contents/ui/banner.jpg ../gallerydata/contents/ui/gallery/NonScrollableGallery.qml ../gallerydata/contents/ui/gallery/RadioButtonGallery.qml ../gallerydata/contents/ui/gallery/ButtonGallery.qml ../gallerydata/contents/ui/gallery/ProgressBarGallery.qml ../gallerydata/contents/ui/gallery/CheckBoxGallery.qml ../gallerydata/contents/ui/gallery/SliderGallery.qml ../gallerydata/contents/ui/gallery/MultipleColumnsGallery.qml ../gallerydata/contents/ui/gallery/MiscGallery.qml ../gallerydata/contents/ui/gallery/ListViewGallery.qml ../gallerydata/contents/ui/gallery/ListViewHeaderItemsGallery.qml ../gallerydata/contents/ui/gallery/SwitchGallery.qml ../gallerydata/contents/ui/gallery/TabBarGallery.qml ../gallerydata/contents/ui/gallery/TextFieldGallery.qml ../gallerydata/contents/ui/gallery/ColorsGallery.qml ../gallerydata/contents/ui/gallery/MetricsGallery.qml ../gallerydata/contents/ui/gallery/LayersGallery.qml ../gallerydata/contents/ui/ExampleApp.qml + ../gallerydata/contents/ui/gallery/ColorSetGallery.qml ../gallerydata/contents/ui/DesktopExampleApp.qml ../gallerydata/metadata.desktop qtquickcontrols2.conf diff --git a/examples/gallerydata/contents/ui/DesktopExampleApp.qml b/examples/gallerydata/contents/ui/DesktopExampleApp.qml index 257dd163..56aedcea 100644 --- a/examples/gallerydata/contents/ui/DesktopExampleApp.qml +++ b/examples/gallerydata/contents/ui/DesktopExampleApp.qml @@ -1,136 +1,136 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami import "gallery" Kirigami.ApplicationWindow { id: root header: Kirigami.ToolBarApplicationHeader {} globalDrawer: Kirigami.GlobalDrawer { title: "Widget gallery" titleIcon: "applications-graphics" bannerImageSource: "banner.jpg" actions: [ Kirigami.Action { text: "Submenu 1" iconName: "view-list-icons" Kirigami.Action { text: "Action 1" onTriggered: showPassiveNotification(text + " clicked") } Kirigami.Action { text: "Action 2" onTriggered: showPassiveNotification(text + " clicked") } Kirigami.Action { text: "Action 3" onTriggered: showPassiveNotification(text + " clicked") } }, Kirigami.Action { text: "Submenu 2" iconName: "folder-sync" Kirigami.Action { text: "Action 4" onTriggered: showPassiveNotification(text + " clicked") } Kirigami.Action { text: "Action 5" onTriggered: showPassiveNotification(text + " clicked") } }, Kirigami.Action { text: "Checkable" iconName: "go-next" checkable: true checked: false onTriggered: { showPassiveNotification("Action checked: " + checked) } }, Kirigami.Action { text: "Open A Page" iconName: "view-list-details" checkable: true //Need to do this, otherwise it breaks the bindings property bool current: pageStack.currentItem ? pageStack.currentItem.objectName == "settingsPage" : false onCurrentChanged: { checked = current; } onTriggered: { pageStack.push(settingsComponent); } }, Kirigami.Action { text: "Open A Layer" iconName: "configure" onTriggered: { pageStack.layers.push(Qt.resolvedUrl("gallery/LayersGallery.qml")); } } ] Controls.CheckBox { checked: true text: "Option 1" } Controls.CheckBox { text: "Option 2" } Controls.CheckBox { text: "Option 3" } Controls.Slider { Layout.fillWidth: true value: 0.5 } } pageStack.initialPage: mainPageComponent Component { id: settingsComponent Kirigami.Page { title: "Settings" objectName: "settingsPage" Rectangle { anchors.fill: parent Controls.Button { anchors.centerIn: parent text: "Remove Page" onClicked: applicationWindow().pageStack.pop(); } } } } //Main app content Component { id: mainPageComponent MainPage {} } } diff --git a/examples/gallerydata/contents/ui/ExampleApp.qml b/examples/gallerydata/contents/ui/ExampleApp.qml index 8482a479..249cf9c7 100644 --- a/examples/gallerydata/contents/ui/ExampleApp.qml +++ b/examples/gallerydata/contents/ui/ExampleApp.qml @@ -1,139 +1,139 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.1 as Kirigami +import org.kde.kirigami 2.2 as Kirigami import "gallery" Kirigami.ApplicationWindow { id: root header: Kirigami.ApplicationHeader {} globalDrawer: Kirigami.GlobalDrawer { title: "Widget gallery" titleIcon: "applications-graphics" bannerImageSource: "banner.jpg" actions: [ Kirigami.Action { text: "Submenu 1" iconName: "view-list-icons" Kirigami.Action { text: "Action 1" onTriggered: showPassiveNotification(text + " clicked") } Kirigami.Action { text: "Action 2" onTriggered: showPassiveNotification(text + " clicked") } Kirigami.Action { text: "Action 3" onTriggered: showPassiveNotification(text + " clicked") } }, Kirigami.Action { text: "Submenu 2" iconName: "folder-sync" Kirigami.Action { text: "Action 4" onTriggered: showPassiveNotification(text + " clicked") } Kirigami.Action { text: "Action 5" onTriggered: showPassiveNotification(text + " clicked") } }, Kirigami.Action { text: "Checkable" iconName: "go-next" checkable: true checked: false onTriggered: { showPassiveNotification("Action checked: " + checked) } }, Kirigami.Action { text: "Open A Page" iconName: "view-list-details" checkable: true //Need to do this, otherwise it breaks the bindings property bool current: pageStack.currentItem ? pageStack.currentItem.objectName == "settingsPage" : false onCurrentChanged: { checked = current; } onTriggered: { pageStack.push(settingsComponent); } }, Kirigami.Action { text: "Open A Layer" iconName: "configure" onTriggered: { pageStack.layers.push(Qt.resolvedUrl("gallery/LayersGallery.qml")); } } ] Controls.CheckBox { checked: true text: "Option 1" } Controls.CheckBox { text: "Option 2" } Controls.CheckBox { text: "Option 3" } Controls.Slider { Layout.fillWidth: true value: 0.5 } } contextDrawer: Kirigami.ContextDrawer { id: contextDrawer } pageStack.initialPage: mainPageComponent Component { id: settingsComponent Kirigami.Page { title: "Settings" objectName: "settingsPage" Rectangle { anchors.fill: parent Controls.Button { anchors.centerIn: parent text: "Remove Page" onClicked: applicationWindow().pageStack.pop(); } } } } //Main app content Component { id: mainPageComponent MainPage {} } } diff --git a/examples/gallerydata/contents/ui/MainPage.qml b/examples/gallerydata/contents/ui/MainPage.qml index 3b801413..75a2ba42 100644 --- a/examples/gallerydata/contents/ui/MainPage.qml +++ b/examples/gallerydata/contents/ui/MainPage.qml @@ -1,151 +1,155 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Controls 2.0 as QQC2 import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ScrollablePage { id: pageRoot implicitWidth: Kirigami.Units.gridUnit * 20 background: Rectangle { - color: Kirigami.Theme.viewBackgroundColor + color: Kirigami.Theme.backgroundColor } title: "Gallery" //flickable: mainListView actions { contextualActions: [ Kirigami.Action { text:"Action 1" iconName: "document-decrypt" onTriggered: showPassiveNotification("Action 1 clicked") }, Kirigami.Action { id: shareAction visible: checkableAction.checked text:"Action 2" iconName: "document-share" onTriggered: showPassiveNotification("Action 2 clicked") }, Kirigami.Action { id: checkableAction text:"Checkable" checkable: true iconName: "dashboard-show" onCheckedChanged: showPassiveNotification("Checked: " + checked) } ] } ListView { id: mainListView currentIndex: -1 //currentIndex has focus, openPageIndex is the one actually open now property int openPageIndex: -1 activeFocusOnTab: true focus: true model: ListModel { ListElement { text: "Button" component: "Button" } ListElement { text: "CheckBox" component: "CheckBox" } ListElement { text: "Radio Button" component: "RadioButton" } ListElement { text: "Progress Bar" component: "ProgressBar" } ListElement { text: "Slider" component: "Slider" } ListElement { text: "Switch" component: "Switch" } ListElement { text: "Tab Bar" component: "TabBar" } ListElement { text: "Text Field" component: "TextField" } ListElement { text: "Multiple Columns" component: "MultipleColumns" } ListElement { text: "Misc widgets" component: "Misc" } ListElement { text: "List View" component: "ListView" } ListElement { text: "List Headers" component: "ListViewHeaderItems" } ListElement { text: "Non Scrollable Page" component: "NonScrollable" } ListElement { text: "Colors" component: "Colors" } + ListElement { + text: "Color Sets" + component: "ColorSet" + } ListElement { text: "Metrics" component: "Metrics" } } delegate: Kirigami.BasicListItem { id: listItem reserveSpaceForIcon: false label: model.text Accessible.role: Accessible.MenuItem property Item ownPage onClicked: { if (!model.component) { return; } root.pageStack.pop(pageRoot); root.pageStack.push(Qt.resolvedUrl("gallery/" + model.component + "Gallery.qml")); mainListView.openPageIndex = index; } checked: mainListView.openPageIndex == index highlighted: focus && ListView.isCurrentItem } } } diff --git a/examples/gallerydata/contents/ui/gallery/ButtonGallery.qml b/examples/gallerydata/contents/ui/gallery/ButtonGallery.qml index b5fd1ddf..8bb57bc9 100644 --- a/examples/gallerydata/contents/ui/gallery/ButtonGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/ButtonGallery.qml @@ -1,197 +1,197 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 ScrollablePage { id: page Layout.fillWidth: true //implicitWidth: Units.gridUnit * (Math.floor(Math.random() * 35) + 10) title: "Buttons" actions { main: Action { iconName: sheet.sheetOpen ? "dialog-cancel" : "document-edit" text: "Main Action Text" checkable: true onCheckedChanged: sheet.sheetOpen = checked; shortcut: "Alt+S" } left: Action { iconName: "go-previous" text: "Left Action Text" onTriggered: { showPassiveNotification(" Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id risus id augue euismod accumsan. Nunc vestibulum placerat bibendum. Morbi commodo auctor varius. Donec molestie euismod ultrices. Sed facilisis augue nec eros auctor, vitae mattis quam rhoncus. Nam ut erat diam. Curabitur iaculis accumsan magna, eget fermentum massa scelerisque eu. Cras elementum erat non erat euismod accumsan. Vestibulum ac mi sed dui finibus pulvinar. Vivamus dictum, leo sed lobortis porttitor, nisl magna faucibus orci, sit amet euismod arcu elit eget est. Duis et vehicula nibh. In arcu sapien, laoreet sit amet porttitor non, rhoncus vel magna. Suspendisse imperdiet consectetur est nec ornare. Pellentesque bibendum sapien at erat efficitur vehicula. Morbi sed porta nibh. Vestibulum ut urna ut dolor sagittis mattis.") } } right: Action { iconName: "go-next" text: "Right Action Text" onTriggered: { showPassiveNotification("Right action triggered") } } contextualActions: [ Action { text:"Action for buttons" iconName: "bookmarks" onTriggered: showPassiveNotification("Action 1 clicked") }, Action { text:"Disabled Action" iconName: "folder" enabled: false }, Action { text: "Action for Sheet" visible: sheet.sheetOpen } ] } //Close the drawer with the back button onBackRequested: { if (bottomDrawer.drawerOpen) { event.accepted = true; bottomDrawer.close(); } if (sheet.sheetOpen) { event.accepted = true; sheet.close(); } } OverlayDrawer { id: bottomDrawer edge: Qt.BottomEdge contentItem: Item { implicitHeight: childrenRect.height + Units.gridUnit ColumnLayout { anchors.centerIn: parent Controls.Button { text: "Button1" onClicked: showPassiveNotification("Button 1 clicked") } Controls.Button { text: "Button2" onClicked: showPassiveNotification("Button 2 clicked") } Item { Layout.minimumHeight: Units.gridUnit * 4 } } } } OverlaySheet { id: sheet onSheetOpenChanged: page.actions.main.checked = sheetOpen ColumnLayout { Label { Layout.fillWidth: true wrapMode: Text.WordWrap text: " Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id risus id augue euismod accumsan. Nunc vestibulum placerat bibendum. Morbi commodo auctor varius. Donec molestie euismod ultrices. Sed facilisis augue nec eros auctor, vitae mattis quam rhoncus. Nam ut erat diam. Curabitur iaculis accumsan magna, eget fermentum massa scelerisque eu. Cras elementum erat non erat euismod accumsan. Vestibulum ac mi sed dui finibus pulvinar. Vivamus dictum, leo sed lobortis porttitor, nisl magna faucibus orci, sit amet euismod arcu elit eget est. Duis et vehicula nibh. In arcu sapien, laoreet sit amet porttitor non, rhoncus vel magna. Suspendisse imperdiet consectetur est nec ornare. Pellentesque bibendum sapien at erat efficitur vehicula. Morbi sed porta nibh. Vestibulum ut urna ut dolor sagittis mattis." } Controls.TextField { Layout.alignment: Qt.AlignHCenter } Label { Layout.fillWidth: true wrapMode: Text.WordWrap text: " Morbi dictum, sapien at maximus pulvinar, sapien metus condimentum magna, quis lobortis nisi dui mollis turpis. Aliquam sit amet scelerisque dui. In sit amet tellus placerat, condimentum enim sed, hendrerit quam. Integer dapibus lobortis finibus. Suspendisse faucibus eros vitae ante posuere blandit. Nullam volutpat quam id diam hendrerit aliquam. Donec non sem at diam posuere convallis. Vivamus ut congue quam. Ut dictum fermentum sapien, eu ultricies est ornare ut. Nullam fringilla a libero vehicula faucibus. Donec euismod sodales nulla, in vehicula lectus posuere a. Donec nisi nulla, pulvinar eu porttitor vitae, varius eget ante. Nam rutrum eleifend elit, quis facilisis leo sodales vitae. Aenean accumsan a nulla at sagittis. Integer placerat tristique magna, vitae iaculis ante cursus sit amet. Sed facilisis mollis turpis nec tristique. Etiam quis feugiat odio. Vivamus sagittis at purus nec aliquam. Morbi neque dolor, elementum ac fermentum ac, auctor ut erat. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vivamus non nibh sit amet quam luctus congue. Donec in eros varius, porta metus sed, sagittis lacus. Mauris dapibus lorem nisi, non eleifend massa tristique egestas. Curabitur nec blandit urna. Mauris rhoncus libero felis, commodo viverra ante consectetur vel. Donec dictum tincidunt orci, quis tristique urna. Quisque egestas, dui ac mollis dictum, purus velit elementum est, at pellentesque erat est fermentum purus. Nulla a quam tellus. Vestibulum a congue ligula. Quisque feugiat nulla et tortor sodales viverra. Maecenas dolor leo, elementum sed urna vel, posuere hendrerit metus. Mauris pellentesque, mi non luctus aliquam, leo nulla varius arcu, vel pulvinar enim enim nec nisl. Etiam sapien leo, venenatis eget justo at, pellentesque mollis tellus. Fusce consequat ullamcorper vulputate. Duis tellus nisi, dictum ut augue non, elementum congue ligula. Fusce in vehicula arcu. Nulla facilisi. Quisque a convallis sapien. Aenean pellentesque convallis egestas. Phasellus rhoncus, nulla in tempor maximus, arcu ex venenatis diam, sit amet egestas mi dolor non ante. " } Controls.Button { text: "Close" anchors.horizontalCenter: parent.horizontalCenter onClicked: sheet.close() } } } ColumnLayout { width: page.width spacing: Units.smallSpacing Controls.Button { text: "Open Bottom drawer" anchors.horizontalCenter: parent.horizontalCenter onClicked: bottomDrawer.open() } Controls.Button { text: "Open Sheet" anchors.horizontalCenter: parent.horizontalCenter onClicked: sheet.open() } Controls.Button { text: "Toggle Action Button" anchors.horizontalCenter: parent.horizontalCenter onClicked: mainAction.visible = !mainAction.visible; } Controls.Button { text: "Show Passive Notification" anchors.horizontalCenter: parent.horizontalCenter onClicked: showPassiveNotification("This is a passive message", 3000); } Controls.Button { text: "Passive Notification Action" anchors.horizontalCenter: parent.horizontalCenter onClicked: showPassiveNotification("This is a passive message", "long", "Action", function() {showPassiveNotification("Passive notification action clicked")}); } Controls.ToolButton { text: "Toggle controls" checkable: true checked: true anchors.horizontalCenter: parent.horizontalCenter onCheckedChanged: applicationWindow().controlsVisible = checked } Controls.Button { text: "Disabled Button" enabled: false anchors.horizontalCenter: parent.horizontalCenter onClicked: showPassiveNotification("clicked") } Controls.ToolButton { text: "Tool Button" anchors.horizontalCenter: parent.horizontalCenter onClicked: showPassiveNotification(text + " clicked") } Controls.ToolButton { text: "Tool Button non flat" flat: false anchors.horizontalCenter: parent.horizontalCenter onClicked: showPassiveNotification(text + " clicked") } } } diff --git a/examples/gallerydata/contents/ui/gallery/CheckBoxGallery.qml b/examples/gallerydata/contents/ui/gallery/CheckBoxGallery.qml index bcef8db3..b2598cb2 100644 --- a/examples/gallerydata/contents/ui/gallery/CheckBoxGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/CheckBoxGallery.qml @@ -1,120 +1,120 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 ScrollablePage { id: page actions { main: Action { iconName: sheet.sheetOpen ? "dialog-cancel" : "document-edit" text: "Main Action Text" checked: sheet.sheetOpen checkable: true onCheckedChanged: sheet.sheetOpen = checked; } contextualActions: [ Action { text:"Action 1" onTriggered: showPassiveNotification("Action 1 clicked") }, Action { text:"Action 2" onTriggered: showPassiveNotification("Action 2 clicked") } ] } Layout.fillWidth: true title: "Checkboxes" OverlaySheet { id: sheet Label { property int implicitWidth: Units.gridUnit * 45 wrapMode: Text.WordWrap text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id risus id augue euismod accumsan. Nunc vestibulum placerat bibendum. Morbi commodo auctor varius. Donec molestie euismod ultrices. Sed facilisis augue nec eros auctor, vitae mattis quam rhoncus. Nam ut erat diam. Curabitur iaculis accumsan magna, eget fermentum massa scelerisque eu. Cras elementum erat non erat euismod accumsan. Vestibulum ac mi sed dui finibus pulvinar. Vivamus dictum, leo sed lobortis porttitor, nisl magna faucibus orci, sit amet euismod arcu elit eget est. Duis et vehicula nibh. In arcu sapien, laoreet sit amet porttitor non, rhoncus vel magna. Suspendisse imperdiet consectetur est nec ornare. Pellentesque bibendum sapien at erat efficitur vehicula. Morbi sed porta nibh. Vestibulum ut urna ut dolor sagittis mattis." } } ColumnLayout { //This OverlaySheet is put in the "wrong place", but will be automatically reparented // to "page" Item { Layout.fillWidth: true Layout.minimumHeight: Units.gridUnit * 10 GridLayout { id: grid anchors.centerIn: parent columns: 3 rows: 3 rowSpacing: Units.smallSpacing Item { width: 1 height: 1 } Label { text: "Normal" } Label { text: "Disabled" enabled: false } Label { text: "On" } Controls.CheckBox { text: "On" checked: true } Controls.CheckBox { text: "On" checked: true enabled: false } Label { text: "Off" } Controls.CheckBox { text: "Off" checked: false } Controls.CheckBox { text: "Off" checked: false enabled: false } } Controls.CheckBox { anchors { top: grid.bottom left: grid.left } text: "Tristate" checked: true tristate: true } } } } diff --git a/examples/gallerydata/contents/ui/gallery/ColorSetGallery.qml b/examples/gallerydata/contents/ui/gallery/ColorSetGallery.qml new file mode 100644 index 00000000..af094fd7 --- /dev/null +++ b/examples/gallerydata/contents/ui/gallery/ColorSetGallery.qml @@ -0,0 +1,180 @@ +/* + * Copyright 2017 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.0 +import QtQuick.Controls 2.0 as Controls +import QtQuick.Layouts 1.2 +import org.kde.kirigami 2.2 as Kirigami + +Kirigami.ScrollablePage { + id: page + title: "Color Sets" + + background: Rectangle { + color: Kirigami.Theme.backgroundColor + } + ColumnLayout { + GridLayout { + columns: 2 + Kirigami.Label { + text: "Global Drawer color set:" + Layout.alignment: Qt.AlignRight + } + Controls.ComboBox { + Kirigami.Theme.inherit: true + currentIndex: 0 + model: ["View", "Window", "Button", "Selection", "Tooltip", "Complementary"] + onCurrentTextChanged: applicationWindow().globalDrawer.Kirigami.Theme.colorSet = currentText + } + + Kirigami.Label { + text: "Page color set:" + Layout.alignment: Qt.AlignRight + } + Controls.ComboBox { + Kirigami.Theme.inherit: true + currentIndex: 1 + model: ["View", "Window", "Button", "Selection", "Tooltip", "Complementary"] + onCurrentTextChanged: page.Kirigami.Theme.colorSet = currentText + } + } + + Controls.Frame { + Kirigami.Theme.inherit: true + Layout.minimumHeight: childrenRect.height + Layout.fillWidth: true + height: childrenRect.height + width: parent.width + background: Rectangle { + color: Kirigami.Theme.backgroundColor + } + contentItem: ColumnLayout { + width: parent.width + Kirigami.Label { + text: "Set inherited from parent Item" + } + Kirigami.BasicListItem { + width: parent.width + icon: "media-record-symbolic" + label: "Delegate1" + } + Kirigami.BasicListItem { + width: parent.width + label: "Delegate2" + } + } + } + + Controls.Frame { + Kirigami.Theme.inherit: false + Kirigami.Theme.colorSet: Kirigami.Theme.Window + Layout.minimumHeight: childrenRect.height + Layout.fillWidth: true + height: childrenRect.height + width: parent.width + background: Rectangle { + color: Kirigami.Theme.backgroundColor + } + contentItem: ColumnLayout { + width: parent.width + Kirigami.Label { + text: "Window Set" + } + Kirigami.BasicListItem { + width: parent.width + icon: "media-record-symbolic" + label: "Delegate1" + } + Kirigami.BasicListItem { + width: parent.width + label: "Delegate2" + } + } + } + + Controls.Frame { + Kirigami.Theme.inherit: false + Kirigami.Theme.colorSet: Kirigami.Theme.View + Layout.minimumHeight: childrenRect.height + Layout.fillWidth: true + height: childrenRect.height + width: parent.width + background: Rectangle { + color: Kirigami.Theme.backgroundColor + } + contentItem: ColumnLayout { + width: parent.width + Kirigami.Label { + text: "View Set" + } + Kirigami.BasicListItem { + width: parent.width + icon: "media-record-symbolic" + label: "Delegate1" + } + Kirigami.BasicListItem { + width: parent.width + label: "Delegate2" + } + } + } + + Controls.Frame { + Kirigami.Theme.inherit: false + Kirigami.Theme.colorSet: Kirigami.Theme.Complementary + Layout.minimumHeight: childrenRect.height + Layout.fillWidth: true + height: childrenRect.height + width: parent.width + background: Rectangle { + color: Kirigami.Theme.backgroundColor + } + contentItem: ColumnLayout { + Kirigami.Label { + text: "Complementary Set" + } + Kirigami.BasicListItem { + width: parent.width + icon: "media-record-symbolic" + label: "Delegate1" + } + Kirigami.BasicListItem { + width: parent.width + label: "Delegate2" + } + } + } + + Controls.Button { + Kirigami.Theme.colorSet: Kirigami.Theme.Button + Kirigami.Theme.inherit: false + text: "Fixed Color Button" + } + Controls.Button { + Kirigami.Theme.inherit: true + text: "Dynamic Color Button" + } + Kirigami.Icon { + source: "media-record-symbolic" + color: "green" + Layout.minimumWidth: 32 + Layout.minimumHeight: 32 + } + } +} diff --git a/examples/gallerydata/contents/ui/gallery/ColorsGallery.qml b/examples/gallerydata/contents/ui/gallery/ColorsGallery.qml index 8a9aac85..6b355f34 100644 --- a/examples/gallerydata/contents/ui/gallery/ColorsGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/ColorsGallery.qml @@ -1,74 +1,118 @@ /* * Copyright 2016 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 ScrollablePage { + id: page title: "Colors" // leftPadding: 20//Units.gridUnit function endsWith(subject, predicate) { var idx = subject.indexOf(predicate); return idx + predicate.length == subject.length; } + function getkeys() { - var keys = []; - for(var v in Theme) { - if (endsWith(v, "Color")) - keys.push(v); + var keys = ["textColor", + "disabledTextColor", + "highlightedTextColor", + "activeTextColor", + "linkColor", + "visitedLinkColor", + "negativeTextColor", + "neutralTextColor", + "positiveTextColor", + "backgroundColor", + "highlightColor", + "focusColor", + "hoverColor"]; + + return keys; + } + + function setName(id) { + switch(id) { + case 0: + return "Theme.View"; + case 1: + return "Theme.Window"; + case 2: + return "Theme.Button"; + case 3: + return "Theme.Selection"; + case 4: + return "Theme.Tooltip"; + case 5: + return "Theme.Complementary"; } - keys.sort(); - return keys; } Column { - Flow { - id: view - anchors.horizontalCenter: parent.horizontalCenter - width: Math.floor(parent.width / (Units.gridUnit * 9)) * (Units.gridUnit * 9) - Repeater { - model: getkeys() + Heading { + text: "Colors by Theme.colorSet" + } + Repeater { + model: Theme.Complementary + 1 + delegate: Column { + width: parent.width + Heading { + level: 2 + text: setName(modelData) + } + Flow { + id: view + Theme.colorSet: modelData + Theme.inherit: false + anchors.horizontalCenter: parent.horizontalCenter + width: Math.floor(parent.width / (Units.gridUnit * 9)) * (Units.gridUnit * 9) + Repeater { + model: page.getkeys() - delegate: ColumnLayout { - width: Units.gridUnit * 9 - Rectangle { - Layout.alignment: Qt.AlignHCenter - width: Units.gridUnit * 7 - height: Units.gridUnit * 3 - color: Theme[modelData] - border { - width: 1 - color: "black" + delegate: ColumnLayout { + width: Units.gridUnit * 9 + Rectangle { + Layout.alignment: Qt.AlignHCenter + width: Units.gridUnit * 7 + height: Units.gridUnit * 3 + color: Theme[modelData] + border { + width: 1 + color: "black" + } + } + Label { + Theme.colorSet: Theme.Window + Theme.inherit: false + Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter + text: modelData + } + Item { + width: 1 + height: Units.smallSpacing + } } } - Label { - Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter - text: modelData - } - Item { - width: 1 - height: Units.smallSpacing - } } } } } } diff --git a/examples/gallerydata/contents/ui/gallery/LayersGallery.qml b/examples/gallerydata/contents/ui/gallery/LayersGallery.qml index 81dc2ad1..68171296 100644 --- a/examples/gallerydata/contents/ui/gallery/LayersGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/LayersGallery.qml @@ -1,85 +1,85 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 ScrollablePage { id: page Layout.fillWidth: true //implicitWidth: Units.gridUnit * (Math.floor(Math.random() * 35) + 8) title: "Multiple Columns" actions { main: Action { iconName: "document-edit" text: "Main Action Text" onTriggered: { showPassiveNotification("Action button in buttons page clicked"); } } left: Action { iconName: "go-previous" text: "Left Action Text" onTriggered: { showPassiveNotification("Left action triggered") } } contextualActions: [ Action { text:"Action 1" iconName: "go-next" onTriggered: showPassiveNotification("Action 1 clicked") }, Action { text:"Action 2" iconName: "folder" enabled: false onTriggered: showPassiveNotification("Action 2 clicked") } ] } ColumnLayout { width: page.width spacing: Units.smallSpacing Label { Layout.fillWidth: true wrapMode: Text.WordWrap text: "This page is used to test multiple layers: it will cover all the columns" } Controls.Button { text: "Push A New Layer" anchors.horizontalCenter: parent.horizontalCenter onClicked: pageStack.layers.push(Qt.resolvedUrl("LayersGallery.qml")); } Controls.Button { text: "Pop A Layer" anchors.horizontalCenter: parent.horizontalCenter onClicked: pageStack.layers.pop(); } } } diff --git a/examples/gallerydata/contents/ui/gallery/ListViewGallery.qml b/examples/gallerydata/contents/ui/gallery/ListViewGallery.qml index 32c048b9..e02932b9 100644 --- a/examples/gallerydata/contents/ui/gallery/ListViewGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/ListViewGallery.qml @@ -1,97 +1,97 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.4 import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.1 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ScrollablePage { id: page Layout.fillWidth: true title: "Long List view" actions { main: Kirigami.Action { iconName: sheet.sheetOpen ? "dialog-cancel" : "document-edit" text: "Main Action Text" checkable: true onCheckedChanged: sheet.sheetOpen = checked; } } //Close the drawer with the back button onBackRequested: { if (sheet.sheetOpen) { event.accepted = true; sheet.close(); } } supportsRefreshing: true onRefreshingChanged: { if (refreshing) { refreshRequestTimer.running = true; } else { showPassiveNotification("Example refreshing completed") } } background: Rectangle { - color: Kirigami.Theme.viewBackgroundColor + color: Kirigami.Theme.backgroundColor } Kirigami.OverlaySheet { id: sheet onSheetOpenChanged: page.actions.main.checked = sheetOpen; parent: applicationWindow().overlay ListView { model: 100 implicitWidth: Kirigami.Units.gridUnit * 30 delegate: Kirigami.BasicListItem { label: "Item in sheet" + modelData } } } ListView { Timer { id: refreshRequestTimer interval: 3000 onTriggered: page.refreshing = false } model: 200 delegate: Kirigami.SwipeListItem { id: listItem contentItem: Kirigami.Label { height: Math.max(implicitHeight, Kirigami.Units.iconSizes.smallMedium) anchors.verticalCenter: parent.verticalCenter text: "Item " + modelData color: listItem.checked || (listItem.pressed && !listItem.checked && !listItem.sectionDelegate) ? listItem.activeTextColor : listItem.textColor } actions: [ Kirigami.Action { iconName: "document-decrypt" onTriggered: showPassiveNotification(model.text + " Action 1 clicked") }, Kirigami.Action { iconName: "mail-reply-sender" onTriggered: showPassiveNotification(model.text + " Action 2 clicked") }] } } } diff --git a/examples/gallerydata/contents/ui/gallery/ListViewHeaderItemsGallery.qml b/examples/gallerydata/contents/ui/gallery/ListViewHeaderItemsGallery.qml index a75fc931..f1c0c05c 100644 --- a/examples/gallerydata/contents/ui/gallery/ListViewHeaderItemsGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/ListViewHeaderItemsGallery.qml @@ -1,103 +1,103 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.4 import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.1 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ScrollablePage { id: page Layout.fillWidth: true title: "Long List view" actions { contextualActions: [ Kirigami.Action { id: overlayHeaderAction checkable: true checked: true text:"Overlay Header" onTriggered: { mainList.headerPositioning = ListView.OverlayHeader; overlayHeaderAction.checked = pullBackHeaderAction.checked = inlineHeaderAction.checked = false; } }, Kirigami.Action { id: pullBackHeaderAction checkable: true text:"PullBack Header" onTriggered: { mainList.headerPositioning = ListView.PullBackHeader; overlayHeaderAction.checked = pullBackHeaderAction.checked = inlineHeaderAction.checked = false; } }, Kirigami.Action { id: inlineHeaderAction checkable: true text:"Inline Header" onTriggered: { mainList.headerPositioning = ListView.InlineHeader; overlayHeaderAction.checked = pullBackHeaderAction.checked = inlineHeaderAction.checked = false; } }, Kirigami.Action { checkable: true checked: true text:"Header overlaps list" onCheckedChanged: { mainList.headerItem.z = checked ? 10 : 0 } } ] } supportsRefreshing: true onRefreshingChanged: { if (refreshing) { refreshRequestTimer.running = true; } else { showPassiveNotification("Example refreshing completed") } } background: Rectangle { - color: Kirigami.Theme.viewBackgroundColor + color: Kirigami.Theme.backgroundColor } ListView { id: mainList Timer { id: refreshRequestTimer interval: 3000 onTriggered: page.refreshing = false } headerPositioning: ListView.OverlayHeader //headerPositioning: ListView.PullBackHeader header: Kirigami.ItemViewHeader { backgroundImage.source: "../banner.jpg" title: page.title } model: 200 delegate: Kirigami.BasicListItem { id: listItem label: "Item " + modelData } } } diff --git a/examples/gallerydata/contents/ui/gallery/MetricsGallery.qml b/examples/gallerydata/contents/ui/gallery/MetricsGallery.qml index 86189595..7d7ccbdf 100644 --- a/examples/gallerydata/contents/ui/gallery/MetricsGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/MetricsGallery.qml @@ -1,130 +1,130 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.0 as QQC2 import QtQuick.Window 2.2 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ScrollablePage { id: page title: "Size Units" GridLayout { id: themetest columns: 2 anchors.margins: Kirigami.Units.gridUnit / 2 Kirigami.Heading { text: "Screen" Layout.columnSpan: 2 level: 2 } QQC2.Label { text: "Geometry (pixels):" } QQC2.Label { text: page.width + "x" + page.height } QQC2.Label { text: "Geometry (gridUnits):" } QQC2.Label { text: Math.round(page.width / Kirigami.Units.gridUnit) + "x" + Math.round(page.height / Kirigami.Units.gridUnit) } QQC2.Label { text: "Units.gridUnit:" } QQC2.Label { text: Kirigami.Units.gridUnit } QQC2.Label { text: "Units.devicePixelRatio:" } QQC2.Label { text: Kirigami.Units.devicePixelRatio.toFixed(2) } QQC2.Label { text: "Screen.devicePixelRatio:" } QQC2.Label { text: Screen.devicePixelRatio } Kirigami.Heading { text: "Font Metrics" level: 2 Layout.columnSpan: 2 } QQC2.Label { text: "FontMetrics pointSize:" } QQC2.Label { text: Kirigami.Units.fontMetrics.font.pointSize } QQC2.Label { text: "FontMetrics pixelSize:" } QQC2.Label { text: Number(Kirigami.Units.fontMetrics.font.pixelSize).toFixed(2) } QQC2.Label { text: "Height of default font:" } QQC2.Label { text: Number(font.pixelSize / Screen.pixelDensity).toFixed(2) + "mm" } Kirigami.Heading { text: "Sizes" Layout.columnSpan: 2 level: 2 } QQC2.Label { text: "Pixel density:" } QQC2.Label { text: Number(Screen.pixelDensity).toFixed(2) } QQC2.Label { text: "2cm x 2cm square:" } Rectangle { width: Math.round(Screen.pixelDensity * 20) height: Math.round(Screen.pixelDensity * 20) color: "black" } QQC2.Label { Layout.columnSpan: 2 Layout.fillHeight: true } } } diff --git a/examples/gallerydata/contents/ui/gallery/MiscGallery.qml b/examples/gallerydata/contents/ui/gallery/MiscGallery.qml index d4458084..902277a3 100644 --- a/examples/gallerydata/contents/ui/gallery/MiscGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/MiscGallery.qml @@ -1,199 +1,199 @@ /* * Copyright 2016 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 ScrollablePage { id: page title: "Misc controls" actions { main: Action { iconName: "document-edit" text: "Main Action Text" } left: Action { iconName: "go-previous" text: "Left Action Text" onTriggered: { showPassiveNotification("Left action triggered") } } right: Action { iconName: "go-next" text: "Right Action Text" onTriggered: { showPassiveNotification("Right action triggered") } } contextualActions: [ Action { text:"Action for buttons" iconName: "bookmarks" onTriggered: showPassiveNotification("Action 1 clicked") }, Action { text:"Disabled Action" iconName: "folder" enabled: false }, Action { text: "Action for Sheet" visible: sheet.sheetOpen } ] } header: Controls.ToolBar { RowLayout { anchors.verticalCenter: parent.verticalCenter Controls.ToolButton { text: "ToolButton" } Controls.ToolButton { text: "Menu" onClicked: menu.open(); Controls.Menu { id: menu y: parent.height Controls.MenuItem { checkable: true text: "Item1" } Controls.MenuItem { text: "Item2" } } } } } footer: Rectangle { - color: Theme.viewBackground + color: Theme.backgroundColor height: Units.gridUnit * 3 Controls.TextField { topPadding: 0 bottomPadding: 0 leftPadding: Units.smallSpacing rightPadding: Units.smallSpacing anchors.fill: parent } Separator { anchors { top: parent.top left: parent.left right: parent.right } } } Controls.Popup { id: dialog modal: true focus: true x: (page.width - width) / 2 y: page.height / 2 - height width: Math.min(page.width - Units.gridUnit * 4, Units.gridUnit * 20) contentHeight: popupColumn.height Column { id: popupColumn spacing: 20 Controls.Label { width: dialog.availableWidth text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id risus id augue euismod accumsan. Nunc vestibulum placerat bibendum. Morbi commodo auctor varius. Donec molestie euismod ultrices. Sed facilisis augue nec eros auctor." wrapMode: Label.Wrap } Controls.Button { anchors.right: parent.right text: "Ok" onClicked: dialog.close() } } } ColumnLayout { anchors.centerIn: parent Controls.Button { Layout.alignment: Qt.AlignHCenter text: "Dialog" onClicked: dialog.open() } Controls.Dial { Layout.alignment: Qt.AlignHCenter } Controls.SpinBox { editable: true Layout.alignment: Qt.AlignHCenter } Controls.ComboBox { model: ["First", "Second", "Third"] Layout.alignment: Qt.AlignHCenter } Controls.GroupBox { title: "Title" Layout.alignment: Qt.AlignHCenter ColumnLayout { id: options Controls.RadioButton { text: "First" checked: true } Controls.RadioButton { text: "Second" checked: false } Controls.RadioButton { text: "Third" checked: false } } } Column { Layout.alignment: Qt.AlignHCenter Controls.ItemDelegate { width: 300 text: "Delegate1" } Controls.ItemDelegate { width: 300 text: "Delegate2" } Controls.CheckDelegate { width: 300 text: "Delegate3" } Controls.SwitchDelegate { width: 300 text: "Delegate4" } Controls.RadioDelegate { width: 300 text: "Delegate5" } } } } diff --git a/examples/gallerydata/contents/ui/gallery/MultipleColumnsGallery.qml b/examples/gallerydata/contents/ui/gallery/MultipleColumnsGallery.qml index 77c4f15f..cc92afdd 100644 --- a/examples/gallerydata/contents/ui/gallery/MultipleColumnsGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/MultipleColumnsGallery.qml @@ -1,106 +1,106 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 ScrollablePage { id: page Layout.fillWidth: true //implicitWidth: Units.gridUnit * (Math.floor(Math.random() * 35) + 8) title: "Multiple Columns" actions { main: Action { iconName: "document-edit" text: "Main Action Text" onTriggered: { showPassiveNotification("Action button in buttons page clicked"); } } left: Action { iconName: "go-previous" text: "Left Action Text" onTriggered: { showPassiveNotification("Left action triggered") } } right: Action { iconName: "go-next" text: "Right Action Text" onTriggered: { showPassiveNotification("Right action triggered") } } contextualActions: [ Action { text:"Action 1" iconName: "bookmarks" onTriggered: showPassiveNotification("Action 1 clicked") }, Action { text:"Action 2" iconName: "folder" enabled: false onTriggered: showPassiveNotification("Action 2 clicked") } ] } ColumnLayout { width: page.width spacing: Units.smallSpacing Label { Layout.fillWidth: true wrapMode: Text.WordWrap text: "This page is used to test multiple columns: you can push and pop an arbitrary number of pages, each new page will have a random implicit width between 8 and 35 grid units.\nIf you enlarge the window enough, you can test how the application behaves with multiple columns." } Item { Layout.minimumWidth: Units.gridUnit *2 Layout.minimumHeight: Layout.minimumWidth } Controls.Button { text: "Push Another Page" anchors.horizontalCenter: parent.horizontalCenter onClicked: pageStack.push(Qt.resolvedUrl("MultipleColumnsGallery.qml")); } Controls.Button { text: "Pop A Page" anchors.horizontalCenter: parent.horizontalCenter onClicked: pageStack.pop(); } RowLayout { anchors.horizontalCenter: parent.horizontalCenter Controls.TextField { id: edit text: page.title } Controls.Button { text: "Rename Page" onClicked: page.title = edit.text; } } } } diff --git a/examples/gallerydata/contents/ui/gallery/NonScrollableGallery.qml b/examples/gallerydata/contents/ui/gallery/NonScrollableGallery.qml index 129abf8b..3688bd70 100644 --- a/examples/gallerydata/contents/ui/gallery/NonScrollableGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/NonScrollableGallery.qml @@ -1,56 +1,56 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 Page { id: page Layout.fillWidth: true title: "Simple Page" actions { main: Action { iconName: sheet.sheetOpen ? "dialog-cancel" : "document-edit" text: "Main Action Text" checkable: true onCheckedChanged: sheet.sheetOpen = checked; } } Rectangle { anchors.fill: parent color: "red" Label { anchors.centerIn: parent text: "Rectangle with automatic margins" } } OverlaySheet { id: sheet onSheetOpenChanged: page.actions.main.checked = sheetOpen; Label { property int implicitWidth: Units.gridUnit * 30 wrapMode: Text.WordWrap text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id risus id augue euismod accumsan. Nunc vestibulum placerat bibendum. Morbi commodo auctor varius. Donec molestie euismod ultrices. Sed facilisis augue nec eros auctor, vitae mattis quam rhoncus. Nam ut erat diam. Curabitur iaculis accumsan magna, eget fermentum massa scelerisque eu. Cras elementum erat non erat euismod accumsan. Vestibulum ac mi sed dui finibus pulvinar. Vivamus dictum, leo sed lobortis porttitor, nisl magna faucibus orci, sit amet euismod arcu elit eget est. Duis et vehicula nibh. In arcu sapien, laoreet sit amet porttitor non, rhoncus vel magna. Suspendisse imperdiet consectetur est nec ornare. Pellentesque bibendum sapien at erat efficitur vehicula. Morbi sed porta nibh. Vestibulum ut urna ut dolor sagittis mattis." } } } diff --git a/examples/gallerydata/contents/ui/gallery/ProgressBarGallery.qml b/examples/gallerydata/contents/ui/gallery/ProgressBarGallery.qml index e29cab68..ef578000 100644 --- a/examples/gallerydata/contents/ui/gallery/ProgressBarGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/ProgressBarGallery.qml @@ -1,111 +1,111 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 ScrollablePage { id: page Layout.fillWidth: true title: "Progress Indicators" actions { main: Action { iconName: "document-edit" text: "Main Action Text" onTriggered: { showPassiveNotification("Main action triggered"); } } right: Action { iconName: "folder-sync" text: "Right Action Text" onTriggered: { showPassiveNotification("Right action triggered") } } } ColumnLayout { width: page.width Timer { id: timer property int value: 0 interval: 80 repeat: true running: true onTriggered: { value = (value + 1) % 100 } } GridLayout { anchors.centerIn: parent rowSpacing: Units.largeSpacing columns: 2 width: parent.width - Units.gridUnit*2 Label { text: "Determinate:" Layout.alignment: Qt.AlignRight } Controls.ProgressBar { from: 0 to: 100 value: timer.value Layout.maximumWidth: Units.gridUnit * 10 } Label { text: "Indeterminate:" Layout.alignment: Qt.AlignRight } Controls.ProgressBar { from: 0 to: 100 indeterminate: true Layout.maximumWidth: Units.gridUnit * 10 } Label { text: "Busy indicator:" Layout.alignment: Qt.AlignRight } Controls.BusyIndicator { } Label { text: "Inactive indicator:" Layout.alignment: Qt.AlignRight } Controls.BusyIndicator { running: false } Label { text: "Custom size:" Layout.alignment: Qt.AlignRight } Controls.BusyIndicator { Layout.minimumWidth: Units.iconSizes.enormous Layout.minimumHeight: width } } } } diff --git a/examples/gallerydata/contents/ui/gallery/RadioButtonGallery.qml b/examples/gallerydata/contents/ui/gallery/RadioButtonGallery.qml index 4d8addb7..64370730 100644 --- a/examples/gallerydata/contents/ui/gallery/RadioButtonGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/RadioButtonGallery.qml @@ -1,108 +1,108 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 ScrollablePage { id: page Layout.fillWidth: true title: "Radio buttons" actions { main: Action { iconName: "document-edit" text: "Main Action Text" onTriggered: { showPassiveNotification("Action button in buttons page clicked"); } } left: Action { iconName: "folder-sync" text: "Left Action Text" onTriggered: { showPassiveNotification("Left action triggered") } } } Controls.ButtonGroup { buttons: column1.children } ColumnLayout { width: page.width Item { Layout.fillWidth: true Layout.minimumHeight: Units.gridUnit * 10 RowLayout { anchors.centerIn: parent ColumnLayout { Layout.fillHeight: true Item { width: 1 height: 1 Layout.fillHeight: true } Label { text: "On" Layout.preferredHeight: radio1.height } Label { text: "Off" Layout.preferredHeight: radio1.height } } ColumnLayout { id: column1 Label { text: "Normal" } Controls.RadioButton { id: radio1 text: "On" checked: true } Controls.RadioButton { text: "Off" checked: false } } ColumnLayout { id: column2 enabled: false Label { text: "Disabled" } Controls.RadioButton { text: "On" checked: true } Controls.RadioButton { text: "Off" checked: false } } } } } } diff --git a/examples/gallerydata/contents/ui/gallery/SliderGallery.qml b/examples/gallerydata/contents/ui/gallery/SliderGallery.qml index ca4baeda..24b304b5 100644 --- a/examples/gallerydata/contents/ui/gallery/SliderGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/SliderGallery.qml @@ -1,121 +1,122 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 ScrollablePage { id: page Layout.fillWidth: true title: "Sliders" actions { left: Action { iconName: "folder-sync" text: "Left Action Text" onTriggered: { showPassiveNotification("Left action triggered") } } right: Action { iconName: "configure" text: "Right Action Text" onTriggered: { showPassiveNotification("Right action triggered") } } } ColumnLayout { width: page.width Item { Layout.fillWidth: true Layout.minimumHeight: Units.gridUnit * 20 ColumnLayout { anchors.centerIn: parent spacing: Units.smallSpacing Label { text: "Normal:" } Controls.Slider { id: slider Layout.minimumWidth: Units.gridUnit * 15 value: 2 to: 5.0 Controls.ToolTip { parent: slider.handle visible: slider.pressed text: slider.position.toFixed(1) } } Label { text: "Disabled:" } Controls.Slider { enabled: false Layout.minimumWidth: Units.gridUnit * 15 value: 2 to: 5.0 } Label { text: "Thickmarks:" } Controls.Slider { id: slider2 Layout.minimumWidth: Units.gridUnit * 15 to: 5.0 stepSize: 1.0 value: 3 Controls.ToolTip { parent: slider2.handle visible: slider2.pressed text: slider2.position.toFixed(1) } } + Controls.RangeSlider {} Label { text: "Vertical:" } RowLayout { Layout.alignment: Qt.AlignHCenter Controls.Slider { Layout.minimumWidth: 2 Layout.minimumHeight: Units.gridUnit * 10 value: 2 to: 5.0 orientation: Qt.Vertical } Controls.Slider { Layout.minimumWidth: 2 Layout.minimumHeight: Units.gridUnit * 10 value: 3 to: 5.0 stepSize: 1.0 orientation: Qt.Vertical } } } } } } diff --git a/examples/gallerydata/contents/ui/gallery/SwitchGallery.qml b/examples/gallerydata/contents/ui/gallery/SwitchGallery.qml index 9659b534..43dd3083 100644 --- a/examples/gallerydata/contents/ui/gallery/SwitchGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/SwitchGallery.qml @@ -1,80 +1,80 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 ScrollablePage { id: page Layout.fillWidth: true title: "Switches" ColumnLayout { width: page.width Item { Layout.fillWidth: true Layout.minimumHeight: Units.gridUnit * 10 GridLayout { anchors.centerIn: parent columns: 3 rows: 3 rowSpacing: Units.smallSpacing Item { width: 1 height: 1 } Label { text: "Normal" } Label { text: "Disabled" enabled: false } Label { text: "On" } Controls.Switch { checked: true text: "On" } Controls.Switch { checked: true enabled: false text: "On" } Label { text: "Off" } Controls.Switch { checked: false text: "Off" } Controls.Switch { checked: false enabled: false text: "Off" } } } } } diff --git a/examples/gallerydata/contents/ui/gallery/TabBarGallery.qml b/examples/gallerydata/contents/ui/gallery/TabBarGallery.qml index 723c80ba..2420f5a0 100644 --- a/examples/gallerydata/contents/ui/gallery/TabBarGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/TabBarGallery.qml @@ -1,77 +1,77 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 Page { id: page title: "Tab Bar" header: Controls.TabBar { id: tabBar currentIndex: swipeView.currentIndex Controls.TabButton { text: "First" } Controls.TabButton { text: "Second" } Controls.TabButton { text: "Third" } } Controls.SwipeView { id: swipeView anchors.fill: parent currentIndex: tabBar.currentIndex clip: true Repeater { model: 3 Item { Label { width: parent.width wrapMode: Label.Wrap horizontalAlignment: Qt.AlignHCenter text: "Page " + modelData } Controls.TabBar { position: Controls.TabBar.Footer anchors { bottom: parent.bottom horizontalCenter: parent.horizontalCenter } Controls.TabButton { text: "First" } Controls.TabButton { text: "Second" } } } } } } diff --git a/examples/gallerydata/contents/ui/gallery/TextFieldGallery.qml b/examples/gallerydata/contents/ui/gallery/TextFieldGallery.qml index 0c2305e7..0a1e45d2 100644 --- a/examples/gallerydata/contents/ui/gallery/TextFieldGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/TextFieldGallery.qml @@ -1,82 +1,82 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 ScrollablePage { id: page Layout.fillWidth: true implicitWidth: applicationWindow().width title: "Text fields" ColumnLayout { objectName: "pollo" width: page.width spacing: Units.smallSpacing Label { text: "Placeholder text:" } Controls.TextField { placeholderText: "Search..." Layout.alignment: Qt.AlignHCenter } Label { text: "Disabled field:" } Controls.TextField { text: "Disabled" enabled: false Layout.alignment: Qt.AlignHCenter } Label { text: "Password:" } Controls.TextField { echoMode: TextInput.Password Layout.alignment: Qt.AlignHCenter } Label { text: "Text area:" } //this to make text selection work on Android //QQC2 should do this by itself MouseArea { Layout.fillWidth: true drag.filterChildren: Settings.isMobile implicitHeight: field.implicitHeight onPressAndHold: { field.forceActiveFocus(); field.cursorPosition = field.positionAt(mouse.x, mouse.y); field.selectWord(); } Controls.TextArea { id: field anchors.fill: parent text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent eu nisl ac nibh malesuada pretium ut sit amet libero. Nulla libero arcu, pharetra a dignissim nec, iaculis sit amet metus. Suspendisse quis justo efficitur, pharetra dui maximus, aliquam dolor. Vestibulum vel imperdiet turpis. Mauris ut leo mauris. Praesent ut libero sollicitudin, tincidunt nisi a, efficitur erat. Curabitur lacinia leo et tempor aliquam." Layout.minimumWidth: Units.gridUnit * 12 Layout.minimumHeight: Units.gridUnit * 12 wrapMode: Controls.TextArea.WordWrap } } } } diff --git a/examples/minimalqmake/Page1Form.ui.qml b/examples/minimalqmake/Page1Form.ui.qml index a48dbe09..5bd00845 100644 --- a/examples/minimalqmake/Page1Form.ui.qml +++ b/examples/minimalqmake/Page1Form.ui.qml @@ -1,45 +1,45 @@ /* * Copyright 2017 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.3 -import org.kde.kirigami 2.1 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.Page { title: qsTr("Page 1") property alias textField1: textField1 property alias button1: button1 RowLayout { anchors.horizontalCenter: parent.horizontalCenter anchors.topMargin: 20 anchors.top: parent.top TextField { id: textField1 placeholderText: qsTr("Text Field") } Button { id: button1 text: qsTr("Press Me") } } } diff --git a/examples/minimalqmake/kirigami-icons.qrc b/examples/minimalqmake/kirigami-icons.qrc index 3a4ec9f0..0d511624 100644 --- a/examples/minimalqmake/kirigami-icons.qrc +++ b/examples/minimalqmake/kirigami-icons.qrc @@ -1,14 +1,15 @@ 3rdparty/breeze-icons/icons/actions/32/application-menu.svg 3rdparty/breeze-icons/icons/actions/32/document-decrypt.svg 3rdparty/breeze-icons/icons/actions/32/folder-sync.svg 3rdparty/breeze-icons/icons/actions/22/go-next.svg 3rdparty/breeze-icons/icons/actions/22/go-previous.svg 3rdparty/breeze-icons/icons/actions/22/go-up.svg 3rdparty/breeze-icons/icons/actions/22/handle-left.svg 3rdparty/breeze-icons/icons/actions/22/handle-right.svg 3rdparty/breeze-icons/icons/actions/32/view-list-icons.svg 3rdparty/breeze-icons/icons/categories/32/applications-graphics.svg + 3rdparty/breeze-icons/icons/actions/symbolic/media-record-symbolic.svg diff --git a/examples/minimalqmake/main.qml b/examples/minimalqmake/main.qml index 8e891e33..378d4d3f 100644 --- a/examples/minimalqmake/main.qml +++ b/examples/minimalqmake/main.qml @@ -1,58 +1,58 @@ /* * Copyright 2017 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.3 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ApplicationWindow { visible: true title: qsTr("Hello World") header: Kirigami.ApplicationHeader {} pageStack.initialPage: Page1 {} globalDrawer: Kirigami.GlobalDrawer { title: "Hello App" titleIcon: "applications-graphics" actions: [ Kirigami.Action { text: "View" iconName: "view-list-icons" Kirigami.Action { text: "action 1" } Kirigami.Action { text: "action 2" } Kirigami.Action { text: "action 3" } }, Kirigami.Action { text: "action 3" }, Kirigami.Action { text: "action 4" } ] } } diff --git a/examples/multiplatformnotesapp/NotesGeneral.qml b/examples/multiplatformnotesapp/NotesGeneral.qml index b4da2c4f..f4d40643 100644 --- a/examples/multiplatformnotesapp/NotesGeneral.qml +++ b/examples/multiplatformnotesapp/NotesGeneral.qml @@ -1,216 +1,216 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.2 import QtQuick.Controls 2.0 as QQC2 import org.kde.kirigami 2.0 as Kirigami Kirigami.ApplicationWindow { id: root property string currentFile header: Kirigami.ToolBarApplicationHeader { } pageStack.initialPage: iconView Kirigami.ScrollablePage { id: iconView title: "Notes" actions { contextualActions: [ Kirigami.Action { id: sortAction iconName: "view-sort-ascending-symbolic" tooltip: "Sort Ascending" } ] } background: Rectangle { - color: Kirigami.Thmeme.viewBackgroundColor + color: Kirigami.Thmeme.backgroundColor } GridView { id: view model: 100 cellWidth: Kirigami.Units.gridUnit * 9 cellHeight: cellWidth currentIndex: -1 highlightMoveDuration: 0 highlight: Rectangle { color: Kirigami.Theme.highlightColor } delegate: MouseArea { width: view.cellWidth height: view.cellHeight Kirigami.Icon { source: "text-plain" anchors { fill: parent margins: Kirigami.Units.gridUnit } QQC2.Label { anchors { top: parent.bottom horizontalCenter: parent.horizontalCenter } text: "File " + modelData } } onClicked: { view.currentIndex = index; root.currentFile = "File " + modelData; if (root.pageStack.depth < 2) { root.pageStack.push(editorComponent); } root.pageStack.currentIndex = 1 } } } } Component { id: editorComponent Kirigami.ScrollablePage { id: editor title: root.currentFile actions { main: Kirigami.Action { id: shareAction iconName: "document-share" text: "Share..." tooltip: "Share this document with your device" checkable: true onCheckedChanged: sheet.sheetOpen = checked; } contextualActions: [ Kirigami.Action { iconName: "format-text-bold-symbolic" tooltip: "Bold" }, Kirigami.Action { iconName: "format-text-underline-symbolic" tooltip: "Underline" }, Kirigami.Action { iconName: "format-text-italic-symbolic" tooltip: "Italic" } ] } background: Rectangle { - color: Kirigami.Theme.viewBackgroundColor + color: Kirigami.Theme.backgroundColor Rectangle { anchors.fill: parent color: "yellow" opacity: 0.2 } } Kirigami.OverlaySheet { id: sheet onSheetOpenChanged: shareAction.checked = sheetOpen ListView { implicitWidth: Kirigami.Units.gridUnit * 30 model: ListModel { ListElement { title: "Share with phone \"Nokia 3310\"" description: "You selected this phone 12 times before. It's currently connected via bluetooth" buttonText: "Push Sync" } ListElement { title: "Share with phone \"My other Nexus5\"" description: "You selected this phone 0 times before. It's currently connected to your laptop via Wifi" buttonText: "push sync" } ListElement { title: "Share with NextCloud" description: "You currently do not have a server set up for sharing and storing notes from Katie. If you want to set one up click here" buttonText: "Setup..." } ListElement { title: "Send document via email" description: "This will send the document as an attached file to your own email for later sync" buttonText: "Send As Email" } } header: Kirigami.AbstractListItem { height: Kirigami.Units.gridUnit * 6 hoverEnabled: false RowLayout { Kirigami.Icon { source: "documentinfo" width: Kirigami.Units.iconSizes.large height: width } QQC2.Label { Layout.fillWidth: true Layout.minimumWidth: 0 wrapMode: Text.WordWrap text: "This document has already automatically synced with your phone \"Dancepartymeister 12\". If you want to sync with another device or do further actions you can do that here" } } } delegate: Kirigami.AbstractListItem { height: Kirigami.Units.gridUnit * 6 hoverEnabled: false //TODO: bug in overlaysheet rightPadding: Kirigami.Units.gridUnit * 1.5 RowLayout { ColumnLayout { Layout.fillWidth: true Layout.minimumWidth: 0 QQC2.Label { wrapMode: Text.WordWrap text: model.title } QQC2.Label { Layout.fillWidth: true Layout.minimumWidth: 0 wrapMode: Text.WordWrap text: model.description } } QQC2.Button { text: model.buttonText onClicked: sheet.close() } } } } } QQC2.TextArea { background: Item {} wrapMode: TextEdit.WordWrap selectByMouse: true text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sollicitudin, lorem at semper pretium, tortor nisl pellentesque risus, eget eleifend odio ipsum ac mi. Donec justo ex, elementum vitae gravida vel, pretium ac lacus. Duis non metus ac enim viverra auctor in non nunc. Sed sit amet luctus nisi. Proin justo nulla, vehicula eget porta sit amet, aliquet vitae dolor. Mauris sed odio auctor, tempus ipsum ac, placerat enim. Ut in dolor vel ante dictum auctor. Praesent blandit rhoncus augue. Phasellus consequat luctus pulvinar. Pellentesque rutrum laoreet dolor, sit amet pellentesque tellus mattis sed. Sed accumsan cursus tortor. Morbi et risus dolor. Nullam facilisis ipsum justo, nec sollicitudin mi pulvinar ac. Nulla facilisi. Donec maximus turpis eget mollis laoreet. Phasellus vel mauris et est mattis auctor eget sit amet turpis. Aliquam dignissim euismod purus, eu efficitur neque fermentum eu. Suspendisse potenti. Praesent mattis ex vitae neque rutrum tincidunt. Etiam placerat leo viverra pulvinar tincidunt. Proin vel rutrum massa. Proin volutpat aliquet dapibus. Maecenas aliquet elit eu venenatis venenatis. Ut elementum, lacus vel auctor auctor, velit massa elementum ligula, quis elementum ex nisi aliquam mauris. Nulla facilisi. Pellentesque aliquet egestas venenatis. Donec iaculis ultrices laoreet. Vestibulum cursus rhoncus sollicitudin. Proin quam libero, bibendum eget sodales id, gravida quis enim. Duis fermentum libero vitae sapien hendrerit, in tincidunt tortor semper. Nullam quam nisi, feugiat sed rutrum vitae, dignissim quis risus. Ut ultricies pellentesque est, ut gravida massa convallis sed. Ut placerat dui non felis interdum, id malesuada nulla ornare. Phasellus volutpat purus placerat velit porta tristique. Donec molestie leo in turpis bibendum pharetra. Fusce fermentum diam vitae neque laoreet, sed aliquam leo sollicitudin. Ut facilisis massa arcu, eu suscipit ante varius sed. Morbi augue leo, mattis eu tempor vitae, condimentum sed urna. Curabitur ac blandit orci. Vestibulum quis consequat nunc. Proin imperdiet commodo imperdiet. Aenean mattis augue et imperdiet ultricies. Ut id feugiat nulla, et sollicitudin dui. Etiam scelerisque ligula ac euismod hendrerit. Integer in quam nibh. Pellentesque risus massa, porttitor quis fermentum eu, dictum varius magna. Morbi euismod bibendum lacus efficitur pretium. Phasellus elementum porttitor enim nec dictum. Morbi et augue laoreet, convallis quam quis, egestas quam." } } } } diff --git a/examples/simpleexamples/AbstractApplicationWindow.qml b/examples/simpleexamples/AbstractApplicationWindow.qml index 546cecb7..add8594d 100644 --- a/examples/simpleexamples/AbstractApplicationWindow.qml +++ b/examples/simpleexamples/AbstractApplicationWindow.qml @@ -1,165 +1,165 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.AbstractApplicationWindow { id: root width: 500 height: 800 visible: true globalDrawer: Kirigami.GlobalDrawer { title: "Widget gallery" titleIcon: "applications-graphics" actions: [ Kirigami.Action { text: "View" iconName: "view-list-icons" Kirigami.Action { text: "action 1" } Kirigami.Action { text: "action 2" } Kirigami.Action { text: "action 3" } }, Kirigami.Action { text: "Sync" iconName: "folder-sync" Kirigami.Action { text: "action 4" } Kirigami.Action { text: "action 5" } }, Kirigami.Action { text: "Checkable" iconName: "view-list-details" checkable: true checked: false onTriggered: { print("Action checked:" + checked) } }, Kirigami.Action { text: "Settings" iconName: "configure" checkable: true //Need to do this, otherwise it breaks the bindings property bool current: pageStack.currentItem ? pageStack.currentItem.objectName == "settingsPage" : false onCurrentChanged: { checked = current; } onTriggered: { pageStack.push(settingsComponent); } } ] Controls.CheckBox { checked: true text: "Option 1" } Controls.CheckBox { text: "Option 2" } Controls.CheckBox { text: "Option 3" } Controls.Slider { Layout.fillWidth: true value: 0.5 } } contextDrawer: Kirigami.ContextDrawer { id: contextDrawer } header: Kirigami.ApplicationHeader {} pageStack: Controls.StackView { anchors.fill: parent property int currentIndex: 0 focus: true onCurrentIndexChanged: { if (depth > currentIndex+1) { pop(get(currentIndex)); } } onDepthChanged: { currentIndex = depth-1; } initialItem: mainPageComponent Keys.onReleased: { if (event.key == Qt.Key_Back || (event.key === Qt.Key_Left && (event.modifiers & Qt.AltModifier))) { event.accepted = true; if (root.contextDrawer && root.contextDrawer.drawerOpen) { root.contextDrawer.close(); } else if (root.globalDrawer && root.globalDrawer.drawerOpen) { root.globalDrawer.close(); } else { var backEvent = {accepted: false} if (root.pageStack.currentIndex >= 1) { root.pageStack.currentItem.backRequested(backEvent); if (!backEvent.accepted) { if (root.pageStack.depth > 1) { root.pageStack.currentIndex = Math.max(0, root.pageStack.currentIndex - 1); backEvent.accepted = true; } else { Qt.quit(); } } } if (!backEvent.accepted) { Qt.quit(); } } } } } Component { id: settingsComponent Kirigami.Page { title: "Settings" objectName: "settingsPage" Rectangle { anchors.fill: parent } } } //Main app content Component { id: mainPageComponent MultipleColumnsGallery {} } } diff --git a/examples/simpleexamples/FixedSidebar.qml b/examples/simpleexamples/FixedSidebar.qml index 4fd34bbc..e7e1d61e 100644 --- a/examples/simpleexamples/FixedSidebar.qml +++ b/examples/simpleexamples/FixedSidebar.qml @@ -1,52 +1,52 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ApplicationWindow { id: root width: Kirigami.Units.gridUnit * 60 height: Kirigami.Units.gridUnit * 40 pageStack.initialPage: mainPageComponent globalDrawer: Kirigami.OverlayDrawer { drawerOpen: true modal: false contentItem: Item { implicitWidth: Kirigami.Units.gridUnit * 10 Kirigami.Label { text: "This is a sidebar" width: parent.width - Kirigami.Units.smallSpacing * 2 wrapMode: Text.WordWrap anchors.horizontalCenter: parent.horizontalCenter } } } //Main app content Component { id: mainPageComponent MultipleColumnsGallery {} } } diff --git a/examples/simpleexamples/MultipleColumnsGallery.qml b/examples/simpleexamples/MultipleColumnsGallery.qml index 78e4b3e7..483fb18d 100644 --- a/examples/simpleexamples/MultipleColumnsGallery.qml +++ b/examples/simpleexamples/MultipleColumnsGallery.qml @@ -1,88 +1,88 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 ScrollablePage { id: page Layout.fillWidth: true implicitWidth: Units.gridUnit * (Math.floor(Math.random() * 35) + 8) title: "Multiple Columns" actions { contextualActions: [ Action { text:"Action for buttons" iconName: "bookmarks" onTriggered: print("Action 1 clicked") }, Action { text:"Action 2" iconName: "folder" enabled: false } ] } ColumnLayout { width: page.width spacing: Units.smallSpacing Label { Layout.fillWidth: true wrapMode: Text.WordWrap text: "This page is used to test multiple columns: you can push and pop an arbitrary number of pages, each new page will have a random implicit width between 8 and 35 grid units.\nIf you enlarge the window enough, you can test how the application behaves with multiple columns." } Item { Layout.minimumWidth: Units.gridUnit *2 Layout.minimumHeight: Layout.minimumWidth } Label { anchors.horizontalCenter: parent.horizontalCenter text: "Page implicitWidth: " + page.implicitWidth } Controls.Button { text: "Push Another Page" anchors.horizontalCenter: parent.horizontalCenter onClicked: pageStack.push(Qt.resolvedUrl("MultipleColumnsGallery.qml")); } Controls.Button { text: "Pop A Page" anchors.horizontalCenter: parent.horizontalCenter onClicked: pageStack.pop(); } RowLayout { anchors.horizontalCenter: parent.horizontalCenter Controls.TextField { id: edit text: page.title } Controls.Button { text: "Rename Page" onClicked: page.title = edit.text; } } } } diff --git a/examples/simpleexamples/SplitDrawer.qml b/examples/simpleexamples/SplitDrawer.qml index 094ce99b..c932d892 100644 --- a/examples/simpleexamples/SplitDrawer.qml +++ b/examples/simpleexamples/SplitDrawer.qml @@ -1,60 +1,60 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ApplicationWindow { id: root width: Kirigami.Units.gridUnit * 60 height: Kirigami.Units.gridUnit * 40 pageStack.initialPage: mainPageComponent globalDrawer: Kirigami.SplitDrawer { id: drawer drawerOpen: true //modal: false contentItem: Column { //implicitWidth: Kirigami.Units.gridUnit * 10 Kirigami.Label { anchors.horizontalCenter: parent.horizontalCenter text: "This is a sidebar" width: parent.width - Kirigami.Units.smallSpacing * 2 wrapMode: Text.WordWrap } Controls.Button { anchors.horizontalCenter: parent.horizontalCenter text: "Modal Drawer" checkable: true checked: true onCheckedChanged: drawer.modal = checked } } } //Main app content Component { id: mainPageComponent MultipleColumnsGallery {} } } diff --git a/examples/simpleexamples/TabBarHeader.qml b/examples/simpleexamples/TabBarHeader.qml index 9d453bfa..30d9c85a 100644 --- a/examples/simpleexamples/TabBarHeader.qml +++ b/examples/simpleexamples/TabBarHeader.qml @@ -1,52 +1,52 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ApplicationWindow { id: root width: 500 height: 800 visible: true header: Kirigami.ApplicationHeader { headerStyle: Kirigami.ApplicationHeaderStyle.TabBar } pageStack.initialPage: mainPageComponent Component.onCompleted: { pageStack.push(mainPageComponent); pageStack.push(mainPageComponent); pageStack.currentIndex = 0; } //Main app content Component { id: mainPageComponent MultipleColumnsGallery {} } } diff --git a/examples/simpleexamples/customdrawer.qml b/examples/simpleexamples/customdrawer.qml index 9b52d6bc..b3ad8d86 100644 --- a/examples/simpleexamples/customdrawer.qml +++ b/examples/simpleexamples/customdrawer.qml @@ -1,50 +1,50 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ApplicationWindow { id: root globalDrawer: Kirigami.OverlayDrawer { contentItem: Rectangle { implicitWidth: Kirigami.Units.gridUnit * 10 color: "red" anchors.fill: parent } } contextDrawer: Kirigami.ContextDrawer { id: contextDrawer } pageStack.initialPage: mainPageComponent Component { id: mainPageComponent Kirigami.ScrollablePage { title: "Hello" Rectangle { anchors.fill: parent } } } } diff --git a/examples/simpleexamples/minimal.qml b/examples/simpleexamples/minimal.qml index c0c3feff..e84e91a4 100644 --- a/examples/simpleexamples/minimal.qml +++ b/examples/simpleexamples/minimal.qml @@ -1,69 +1,69 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ApplicationWindow { id: root globalDrawer: Kirigami.GlobalDrawer { title: "Hello App" titleIcon: "applications-graphics" actions: [ Kirigami.Action { text: "View" iconName: "view-list-icons" Kirigami.Action { text: "action 1" } Kirigami.Action { text: "action 2" } Kirigami.Action { text: "action 3" } }, Kirigami.Action { text: "action 3" }, Kirigami.Action { text: "action 4" } ] } contextDrawer: Kirigami.ContextDrawer { id: contextDrawer } pageStack.initialPage: mainPageComponent Component { id: mainPageComponent Kirigami.ScrollablePage { title: "Hello" Rectangle { anchors.fill: parent } } } } diff --git a/examples/simpleexamples/pushpopclear.qml b/examples/simpleexamples/pushpopclear.qml index 835e7537..d1adbe13 100644 --- a/examples/simpleexamples/pushpopclear.qml +++ b/examples/simpleexamples/pushpopclear.qml @@ -1,82 +1,82 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ApplicationWindow { id: root header: Kirigami.ApplicationHeader { } globalDrawer: Kirigami.GlobalDrawer { title: "Hello App" titleIcon: "applications-graphics" actions: [ Kirigami.Action { text: "push" onTriggered: pageStack.push(secondPageComponent) }, Kirigami.Action { text: "pop" onTriggered: pageStack.pop() }, Kirigami.Action { text: "clear" onTriggered: pageStack.clear() }, Kirigami.Action { text: "replace" onTriggered: pageStack.replace(secondPageComponent) } ] } pageStack.initialPage: mainPageComponent Component { id: mainPageComponent Kirigami.Page { title: "First Page" Rectangle { anchors.fill: parent Kirigami.Label { text: "First Page" } } } } Component { id: secondPageComponent Kirigami.Page { title: "Second Page" Rectangle { color: "red" anchors.fill: parent Kirigami.Label { text: "Second Page" } } } } } diff --git a/examples/simpleexamples/simpleChatApp.qml b/examples/simpleexamples/simpleChatApp.qml index 799977a7..f51ccbba 100644 --- a/examples/simpleexamples/simpleChatApp.qml +++ b/examples/simpleexamples/simpleChatApp.qml @@ -1,371 +1,371 @@ /* * Copyright 2017 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.6 import QtQuick.Layouts 1.2 import QtQuick.Controls 2.2 as QQC2 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ApplicationWindow { id: root header: Kirigami.ApplicationHeader {} //FIXME: perhaps the default logic for going widescreen should be refined upstream wideScreen: width > columnWidth * 3 property int columnWidth: Kirigami.Units.gridUnit * 13 property int footerHeight: Math.round(Kirigami.Units.gridUnit * 2.5) globalDrawer: Kirigami.GlobalDrawer { contentItem.implicitWidth: columnWidth title: "Chat App" titleIcon: "konversation" modal: true drawerOpen: false actions: [ Kirigami.Action { text: "Rooms" iconName: "view-list-icons" }, Kirigami.Action { text: "Contacts" iconName: "tag-people" }, Kirigami.Action { text: "Search" iconName: "search" } ] } contextDrawer: Kirigami.GlobalDrawer { id: contextDrawer contentItem.implicitWidth: columnWidth //they can depend on the page like that or be defined directly here actions: pageStack.get(1).contextualActions edge: Qt.RightEdge modal: !root.wideScreen onModalChanged: drawerOpen = !modal handleVisible: applicationWindow == undefined ? false : applicationWindow().controlsVisible //here padding 0 as listitems look better without as opposed to any other control topPadding: 0 bottomPadding: 0 leftPadding: 0 rightPadding: 0 topContent: QQC2.Control { anchors { left: parent.left right: parent.right } background: Rectangle { anchors.fill: parent color: Kirigami.Theme.highlightColor opacity: 0.8 } padding: Kirigami.Units.gridUnit contentItem: ColumnLayout { id: titleLayout spacing: Kirigami.Units.gridUnit RowLayout { spacing: Kirigami.Units.gridUnit Rectangle { color: Kirigami.Theme.highlightedTextColor radius: width implicitWidth: Kirigami.Units.iconSizes.medium implicitHeight: implicitWidth } ColumnLayout { QQC2.Label { Layout.fillWidth: true color: Kirigami.Theme.highlightedTextColor text: "KDE" } QQC2.Label { Layout.fillWidth: true color: Kirigami.Theme.highlightedTextColor font.pointSize: Kirigami.Units.fontMetrics.font.pointSize * 0.8 text: "#kde: kde.org" } } } QQC2.Label { Layout.fillWidth: true color: Kirigami.Theme.highlightedTextColor text: "Main room for KDE community, other rooms are listed at kde.org/rooms" wrapMode: Text.WordWrap } } } ColumnLayout { spacing: 0 Kirigami.Separator { Layout.fillWidth: true Layout.maximumHeight: 1//implicitHeight } QQC2.ScrollView { Layout.fillWidth: true Layout.fillHeight: true ListView { model: 50 delegate: Kirigami.BasicListItem { label: "Person " + modelData separatorVisible: false reserveSpaceForIcon: false } } } Kirigami.Separator { Layout.fillWidth: true Layout.maximumHeight: 1//implicitHeight } Kirigami.BasicListItem { label: "Group call" icon: "call-start" separatorVisible: false } Kirigami.BasicListItem { label: "Send Attachment" icon: "mail-attachment" separatorVisible: false } } } pageStack.defaultColumnWidth: columnWidth pageStack.initialPage: [channelsComponent, chatComponent] //Experiment: custom animation for layers pageStack.layers.popEnter: Transition { PauseAnimation { duration: Kirigami.Units.longDuration } } pageStack.layers.popExit: Transition { YAnimator { from: 0 to: pageStack.layers.height duration: Kirigami.Units.longDuration easing.type: Easing.OutCubic } } pageStack.layers.pushEnter: Transition { YAnimator { from: pageStack.layers.height to: 0 duration: Kirigami.Units.longDuration easing.type: Easing.OutCubic } } pageStack.layers.pushExit: Transition { PauseAnimation { duration: Kirigami.Units.longDuration } } pageStack.layers.replaceEnter: Transition { YAnimator { from: pageStack.layers.width to: 0 duration: Kirigami.Units.longDuration easing.type: Easing.OutCubic } } pageStack.layers.replaceExit: Transition { PauseAnimation { duration: Kirigami.Units.longDuration } } Component { id: channelsComponent Kirigami.ScrollablePage { title: "Channels" background: Rectangle { anchors.fill: parent - color: Kirigami.Theme.viewBackgroundColor + color: Kirigami.Theme.backgroundColor } footer: QQC2.ToolBar { height: root.footerHeight padding: Kirigami.Units.smallSpacing RowLayout { anchors.fill: parent spacing: Kirigami.Units.smallSpacing //NOTE: icon support in tool button in Qt 5.11 QQC2.ToolButton { Layout.fillHeight: true //make it square implicitWidth: height Kirigami.Icon { anchors.centerIn: parent width: Kirigami.Units.iconSizes.smallMedium height: width source: "configure" } onClicked: root.pageStack.layers.push(secondLayerComponent); } QQC2.ComboBox { Layout.fillWidth: true Layout.fillHeight: true model: ["First", "Second", "Third"] } } } ListView { id: channelsList currentIndex: 2 model: 30 delegate: Kirigami.BasicListItem { label: "#Channel " + modelData checkable: true checked: channelsList.currentIndex == index separatorVisible: false reserveSpaceForIcon: false } } } } Component { id: chatComponent Kirigami.ScrollablePage { title: "#KDE" actions.contextualActions: [ Kirigami.Action { text: "Room Settings" iconName: "configure" Kirigami.Action { text: "Setting 1" } Kirigami.Action { text: "Setting 2" } }, Kirigami.Action { text: "Shared Media" iconName: "document-share" Kirigami.Action { text: "Media 1" } Kirigami.Action { text: "Media 2" } Kirigami.Action { text: "Media 3" } } ] background: Rectangle { anchors.fill: parent - color: Kirigami.Theme.viewBackgroundColor + color: Kirigami.Theme.backgroundColor } footer: QQC2.Control { height: footerHeight padding: Kirigami.Units.smallSpacing background: Rectangle { - color: Kirigami.Theme.viewBackgroundColor + color: Kirigami.Theme.backgroundColor Kirigami.Separator { Rectangle { anchors.fill: parent color: Kirigami.Theme.viewFocusColor visible: chatTextInput.activeFocus } anchors { left: parent.left right: parent.right top: parent.top } } } contentItem: RowLayout { QQC2.TextField { Layout.fillWidth: true id: chatTextInput background: Item {} } //NOTE: icon support in tool button in Qt 5.11 QQC2.ToolButton { Layout.fillHeight: true //make it square implicitWidth: height Kirigami.Icon { anchors.centerIn: parent width: Kirigami.Units.iconSizes.smallMedium height: width source: "go-next" } } } } ListView { id: channelsList verticalLayoutDirection: ListView.BottomToTop currentIndex: 2 model: 30 delegate: Item { height: Kirigami.Units.gridUnit * 4 ColumnLayout { x: Kirigami.Units.gridUnit anchors.verticalCenter: parent.verticalCenter Kirigami.Label { text: modelData % 2 ? "John Doe" : "John Applebaum" } Kirigami.Label { text: "Message " + modelData } } } } } } Component { id: secondLayerComponent Kirigami.Page { title: "Settings" background: Rectangle { color: Kirigami.Theme.backgroundColor } footer: QQC2.ToolBar { height: root.footerHeight QQC2.ToolButton { Layout.fillHeight: true //make it square implicitWidth: height Kirigami.Icon { anchors.centerIn: parent width: Kirigami.Units.iconSizes.smallMedium height: width source: "configure" } onClicked: root.pageStack.layers.pop(); } } } } } diff --git a/kirigami.pri b/kirigami.pri index 0028bd52..814f4910 100644 --- a/kirigami.pri +++ b/kirigami.pri @@ -1,28 +1,34 @@ -QT += qml quick gui svg +QT += qml quick gui svg quickcontrols2 HEADERS += $$PWD/src/kirigamiplugin.h \ $$PWD/src/enums.h \ - $$PWD/src/settings.h + $$PWD/src/settings.h \ + $$PWD/src/libkirigami/basictheme_p.h \ + $$PWD/src/libkirigami/platformtheme.h \ + $$PWD/src/libkirigami/platformthemefactory.h SOURCES += $$PWD/src/kirigamiplugin.cpp \ $$PWD/src/enums.cpp \ - $$PWD/src/settings.cpp + $$PWD/src/settings.cpp \ + $$PWD/src/libkirigami/basictheme.cpp \ + $$PWD/src/libkirigami/platformtheme.cpp \ + $$PWD/src/libkirigami/platformthemefactory.cpp INCLUDEPATH += $$PWD/src DEFINES += KIRIGAMI_BUILD_TYPE_STATIC !ios:!android { message( "compiling for desktop" ) HEADERS += $$PWD/src/desktopicon.h SOURCES += $$PWD/src/desktopicon.cpp } API_VER=1.0 RESOURCES += $$PWD/kirigami.qrc exists($$_PRO_FILE_PWD_/kirigami-icons.qrc) { message("Using icons QRC file shipped by the project") RESOURCES += $$_PRO_FILE_PWD_/kirigami-icons.qrc } else { message("Using icons QRCfile shipped in kirigami") RESOURCES += $$PWD/kirigami-icons.qrc } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 170bdb85..ceeafd11 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,64 +1,74 @@ project(kirigami) if (NOT STATIC_LIBRARY) ecm_create_qm_loader(kirigami_QM_LOADER libkirigami2plugin_qt) +else() + set(KIRIGAMI_STATIC_FILES + libkirigami/basictheme.cpp + libkirigami/platformtheme.cpp + libkirigami/kirigamipluginfactory.cpp) endif() +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libkirigami ${CMAKE_CURRENT_BINARY_DIR}/libkirigami) + set(kirigami_SRCS kirigamiplugin.cpp enums.cpp desktopicon.cpp settings.cpp ${kirigami_QM_LOADER} + ${KIRIGAMI_STATIC_FILES} ) IF(STATIC_LIBRARY) qt5_add_resources(RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../kirigami.qrc) add_library(kirigamiplugin STATIC ${kirigami_SRCS} ${RESOURCES}) target_link_libraries(kirigamiplugin Qt5::Core Qt5::Qml Qt5::Quick) ELSE(STATIC_LIBRARY) +add_subdirectory(libkirigami) add_library(kirigamiplugin SHARED ${kirigami_SRCS}) + set_target_properties(kirigamiplugin PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/org/kde/kirigami.2) -target_link_libraries(kirigamiplugin Qt5::Core Qt5::Qml Qt5::Quick) +target_link_libraries(kirigamiplugin KF5::Kirigami2 Qt5::Core Qt5::Qml Qt5::Quick) add_custom_target(copy) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin/org/kde/kirigami.2) add_custom_command(TARGET copy PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/controls ${CMAKE_BINARY_DIR}/bin/org/kde/kirigami.2/) add_custom_command(TARGET copy PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/styles ${CMAKE_BINARY_DIR}/bin/org/kde/kirigami.2/styles) add_dependencies(kirigamiplugin copy) install(TARGETS kirigamiplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigami.2) install(DIRECTORY controls/ DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigami.2) if (PLASMA_ENABLED) install(DIRECTORY styles/Plasma DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigami.2/styles) endif() if (DESKTOP_ENABLED) install(DIRECTORY styles/org.kde.desktop DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigami.2/styles) endif() if (PLASMA_ENABLED AND DESKTOP_ENABLED) install(DIRECTORY styles/org.kde.desktop.plasma DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigami.2/styles) endif() install(DIRECTORY styles/Material DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigami.2/styles) install(FILES ${platformspecific} DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigami.2) include(ECMGeneratePriFile) ecm_generate_pri_file(BASE_NAME Kirigami2 LIB_NAME KF5Kirigami2 DEPS "core qml quick svg" FILENAME_VAR PRI_FILENAME ) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) ENDIF(STATIC_LIBRARY) diff --git a/src/controls/AbstractApplicationHeader.qml b/src/controls/AbstractApplicationHeader.qml index 7496d705..382bf1c8 100644 --- a/src/controls/AbstractApplicationHeader.qml +++ b/src/controls/AbstractApplicationHeader.qml @@ -1,54 +1,54 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import "private" import "templates" as T /** * An item that can be used as a title for the application. * Scrolling the main page will make it taller or shorter (trough the point of going away) * It's a behavior similar to the typical mobile web browser adressbar * the minimum, preferred and maximum heights of the item can be controlled with * * minimumHeight: default is 0, i.e. hidden * * preferredHeight: default is Units.gridUnit * 1.6 * * maximumHeight: default is Units.gridUnit * 3 * * To achieve a titlebar that stays completely fixed just set the 3 sizes as the same */ T.AbstractApplicationHeader { id: root background: Rectangle { color: Theme.highlightColor EdgeShadow { id: shadow edge: Qt.TopEdge anchors { right: parent.right left: parent.left top: parent.bottom } } } } diff --git a/src/controls/AbstractApplicationItem.qml b/src/controls/AbstractApplicationItem.qml index a4b5b381..1c55de8a 100644 --- a/src/controls/AbstractApplicationItem.qml +++ b/src/controls/AbstractApplicationItem.qml @@ -1,371 +1,371 @@ /* * Copyright 2017 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import QtQuick.Templates 2.0 as T2 import QtQuick.Window 2.2 import "templates/private" -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import QtGraphicalEffects 1.0 /** * A window that provides some basic features needed for all apps * Use this class only if you need a custom content for your application, * different from the Page Row behavior recomended by the HIG and provided * by ApplicationItem. * It is recomended to use ApplicationItem instead * @see ApplicationItem * * It's usually used as a root QML component for the application. * It provides support for a central page stack, side drawers and * a top ApplicationHeader, as well as basic support for the * Android back button * * Example usage: * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.ApplicationItem { * [...] * globalDrawer: Kirigami.GlobalDrawer { * actions: [ * Kirigami.Action { * text: "View" * iconName: "view-list-icons" * Kirigami.Action { * text: "action 1" * } * Kirigami.Action { * text: "action 2" * } * Kirigami.Action { * text: "action 3" * } * }, * Kirigami.Action { * text: "Sync" * iconName: "folder-sync" * } * ] * } * * contextDrawer: Kirigami.ContextDrawer { * id: contextDrawer * } * * pageStack: PageStack { * ... * } * [...] * } * @endcode * * @inherit QtQuick.Item */ Item { id: root /** * pageStack: StackView * Readonly. * The stack used to allocate the pages and to manage the transitions * between them. * Put a container here, such as QQuickControls PageStack */ property Item pageStack LayoutMirroring.enabled: Qt.application.layoutDirection == Qt.RightToLeft LayoutMirroring.childrenInherit: true property alias overlay: overlayRoot Item { anchors.fill: parent parent: root.parent z: 999999 Rectangle { z: -1 anchors.fill: parent color: "black" visible: contextDrawer && contextDrawer.modal parent: contextDrawer ? contextDrawer.background.parent.parent : overlayRoot opacity: contextDrawer ? contextDrawer.position * 0.6 : 0 } Rectangle { z: -1 anchors.fill: parent color: "black" visible: globalDrawer && globalDrawer.modal parent: contextDrawer ? globalDrawer.background.parent.parent : overlayRoot opacity: contextDrawer ? globalDrawer.position * 0.6 : 0 } Item { id: overlayRoot z: -1 anchors.fill: parent } Window.onWindowChanged: { if (globalDrawer) { globalDrawer.visible = globalDrawer.drawerOpen; } if (contextDrawer) { contextDrawer.visible = contextDrawer.drawerOpen; } } } /** * copatibility with Applicationwindow */ readonly property Item activeFocusItem: Window.activeFocusItem /** * Shows a little passive notification at the bottom of the app window * lasting for few seconds, with an optional action button. * * @param message The text message to be shown to the user. * @param timeout How long to show the message: * possible values: "short", "long" or the number of milliseconds * @param actionText Text in the action button, if any. * @param callBack A JavaScript function that will be executed when the * user clicks the button. */ function showPassiveNotification(message, timeout, actionText, callBack) { if (!internal.__passiveNotification) { var component = Qt.createComponent("templates/private/PassiveNotification.qml"); internal.__passiveNotification = component.createObject(overlay.parent); } internal.__passiveNotification.showNotification(message, timeout, actionText, callBack); } /** * Hide the passive notification, if any is shown */ function hidePassiveNotification() { if(internal.__passiveNotification) { internal.__passiveNotification.hideNotification(); } } /** * @returns a pointer to this application window * can be used anywhere in the application. */ function applicationWindow() { return root; } /** * header: ApplicationHeader * An item that can be used as a title for the application. * Scrolling the main page will make it taller or shorter (trough the point of going away) * It's a behavior similar to the typical mobile web browser adressbar * the minimum, preferred and maximum heights of the item can be controlled with * * Layout.minimumHeight: default is 0, i.e. hidden * * Layout.preferredHeight: default is Units.gridUnit * 1.6 * * Layout.maximumHeight: default is Units.gridUnit * 3 * * To achieve a titlebar that stays completely fixed just set the 3 sizes as the same */ property Item header onHeaderChanged: header.parent = contentItemRoot /** * footer: ApplicationHeader * An item that can be used as a footer for the application. */ property Item footer onFooterChanged: footer.parent = contentItemRoot /** * controlsVisible: bool * This property controls wether the standard chrome of the app, such * as the Action button, the drawer handles and the application * header should be visible or not. */ property bool controlsVisible: true /** * globalDrawer: OverlayDrawer * The drawer for global actions, that will be opened by sliding from the * left screen edge or by dragging the ActionButton to the right. * It is recommended to use the GlobalDrawer class here */ property OverlayDrawer globalDrawer /** * wideScreen: bool * If true the application is considered to be in "widescreen" mode, such as on desktops or horizontal tablets. * Different styles can have an own logic for deciding this */ property bool wideScreen: width >= Units.gridUnit * 60 /** * contextDrawer: OverlayDrawer * The drawer for context-dependednt actions, that will be opened by sliding from the * right screen edge or by dragging the ActionButton to the left. * It is recommended to use the ContextDrawer class here. * The contents of the context drawer should depend from what page is * loaded in the main pageStack * * Example usage: * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.ApplicationItem { * [...] * contextDrawer: Kirigami.ContextDrawer { * id: contextDrawer * } * [...] * } * @endcode * * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.Page { * [...] * contextualActions: [ * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * }, * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * } * ] * [...] * } * @endcode * * When this page will be the current one, the context drawer will visualize * contextualActions defined as property in that page. */ property OverlayDrawer contextDrawer /** * reachableMode: bool * When true the application is in reachable mode for single hand use. * the whole content of the application is moved down the screen to be * reachable with the thumb. if wideScreen is true, or reachableModeEnabled is false, * tis property has no effect. */ property bool reachableMode: false /** * When true the application will go into reachable mode on pull down */ property bool reachableModeEnabled: true MouseArea { parent: contentItem.parent z: -1 anchors.fill: parent onClicked: root.reachableMode = false; visible: root.reachableMode && root.reachableModeEnabled Rectangle { anchors.fill: parent color: Qt.rgba(0, 0, 0, 0.3) opacity: 0.15 Icon { anchors.horizontalCenter: parent.horizontalCenter y: x width: Units.iconSizes.large height: width source: "go-up" } } } /** * contentItem: Item * This property holds the Item of the main part of the Application UI */ default property alias __data: contentItemRoot.data readonly property Item contentItem: Item { id: contentItemRoot parent: root anchors.fill: parent anchors.left: contentItem.parent.left anchors.right: contentItem.parent.right anchors.topMargin: root.wideScreen && header && controlsVisible ? header.height : 0 anchors.leftMargin: root.globalDrawer && (root.globalDrawer.modal === false) ? root.globalDrawer.contentItem.width * root.globalDrawer.position : 0 anchors.rightMargin: root.contextDrawer && root.contextDrawer.modal === false ? root.contextDrawer.contentItem.width * root.contextDrawer.position : 0 transform: Translate { Behavior on y { NumberAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } y: root.reachableMode && root.reachableModeEnabled && !root.wideScreen ? root.height/2 : 0 x: root.globalDrawer && root.globalDrawer.modal === true && root.globalDrawer.toString().indexOf("SplitDrawer") === 0 ? root.globalDrawer.contentItem.width * root.globalDrawer.position : 0 } Binding { when: root.header target: root.header property: "y" value: root.header ? -root.header.height : 0 } } //Don't want overscroll in landscape mode onWidthChanged: { if (width > height) { root.reachableMode = false; } } Binding { when: globalDrawer !== undefined && root.visible target: globalDrawer property: "parent" value: overlay } Binding { when: contextDrawer !== undefined && root.visible target: contextDrawer property: "parent" value: overlay } onPageStackChanged: pageStack.parent = contentItem; width: Units.gridUnit * 30 height: Units.gridUnit * 45 visible: true QtObject { id: internal property Item __passiveNotification } Shortcut { sequence: StandardKey.Quit onActivated: root.close() } } diff --git a/src/controls/AbstractApplicationWindow.qml b/src/controls/AbstractApplicationWindow.qml index a6094c77..ae3f92b7 100644 --- a/src/controls/AbstractApplicationWindow.qml +++ b/src/controls/AbstractApplicationWindow.qml @@ -1,305 +1,305 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import QtQuick.Controls 2.0 as QQC2 import "templates/private" -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import QtGraphicalEffects 1.0 /** * A window that provides some basic features needed for all apps * Use this class only if you need a custom content for your application, * different from the Page Row behavior recomended by the HIG and provided * by ApplicationWindow. * It is recomended to use ApplicationWindow instead * @see ApplicationWindow * * It's usually used as a root QML component for the application. * It provides support for a central page stack, side drawers and * a top ApplicationHeader, as well as basic support for the * Android back button * * Example usage: * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.ApplicationWindow { * [...] * globalDrawer: Kirigami.GlobalDrawer { * actions: [ * Kirigami.Action { * text: "View" * iconName: "view-list-icons" * Kirigami.Action { * text: "action 1" * } * Kirigami.Action { * text: "action 2" * } * Kirigami.Action { * text: "action 3" * } * }, * Kirigami.Action { * text: "Sync" * iconName: "folder-sync" * } * ] * } * * contextDrawer: Kirigami.ContextDrawer { * id: contextDrawer * } * * pageStack: PageStack { * ... * } * [...] * } * @endcode * * @inherit QtQuick.Controls.ApplicationWindow */ QQC2.ApplicationWindow { id: root /** * pageStack: StackView * Readonly. * The stack used to allocate the pages and to manage the transitions * between them. * Put a container here, such as QQuickControls PageStack */ property Item pageStack LayoutMirroring.enabled: Qt.application.layoutDirection == Qt.RightToLeft LayoutMirroring.childrenInherit: true /** * Shows a little passive notification at the bottom of the app window * lasting for few seconds, with an optional action button. * * @param message The text message to be shown to the user. * @param timeout How long to show the message: * possible values: "short", "long" or the number of milliseconds * @param actionText Text in the action button, if any. * @param callBack A JavaScript function that will be executed when the * user clicks the button. */ function showPassiveNotification(message, timeout, actionText, callBack) { if (!internal.__passiveNotification) { var component = Qt.createComponent("templates/private/PassiveNotification.qml"); internal.__passiveNotification = component.createObject(overlay.parent); } internal.__passiveNotification.showNotification(message, timeout, actionText, callBack); } /** * Hide the passive notification, if any is shown */ function hidePassiveNotification() { if(internal.__passiveNotification) { internal.__passiveNotification.hideNotification(); } } /** * @returns a pointer to this application window * can be used anywhere in the application. */ function applicationWindow() { return root; } /** * header: ApplicationHeader * An item that can be used as a title for the application. * Scrolling the main page will make it taller or shorter (trough the point of going away) * It's a behavior similar to the typical mobile web browser adressbar * the minimum, preferred and maximum heights of the item can be controlled with * * Layout.minimumHeight: default is 0, i.e. hidden * * Layout.preferredHeight: default is Units.gridUnit * 1.6 * * Layout.maximumHeight: default is Units.gridUnit * 3 * * To achieve a titlebar that stays completely fixed just set the 3 sizes as the same * //FIXME: this should become an actual ApplicationHeader */ //header: undefined /** * controlsVisible: bool * This property controls wether the standard chrome of the app, such * as the Action button, the drawer handles and the application * header should be visible or not. */ property bool controlsVisible: true /** * globalDrawer: OverlayDrawer * The drawer for global actions, that will be opened by sliding from the * left screen edge or by dragging the ActionButton to the right. * It is recommended to use the GlobalDrawer class here */ property OverlayDrawer globalDrawer /** * wideScreen: bool * If true the application is considered to be in "widescreen" mode, such as on desktops or horizontal tablets. * Different styles can have an own logic for deciding this */ property bool wideScreen: width >= Units.gridUnit * 60 /** * contextDrawer: OverlayDrawer * The drawer for context-dependednt actions, that will be opened by sliding from the * right screen edge or by dragging the ActionButton to the left. * It is recommended to use the ContextDrawer class here. * The contents of the context drawer should depend from what page is * loaded in the main pageStack * * Example usage: * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.ApplicationWindow { * [...] * contextDrawer: Kirigami.ContextDrawer { * id: contextDrawer * } * [...] * } * @endcode * * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.Page { * [...] * contextualActions: [ * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * }, * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * } * ] * [...] * } * @endcode * * When this page will be the current one, the context drawer will visualize * contextualActions defined as property in that page. */ property OverlayDrawer contextDrawer /** * reachableMode: bool * When true the application is in reachable mode for single hand use. * the whole content of the application is moved down the screen to be * reachable with the thumb. if wideScreen is true, or reachableModeEnabled is false, * tis property has no effect. */ property bool reachableMode: false /** * When true the application will go into reachable mode on pull down */ property bool reachableModeEnabled: true MouseArea { parent: contentItem.parent z: -1 anchors.fill: parent onClicked: root.reachableMode = false; visible: root.reachableMode && root.reachableModeEnabled Rectangle { anchors.fill: parent color: Qt.rgba(0, 0, 0, 0.3) opacity: 0.15 Icon { anchors.horizontalCenter: parent.horizontalCenter y: x width: Units.iconSizes.large height: width source: "go-up" } } } contentItem.anchors.left: contentItem.parent.left contentItem.anchors.right: contentItem.parent.right contentItem.anchors.topMargin: root.wideScreen && header && controlsVisible ? header.height : 0 contentItem.anchors.leftMargin: root.globalDrawer && (root.globalDrawer.modal === false) ? root.globalDrawer.contentItem.width * root.globalDrawer.position : 0 contentItem.anchors.rightMargin: root.contextDrawer && root.contextDrawer.modal === false ? root.contextDrawer.contentItem.width * root.contextDrawer.position : 0 contentItem.transform: Translate { Behavior on y { NumberAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } y: root.reachableMode && root.reachableModeEnabled && !root.wideScreen ? root.height/2 : 0 x: root.globalDrawer && root.globalDrawer.modal === true && root.globalDrawer.toString().indexOf("SplitDrawer") === 0 ? root.globalDrawer.contentItem.width * root.globalDrawer.position : 0 } //Don't want overscroll in landscape mode onWidthChanged: { if (width > height) { root.reachableMode = false; } } Binding { when: globalDrawer !== undefined && root.visible target: globalDrawer property: "parent" value: overlay } Binding { when: contextDrawer !== undefined && root.visible target: contextDrawer property: "parent" value: overlay } onPageStackChanged: pageStack.parent = contentItem; width: Units.gridUnit * 30 height: Units.gridUnit * 45 visible: true QtObject { id: internal property Item __passiveNotification } Shortcut { sequence: StandardKey.Quit onActivated: root.close() } } diff --git a/src/controls/AbstractItemViewHeader.qml b/src/controls/AbstractItemViewHeader.qml index 5142e71d..6842ce32 100644 --- a/src/controls/AbstractItemViewHeader.qml +++ b/src/controls/AbstractItemViewHeader.qml @@ -1,49 +1,49 @@ /* * Copyright 2017 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import QtQuick.Templates 2.0 as T2 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami /** * An item that can be used as an header for a ListView. * It will play nice with the margin policies of ScrollablePage and can * automatically shrink when the list is scrolled, like the behavior * of list headers in many mobile applications. * @since 2.1 * @inherit QtQuick.Controls.Control */ T2.Control { property int minimumHeight: Kirigami.Units.gridUnit * 2 + Kirigami.Units.smallSpacing * 2 property int maximumHeight: Kirigami.Units.gridUnit * 6 property ListView view: ListView.view width: view.width implicitHeight: topPadding + bottomPadding + (view.headerPositioning == ListView.InlineHeader ? maximumHeight : Math.min(maximumHeight, Math.max(minimumHeight, maximumHeight - Math.max(0, view.contentY)))) z: 9 topPadding: applicationWindow() && !applicationWindow().wideScreen && applicationWindow().header ? applicationWindow().header.paintedHeight : 0 rightPadding: Kirigami.Units.gridUnit } diff --git a/src/controls/ApplicationItem.qml b/src/controls/ApplicationItem.qml index 4cc842d4..445e3d7a 100644 --- a/src/controls/ApplicationItem.qml +++ b/src/controls/ApplicationItem.qml @@ -1,174 +1,174 @@ /* * Copyright 2017 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import "templates/private" -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami import QtGraphicalEffects 1.0 /** * A window that provides some basic features needed for all apps * This version is an Item as opposed to a window, it's intended * for use into a QQuickView * * It's usually used as a root QML component for the application. * It's based around the PageRow component, the application will be * about pages adding and removal. * For most of the usages, this class should be used instead * of AbstractApplicationWidnow * @see AbstractApplicationWidnow * * Example usage: * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.ApplicationItem { * [...] * globalDrawer: Kirigami.GlobalDrawer { * actions: [ * Kirigami.Action { * text: "View" * iconName: "view-list-icons" * Kirigami.Action { * text: "action 1" * } * Kirigami.Action { * text: "action 2" * } * Kirigami.Action { * text: "action 3" * } * }, * Kirigami.Action { * text: "Sync" * iconName: "folder-sync" * } * ] * } * * contextDrawer: Kirigami.ContextDrawer { * id: contextDrawer * } * * pageStack.initialPage: Kirigami.Page { * mainAction: Kirigami.Action { * iconName: "edit" * onTriggered: { * // do stuff * } * } * contextualActions: [ * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * }, * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * } * ] * [...] * } * [...] * } * @endcode * */ AbstractApplicationItem { id: root /** * pageStack: StackView * Readonly. * The stack used to allocate the pages and to manage the transitions * between them. * It's using a PageRow, while having the same API as PageStack, * it positions the pages as adjacent columns, with as many columns * as can fit in the screen. An handheld device would usually have a single * fullscreen column, a tablet device would have many tiled columns. */ property alias pageStack: __pageStack //redefines here as here we can know a pointer to PageRow wideScreen: width >= applicationWindow().pageStack.defaultColumnWidth*2 PageRow { id: __pageStack anchors { fill: parent //HACK: workaround a bug in android iOS keyboard management bottomMargin: ((Qt.platform.os == "android" || Qt.platform.os == "ios") || !Qt.inputMethod.visible) ? 0 : Qt.inputMethod.keyboardRectangle.height onBottomMarginChanged: { if (bottomMargin > 0) { root.reachableMode = false; } } } //FIXME onCurrentIndexChanged: root.reachableMode = false; function goBack() { //NOTE: drawers are handling the back button by themselves var backEvent = {accepted: false} if (root.pageStack.currentIndex >= 1) { root.pageStack.currentItem.backRequested(backEvent); if (!backEvent.accepted) { root.pageStack.flickBack(); backEvent.accepted = true; } } if (Kirigami.Settings.isMobile && !backEvent.accepted && Qt.platform.os !== "ios") { Qt.quit(); } } function goForward() { root.pageStack.currentIndex = Math.min(root.pageStack.depth-1, root.pageStack.currentIndex + 1); } Keys.onBackPressed: { goBack(); event.accepted = true } Shortcut { sequence: "Forward" onActivated: __pageStack.goForward(); } Shortcut { sequence: StandardKey.Forward onActivated: __pageStack.goForward(); } Shortcut { sequence: StandardKey.Back onActivated: __pageStack.goBack(); } Rectangle { z: -1 anchors.fill: parent color: Kirigami.Theme.backgroundColor } focus: true } } diff --git a/src/controls/ApplicationWindow.qml b/src/controls/ApplicationWindow.qml index 66109985..816e9daf 100644 --- a/src/controls/ApplicationWindow.qml +++ b/src/controls/ApplicationWindow.qml @@ -1,172 +1,172 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import "templates/private" -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami import QtGraphicalEffects 1.0 /** * A window that provides some basic features needed for all apps * * It's usually used as a root QML component for the application. * It's based around the PageRow component, the application will be * about pages adding and removal. * For most of the usages, this class should be used instead * of AbstractApplicationWidnow * @see AbstractApplicationWidnow * * Example usage: * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.ApplicationWindow { * [...] * globalDrawer: Kirigami.GlobalDrawer { * actions: [ * Kirigami.Action { * text: "View" * iconName: "view-list-icons" * Kirigami.Action { * text: "action 1" * } * Kirigami.Action { * text: "action 2" * } * Kirigami.Action { * text: "action 3" * } * }, * Kirigami.Action { * text: "Sync" * iconName: "folder-sync" * } * ] * } * * contextDrawer: Kirigami.ContextDrawer { * id: contextDrawer * } * * pageStack.initialPage: Kirigami.Page { * mainAction: Kirigami.Action { * iconName: "edit" * onTriggered: { * // do stuff * } * } * contextualActions: [ * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * }, * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * } * ] * [...] * } * [...] * } * @endcode * */ AbstractApplicationWindow { id: root /** * pageStack: StackView * Readonly. * The stack used to allocate the pages and to manage the transitions * between them. * It's using a PageRow, while having the same API as PageStack, * it positions the pages as adjacent columns, with as many columns * as can fit in the screen. An handheld device would usually have a single * fullscreen column, a tablet device would have many tiled columns. */ property alias pageStack: __pageStack //redefines here as here we can know a pointer to PageRow wideScreen: width >= applicationWindow().pageStack.defaultColumnWidth*2 PageRow { id: __pageStack anchors { fill: parent //HACK: workaround a bug in android iOS keyboard management bottomMargin: ((Qt.platform.os == "android" || Qt.platform.os == "ios") || !Qt.inputMethod.visible) ? 0 : Qt.inputMethod.keyboardRectangle.height onBottomMarginChanged: { if (bottomMargin > 0) { root.reachableMode = false; } } } //FIXME onCurrentIndexChanged: root.reachableMode = false; function goBack() { //NOTE: drawers are handling the back button by themselves var backEvent = {accepted: false} if (root.pageStack.currentIndex >= 1) { root.pageStack.currentItem.backRequested(backEvent); if (!backEvent.accepted) { root.pageStack.flickBack(); backEvent.accepted = true; } } if (Kirigami.Settings.isMobile && !backEvent.accepted && Qt.platform.os !== "ios") { Qt.quit(); } } function goForward() { root.pageStack.currentIndex = Math.min(root.pageStack.depth-1, root.pageStack.currentIndex + 1); } Keys.onBackPressed: { goBack(); event.accepted = true } Shortcut { sequence: "Forward" onActivated: __pageStack.goForward(); } Shortcut { sequence: StandardKey.Forward onActivated: __pageStack.goForward(); } Shortcut { sequence: StandardKey.Back onActivated: __pageStack.goBack(); } Rectangle { z: -1 anchors.fill: parent color: Kirigami.Theme.backgroundColor } focus: true } } diff --git a/src/controls/BasicListItem.qml b/src/controls/BasicListItem.qml index 7b5fdc6c..e72ffe67 100644 --- a/src/controls/BasicListItem.qml +++ b/src/controls/BasicListItem.qml @@ -1,78 +1,78 @@ /* * Copyright 2010 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 /** * An item delegate for the primitive ListView component. * * It's intended to make all listviews look coherent. * It has a default icon and a label * */ AbstractListItem { id: listItem /** * string: bool * A single text label the list item will contain */ property alias label: listItem.text /** * icon: var * A single icon that will be displayed in the list item. The icon can * be either a QIcon, a string name of a fdo compatible name, * or any url accepted by the Image element. */ property alias icon: iconItem.source /** * reserveSpaceForIcon: bool * If true, even when there is no icon the space will be reserved for it * It's useful in layouts where only some entries have an icon, * having the text all horizontally aligned */ property alias reserveSpaceForIcon: iconItem.visible default property alias _basicDefault: layout.children RowLayout { id: layout spacing: Units.smallSpacing*2 - property bool indicateActiveFocus: Settings.isMobile || listItem.activeFocus || (listItem.ListView.view ? listItem.ListView.view.activeFocus : false) + property bool indicateActiveFocus: listItem.pressed || Settings.isMobile || listItem.activeFocus || (listItem.ListView.view ? listItem.ListView.view.activeFocus : false) Icon { id: iconItem Layout.minimumHeight: Units.iconSizes.smallMedium Layout.maximumHeight: Layout.minimumHeight Layout.minimumWidth: height selected: layout.indicateActiveFocus && (listItem.checked || listItem.pressed) } Label { id: labelItem text: listItem.text Layout.fillWidth: true color: layout.indicateActiveFocus && (listItem.checked || listItem.pressed) ? listItem.activeTextColor : listItem.textColor elide: Text.ElideRight font: listItem.font } } } diff --git a/src/controls/ContextDrawer.qml b/src/controls/ContextDrawer.qml index b4db693b..d101c0a0 100644 --- a/src/controls/ContextDrawer.qml +++ b/src/controls/ContextDrawer.qml @@ -1,155 +1,157 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import "templates/private" /** * A drawer specialization that will show a list of actions that are * specific of the current page shown by the application * * Example usage: * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.ApplicationWindow { * [...] * contextDrawer: Kirigami.ContextDrawer { * id: contextDrawer * } * [...] * } * @endcode * * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.Page { * [...] * contextualActions: [ * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * }, * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * } * ] * [...] * } * @endcode * * @inherit AbstractDrawer */ OverlayDrawer { id: root /** * title: string * A title for the action list that will be shown to the user when opens the drawer */ property string title: qsTr("Actions") /** * actions: list * This can be any type of object that a ListView can accept as model. * It expects items compatible with either QAction or Kirigami Action */ property var actions: pageStack.layers.depth > 1 ? pageStack.layers.currentItem.contextualActions : (pageStack.currentItem ? pageStack.currentItem.contextualActions : null) enabled: menu.count > 0 edge: Qt.application.layoutDirection == Qt.RightToLeft ? Qt.LeftEdge : Qt.RightEdge drawerOpen: false //list items go to edges, have their own padding leftPadding: 0 rightPadding: 0 bottomPadding: 0 handleVisible: applicationWindow == undefined ? false : applicationWindow().controlsVisible contentItem: ScrollView { + //this just to create the attached property + Theme.inherit: true implicitWidth: Units.gridUnit * 20 ListView { id: menu interactive: contentHeight > height model: { if (typeof root.actions == "undefined") { return null; } if (root.actions.length == 0) { return null; } else { return root.actions[0].text !== undefined && root.actions[0].trigger !== undefined ? root.actions : root.actions[0]; } } topMargin: menu.height - menu.contentHeight header: Item { height: heading.height width: menu.width Heading { id: heading anchors { left: parent.left right: parent.right margins: Units.largeSpacing } elide: Text.ElideRight level: 2 text: root.title } } delegate: BasicListItem { checked: modelData.checked icon: modelData.iconName supportsMouseEvents: true separatorVisible: false label: model ? (model.tooltip ? model.tooltip : model.text) : (modelData.tooltip ? modelData.tooltip : modelData.text) enabled: model ? model.enabled : modelData.enabled visible: model ? model.visible : modelData.visible opacity: enabled ? 1.0 : 0.6 onClicked: { if (modelData && modelData.trigger !== undefined) { modelData.trigger(); // assume the model is a list of QAction or Action } else if (menu.model.length > index) { menu.model[index].trigger(); } else { console.warning("Don't know how to trigger the action") } root.drawerOpen = false; } } } } } diff --git a/src/controls/GlobalDrawer.qml b/src/controls/GlobalDrawer.qml index 9f130c7d..bd184010 100644 --- a/src/controls/GlobalDrawer.qml +++ b/src/controls/GlobalDrawer.qml @@ -1,442 +1,446 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Templates 2.0 as T2 import QtQuick.Layouts 1.2 import QtGraphicalEffects 1.0 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import "private" import "templates/private" /** * A drawer specialization intended for the global actions of the application * valid regardless of the application state (think about the menubar * of a desktop application). * * Example usage: * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.ApplicationWindow { * [...] * globalDrawer: Kirigami.GlobalDrawer { * actions: [ * Kirigami.Action { * text: "View" * iconName: "view-list-icons" * Kirigami.Action { * text: "action 1" * } * Kirigami.Action { * text: "action 2" * } * Kirigami.Action { * text: "action 3" * } * }, * Kirigami.Action { * text: "Sync" * iconName: "folder-sync" * } * ] * } * [...] * } * @endcode * */ OverlayDrawer { id: root edge: Qt.application.layoutDirection == Qt.RightToLeft ? Qt.RightEdge : Qt.LeftEdge /** * title: string * A title to be displayed on top of the drawer */ property alias title: heading.text /** * icon: var * An icon to be displayed alongside the title. * It can be a QIcon, a fdo-compatible icon name, or any url understood by Image */ property alias titleIcon: headingIcon.source /** * bannerImageSource: string * An image to be used as background for the title and icon for * a decorative purpose. * It accepts any url format supported by Image */ property alias bannerImageSource: bannerImage.source /** * actions: list * The list of actions can be nested having a tree structure. * A tree depth bigger than 2 is discouraged. * * Example usage: * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.ApplicationWindow { * [...] * globalDrawer: Kirigami.GlobalDrawer { * actions: [ * Kirigami.Action { * text: "View" * iconName: "view-list-icons" * Kirigami.Action { * text: "action 1" * } * Kirigami.Action { * text: "action 2" * } * Kirigami.Action { * text: "action 3" * } * }, * Kirigami.Action { * text: "Sync" * iconName: "folder-sync" * } * ] * } * [...] * } * @endcode */ property list actions /** * content: list default property * Any random Item can be instantiated inside the drawer and * will be displayed underneath the actions list. * * Example usage: * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.ApplicationWindow { * [...] * globalDrawer: Kirigami.GlobalDrawer { * actions: [...] * Button { * text: "Button" * onClicked: //do stuff * } * } * [...] * } * @endcode */ default property alias content: mainContent.data /** * topContent: list default property * Items that will be instantiated inside the drawer and * will be displayed on top of the actions list. * * Example usage: * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.ApplicationWindow { * [...] * globalDrawer: Kirigami.GlobalDrawer { * actions: [...] * topContent: [Button { * text: "Button" * onClicked: //do stuff * }] * } * [...] * } * @endcode */ property alias topContent: topContent.data /** * resetMenuOnTriggered: bool * * On the actions menu, whenever a leaf action is triggered, the menu * will reset to its parent. */ property bool resetMenuOnTriggered: true /** * currentSubMenu: Action * * Points to the action acting as a submenu */ readonly property Action currentSubMenu: stackView.currentItem ? stackView.currentItem.current: null /** * Notifies that the banner has been clicked */ signal bannerClicked() /** * Reverts the menu back to its initial state */ function resetMenu() { stackView.pop(stackView.get(0, T2.StackView.DontLoad)); if (root.modal) { root.drawerOpen = false; } } rightPadding: !Settings.isMobile && mainFlickable.contentHeight > mainFlickable.height ? Units.gridUnit : Units.smallSpacing contentItem: ScrollView { id: scrollView + //ensure the attached property exists + Theme.inherit: true anchors.fill: parent implicitWidth: Math.min (Units.gridUnit * 20, root.parent.width * 0.8) horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff Flickable { id: mainFlickable contentWidth: width contentHeight: mainColumn.Layout.minimumHeight ColumnLayout { id: mainColumn width: mainFlickable.width spacing: 0 height: Math.max(root.height, Layout.minimumHeight) Image { id: bannerImage Layout.fillWidth: true Layout.preferredWidth: title.implicitWidth Layout.preferredHeight: bannerImageSource != "" ? 10 * Units.gridUnit : Layout.minimumHeight Layout.minimumHeight: title.height > 0 ? title.height + Units.smallSpacing * 2 : 0 MouseArea { anchors.fill: parent onClicked: root.bannerClicked() } fillMode: Image.PreserveAspectCrop asynchronous: true anchors { left: parent.left right: parent.right top: parent.top } EdgeShadow { edge: Qt.BottomEdge visible: bannerImageSource != "" anchors { left: parent.left right: parent.right bottom: parent.top } } LinearGradient { anchors { left: parent.left right: parent.right top: parent.top } visible: bannerImageSource != "" && root.title != "" height: title.height * 1.3 start: Qt.point(0, 0) end: Qt.point(0, height) gradient: Gradient { GradientStop { position: 0.0 color: Qt.rgba(0, 0, 0, 0.8) } GradientStop { position: 1.0 color: "transparent" } } } RowLayout { id: title anchors { left: parent.left top: parent.top margins: Units.smallSpacing * 2 } Icon { id: headingIcon Layout.minimumWidth: Units.iconSizes.large Layout.minimumHeight: width visible: valid + isMask: false //TODO: find a better way to control selective coloring on Android enabled: !Settings.isMobile } Heading { id: heading Layout.fillWidth: true Layout.rightMargin: heading.height visible: text.length > 0 level: 1 color: bannerImageSource != "" ? "white" : Theme.textColor elide: Text.ElideRight } } } ColumnLayout { id: topContent spacing: 0 Layout.alignment: Qt.AlignHCenter Layout.leftMargin: root.leftPadding Layout.rightMargin: root.rightPadding Layout.bottomMargin: Units.smallSpacing Layout.topMargin: root.topPadding Layout.fillWidth: true Layout.fillHeight: true //NOTE: why this? just Layout.fillWidth: true doesn't seem sufficient //as items are added only after this column creation Layout.minimumWidth: parent.width - root.leftPadding - root.rightPadding visible: children.length > 0 && childrenRect.height > 0 } T2.StackView { id: stackView Layout.fillWidth: true Layout.minimumHeight: currentItem ? currentItem.implicitHeight : 0 Layout.maximumHeight: Layout.minimumHeight initialItem: menuComponent //NOTE: it's important those are NumberAnimation and not XAnimators // as while the animation is running the drawer may close, and //the animator would stop when not drawing see BUG 381576 popEnter: Transition { NumberAnimation { property: "x"; from: (stackView.mirrored ? -1 : 1) * -stackView.width; to: 0; duration: 400; easing.type: Easing.OutCubic } } popExit: Transition { NumberAnimation { property: "x"; from: 0; to: (stackView.mirrored ? -1 : 1) * stackView.width; duration: 400; easing.type: Easing.OutCubic } } pushEnter: Transition { NumberAnimation { property: "x"; from: (stackView.mirrored ? -1 : 1) * stackView.width; to: 0; duration: 400; easing.type: Easing.OutCubic } } pushExit: Transition { NumberAnimation { property: "x"; from: 0; to: (stackView.mirrored ? -1 : 1) * -stackView.width; duration: 400; easing.type: Easing.OutCubic } } replaceEnter: Transition { NumberAnimation { property: "x"; from: (stackView.mirrored ? -1 : 1) * stackView.width; to: 0; duration: 400; easing.type: Easing.OutCubic } } replaceExit: Transition { NumberAnimation { property: "x"; from: 0; to: (stackView.mirrored ? -1 : 1) * -stackView.width; duration: 400; easing.type: Easing.OutCubic } } } Item { Layout.fillWidth: true Layout.fillHeight: root.actions.length>0 Layout.minimumHeight: Units.smallSpacing } ColumnLayout { id: mainContent Layout.alignment: Qt.AlignHCenter Layout.leftMargin: root.leftPadding Layout.rightMargin: root.rightPadding Layout.fillWidth: true Layout.fillHeight: true //NOTE: why this? just Layout.fillWidth: true doesn't seem sufficient //as items are added only after this column creation Layout.minimumWidth: parent.width - root.leftPadding - root.rightPadding visible: children.length > 0 } Item { Layout.minimumWidth: Units.smallSpacing Layout.minimumHeight: root.bottomPadding } Component { id: menuComponent ColumnLayout { spacing: 0 property alias model: actionsRepeater.model property Action current property int level: 0 Layout.maximumHeight: Layout.minimumHeight BasicListItem { visible: level > 0 supportsMouseEvents: true icon: (LayoutMirroring.enabled ? "go-previous-symbolic-rtl" : "go-previous-symbolic") label: qsTr("Back") separatorVisible: false onClicked: stackView.pop() } Repeater { id: actionsRepeater model: actions delegate: BasicListItem { id: listItem supportsMouseEvents: true checked: modelData.checked icon: modelData.iconName label: modelData.text separatorVisible: false visible: model ? model.visible || model.visible===undefined : modelData.visible enabled: model ? model.enabled : modelData.enabled opacity: enabled ? 1.0 : 0.3 Icon { + isMask: true anchors { verticalCenter: contentItem.verticalCenter right: contentItem.right rightMargin: !Settings.isMobile && mainFlickable.contentHeight > mainFlickable.height ? Units.gridUnit : 0 } height: Units.iconSizes.smallMedium selected: listItem.checked || listItem.pressed width: height source: (LayoutMirroring.enabled ? "go-next-symbolic-rtl" : "go-next-symbolic") visible: modelData.children!==undefined && modelData.children.length > 0 } onClicked: { modelData.trigger(); if (modelData.children!==undefined && modelData.children.length > 0) { stackView.push(menuComponent, {model: modelData.children, level: level + 1, current: modelData }); } else if (root.resetMenuOnTriggered) { root.resetMenu(); } checked = Qt.binding(function() { return modelData.checked }); } } } } } } } } } diff --git a/src/controls/Heading.qml b/src/controls/Heading.qml index 947b8904..d61da505 100644 --- a/src/controls/Heading.qml +++ b/src/controls/Heading.qml @@ -1,84 +1,84 @@ /* * Copyright 2012 by Sebastian Kügler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.0 import QtQuick.Controls 2.0 as QQC2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 /** * A heading label used for subsections of texts. * * The characteristics of the text will be automatically set according to the * plasma Theme. Use this components for section titles or headings in your UI, * for example page or section titles. * * Example usage: * * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * [...] * Column { * Kirigami.Heading { * text: "Apples in the sunlight" * level: 2 * } * [...] * } * @endcode * * The most important property is "text", which applies to the text property of * Label. See PlasmaComponents Label and primitive QML Text element API for * additional properties, methods and signals. * @inherits QtQuick.Controls.Label */ QQC2.Label { id: heading /** * level: int * The level determines how big the section header is display, values * between 1 (big) and 5 (small) are accepted */ property int level: 1 /** * step: int * adjust the point size in between a level and another. */ property int step: 2 lineHeight: 1.2 font.pointSize: headerPointSize(level) font.weight: Font.Light wrapMode: Text.WordWrap opacity: 0.8 function headerPointSize(l) { var n = Theme.defaultFont.pointSize; var s; if (l > 4) { s = n } else if (l < 2) { s = n + (5*step) } else { s = n + ((5-level)*2) } return s; } } diff --git a/src/controls/Icon.qml b/src/controls/Icon.qml index 1c0fd2a2..10a2dc7d 100644 --- a/src/controls/Icon.qml +++ b/src/controls/Icon.qml @@ -1,80 +1,95 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import QtGraphicalEffects 1.0 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 /** * Graphical representatrion of an Icon * @inherit QtQuick.Item */ Item { id: root /** * source: string * It can be any string Image would recognize as source, or a system-wide icon * name that would be defined in a desktop icon theme, such as "go-up" */ property string source /** * smooth: bool * render smoothly */ property alias smooth: image.smooth /** * active: bool * the icon is in an active state, such as under the umouse */ property bool active: false /** * valid: bool * if true the icon loaded correctly */ property bool valid: image.status == Image.Ready /** * The icon is in a "selected" status, which usually means its color scheme * is inverted and is over a colored background */ property bool selected: false + /** + * isMask: bool + * true if the icon should be treated as a monochrome icon which can be tinted + * @since 2.2 + */ + property bool isMask: true + + /** + * color: color + * Allow to set the main color of the icon as a particular color + * default: transparent + * @since 2.2 + */ + property color color: "transparent" + implicitWidth: image.source != "" ? Units.iconSizes.smallMedium : 0 implicitHeight: image.source != "" ? Units.iconSizes.smallMedium : 0 Image { id: image anchors.fill: parent source: root.source != "" ? (root.source.indexOf(".") === -1 ? "./icons/" + root.source + ".svg" : root.source) : root.source sourceSize.width: root.width sourceSize.height: root.height fillMode: Image.PreserveAspectCrop } ColorOverlay { anchors.fill: parent source: image - color: root.selected ? Theme.highlightedTextColor : Theme.textColor + color: root.selected ? Theme.highlightedTextColor : (root.color != "trasparent" ? root.color : Theme.textColor) cached: true - visible: root.enabled && root.valid + visible: root.enabled && root.valid && root.isMask } } diff --git a/src/controls/ItemViewHeader.qml b/src/controls/ItemViewHeader.qml index 864938f4..f403c769 100644 --- a/src/controls/ItemViewHeader.qml +++ b/src/controls/ItemViewHeader.qml @@ -1,114 +1,114 @@ /* * Copyright 2017 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import QtQuick.Templates 2.0 as T2 import QtGraphicalEffects 1.0 -import org.kde.kirigami 2.1 as Kirigami +import org.kde.kirigami 2.2 as Kirigami import "private" /** * An item that can be used as an header for a ListView. * It will play nice with the margin policies of ScrollablePage and can * automatically shrink when the list is scrolled, like the behavior * of list headers in many mobile applications. * It provides some default content: a title and an optional background image * @since 2.1 */ Kirigami.AbstractItemViewHeader { id: root property alias title: heading.text property alias color: heading.color property alias backgroundImage: image maximumHeight: (backgroundImage.hasImage ? 10 : 6) * Kirigami.Units.gridUnit - (applicationWindow().header ? applicationWindow().header.height : 0) bottomPadding: Kirigami.Units.smallSpacing leftPadding: Kirigami.Units.smallSpacing background: Rectangle { id: backgroundItem color: Kirigami.Theme.backgroundColor Image { id: image anchors.fill: parent readonly property bool hasImage: backgroundImage.status === Image.Ready || backgroundImage.status === Image.Loading fillMode: Image.PreserveAspectCrop asynchronous: true } EdgeShadow { edge: root.view.headerPositioning == ListView.InlineHeader ? Qt.BottomEdge : Qt.TopEdge anchors { right: parent.right left: parent.left top: root.view.headerPositioning == ListView.InlineHeader ? undefined : parent.bottom bottom: root.view.headerPositioning == ListView.InlineHeader ? parent.top : undefined } } readonly property Page page: { var obj = root.view; while(obj && !obj.hasOwnProperty("title") && !obj.hasOwnProperty("isCurrentPage")) { obj = obj.parent } return obj; } Rectangle { id: rect color: backgroundItem.page.isCurrentPage ? Kirigami.Theme.highlightColor : Kirigami.Theme.disabledTextColor height: root.bottomPadding anchors { left: parent.left right: parent.right bottom: parent.bottom } } } contentItem: Item { Kirigami.Heading { id: heading anchors { fill: parent margins: Kirigami.Units.smallSpacing } height: undefined text: page.title fontSizeMode: Text.Fit minimumPointSize: 10 font.pointSize: 30 horizontalAlignment: Text.AlignRight verticalAlignment: Text.AlignBottom color: root.backgroundImage.hasImage ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.highlightColor opacity: 1 elide: Text.ElideRight layer.enabled: root.backgroundImage.hasImage layer.effect: DropShadow { horizontalOffset: 0 verticalOffset: 2 radius: Kirigami.Units.smallSpacing*2 samples: 32 color: Qt.rgba(0, 0, 0, 0.7) } } } } diff --git a/src/controls/Label.qml b/src/controls/Label.qml index 6f4b1534..daf8dd36 100644 --- a/src/controls/Label.qml +++ b/src/controls/Label.qml @@ -1,61 +1,61 @@ /* * Copyright (C) 2011 by Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.1 import QtQuick.Window 2.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import QtQuick.Templates 2.0 as T2 /** * This is a label which uses the plasma Theme. * * The characteristics of the text will be automatically set according to the * plasma Theme. If you need a more customized text item use the Text component * from QtQuick. * * You can use all elements of the QML Text component, in particular the "text" * property to define the label text. * * @inherit QtQuick.Templates.Label */ T2.Label { id: root height: Math.round(Math.max(paintedHeight, Units.gridUnit * 1.6)) verticalAlignment: lineCount > 1 ? Text.AlignTop : Text.AlignVCenter activeFocusOnTab: false renderType: Settings.isMobile || Window.devicePixelRatio % 2 != 0 ? Text.QtRendering : Text.NativeRendering font.capitalization: Theme.defaultFont.capitalization font.family: Theme.defaultFont.family font.italic: Theme.defaultFont.italic font.letterSpacing: Theme.defaultFont.letterSpacing font.pointSize: Theme.defaultFont.pointSize font.strikeout: Theme.defaultFont.strikeout font.underline: Theme.defaultFont.underline font.weight: Theme.defaultFont.weight font.wordSpacing: Theme.defaultFont.wordSpacing color: Theme.textColor opacity: enabled? 1 : 0.6 Accessible.role: Accessible.StaticText Accessible.name: text } diff --git a/src/controls/OverlayDrawer.qml b/src/controls/OverlayDrawer.qml index 5aebeb8b..e52cd34a 100644 --- a/src/controls/OverlayDrawer.qml +++ b/src/controls/OverlayDrawer.qml @@ -1,104 +1,104 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtGraphicalEffects 1.0 import QtQuick.Templates 2.0 as T2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import "private" import "templates" as T /** * Overlay Drawers are used to expose additional UI elements needed for * small secondary tasks for which the main UI elements are not needed. * For example in Okular Active, an Overlay Drawer is used to display * thumbnails of all pages within a document along with a search field. * This is used for the distinct task of navigating to another page. */ T.OverlayDrawer { id: root //BEGIN Properties background: Rectangle { - color: Theme.viewBackgroundColor + color: Theme.backgroundColor Item { parent: root.handle anchors.fill: parent DropShadow { anchors.fill: handleGraphics horizontalOffset: 0 verticalOffset: Units.devicePixelRatio radius: Units.gridUnit /2 samples: 16 color: Qt.rgba(0, 0, 0, root.handle.pressed ? 0.6 : 0.4) source: handleGraphics } Rectangle { id: handleGraphics anchors.centerIn: parent - color: root.handle.pressed ? Theme.highlightColor : Theme.buttonBackgroundColor + color: root.handle.pressed ? Theme.highlightColor : Theme.backgroundColor width: Units.iconSizes.smallMedium + Units.smallSpacing * 2 height: width radius: Units.devicePixelRatio * 2 Loader { anchors.centerIn: parent width: height height: Units.iconSizes.small source: root.edge == Qt.LeftEdge ? Qt.resolvedUrl("templates/private/MenuIcon.qml") : (root.edge == Qt.RightEdge ? Qt.resolvedUrl("templates/private/ContextIcon.qml") : "") onItemChanged: { if(item) { item.morph = Qt.binding(function(){return root.position}) - item.color = Qt.binding(function(){return root.handle.pressed ? Theme.highlightedTextColor : Theme.buttonTextColor}) + item.color = Qt.binding(function(){return root.handle.pressed ? Theme.highlightedTextColor : Theme.textColor}) } } } Behavior on color { ColorAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } } } EdgeShadow { z: -2 edge: root.edge anchors { right: root.edge == Qt.RightEdge ? parent.left : (root.edge == Qt.LeftEdge ? undefined : parent.right) left: root.edge == Qt.LeftEdge ? parent.right : (root.edge == Qt.RightEdge ? undefined : parent.left) top: root.edge == Qt.TopEdge ? parent.bottom : (root.edge == Qt.BottomEdge ? undefined : parent.top) bottom: root.edge == Qt.BottomEdge ? parent.top : (root.edge == Qt.TopEdge ? undefined : parent.bottom) } opacity: root.position == 0 ? 0 : 1 Behavior on opacity { NumberAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } } } } diff --git a/src/controls/OverlaySheet.qml b/src/controls/OverlaySheet.qml index 765a4614..67ddab50 100644 --- a/src/controls/OverlaySheet.qml +++ b/src/controls/OverlaySheet.qml @@ -1,106 +1,106 @@ /* * Copyright (C) 2016 by Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.5 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import "private" import "templates" as T /** * An overlay sheet that covers the current Page content. * Its contents can be scrolled up or down, scrolling all the way up or * all the way down, dismisses it. * Use this for big, modal dialogs or information display, that can't be * logically done as a new separate Page, even if potentially * are taller than the screen space. */ T.OverlaySheet { id: root background: Item { anchors.fill: parent //Why not a shadow or rectangularglow? //on some android devices they break badly when the OverlaySheet is bigger than //the screen CornerShadow { corner: Qt.BottomRightCorner anchors { right: parent.left bottom: parent.top } } CornerShadow { corner: Qt.BottomLeftCorner anchors { left: parent.right bottom: parent.top } } CornerShadow { corner: Qt.TopRightCorner anchors { right: parent.left top: parent.bottom } } CornerShadow { corner: Qt.TopLeftCorner anchors { left: parent.right top: parent.bottom } } EdgeShadow { edge: Qt.BottomEdge anchors { left: parent.left right: parent.right bottom: parent.top } } EdgeShadow { edge: Qt.TopEdge anchors { left: parent.left right: parent.right top: parent.bottom } } EdgeShadow { edge: Qt.LeftEdge anchors { top: parent.top bottom: parent.bottom left: parent.right } } EdgeShadow { edge: Qt.RightEdge anchors { top: parent.top bottom: parent.bottom right: parent.left } } Rectangle { anchors.fill: parent - color: Theme.viewBackgroundColor + color: Theme.backgroundColor } } } diff --git a/src/controls/Page.qml b/src/controls/Page.qml index 5d80777d..5dc0acb8 100644 --- a/src/controls/Page.qml +++ b/src/controls/Page.qml @@ -1,266 +1,266 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 as Kirigami import "private" import QtQuick.Templates 2.0 as T2 /** * Page is a container for all the app pages: everything pushed to the * ApplicationWindow stackView should be a Page instabnce (or a subclass, * such as ScrollablePage) * @see ScrollablePage * @inherit QtQuick.Templates.Page */ T2.Page { id: root /** * leftPadding: int * default contents padding at left */ - leftPadding: Units.gridUnit + leftPadding: Kirigami.Units.gridUnit /** * topPadding: int * default contents padding at top */ - topPadding: Units.gridUnit + topPadding: Kirigami.Units.gridUnit /** * rightPadding: int * default contents padding at right */ - rightPadding: Units.gridUnit + rightPadding: Kirigami.Units.gridUnit /** * bottomPadding: int * default contents padding at bottom */ - bottomPadding: Units.gridUnit + bottomPadding: Kirigami.Units.gridUnit /** * flickable: Flickable * if the central element of the page is a Flickable * (ListView and Gridview as well) you can set it there. * normally, you wouldn't need to do that, but just use the * ScrollablePage element instead * @see ScrollablePage * Use this if your flickable has some non standard properties, such as not covering the whole Page */ property Flickable flickable /** * actions.contextualActions: list * Defines the contextual actions for the page: * an easy way to assign actions in the right sliding panel * * Example usage: * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.ApplicationWindow { * [...] * contextDrawer: Kirigami.ContextDrawer { * id: contextDrawer * } * [...] * } * @endcode * * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * * Kirigami.Page { * [...] * actions.contextualActions: [ * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * }, * Kirigami.Action { * iconName: "edit" * text: "Action text" * onTriggered: { * // do stuff * } * } * ] * [...] * } * @endcode */ //TODO: remove property alias contextualActions: actionsGroup.contextualActions /** * actions.main: Action * An optional single action for the action button. * it can be a Kirigami.Action or a QAction * * Example usage: * * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * Kirigami.Page { * actions.main: Kirigami.Action { * iconName: "edit" * onTriggered: { * // do stuff * } * } * } * @endcode */ //TODO: remove property alias mainAction: actionsGroup.main /** * actions.left: Action * An optional extra action at the left of the main action button. * it can be a Kirigami.Action or a QAction * * Example usage: * * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * Kirigami.Page { * actions.left: Kirigami.Action { * iconName: "edit" * onTriggered: { * // do stuff * } * } * } * @endcode */ //TODO: remove property alias leftAction: actionsGroup.left /** * actions.right: Action * An optional extra action at the right of the main action button. * it can be a Kirigami.Action or a QAction * * Example usage: * * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * Kirigami.Page { * actions.right: Kirigami.Action { * iconName: "edit" * onTriggered: { * // do stuff * } * } * } * @endcode */ //TODO: remove property alias rightAction: actionsGroup.right /** * Actions properties are grouped. * * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * Kirigami.Page { * actions { * main: Kirigami.Action {...} * left: Kirigami.Action {...} * right: Kirigami.Action {...} * contextualActions: [ * Kirigami.Action {...}, * Kirigami.Action {...} * ] * } * } * @endcode */ readonly property alias actions: actionsGroup /** * isCurrentPage: bool * * Specifies if it's the currently selected page in the window's pages row. * * @since 2.1 */ readonly property bool isCurrentPage: applicationWindow().pageStack.layers.depth > 1 ? applicationWindow().pageStack.layers.currentItem == root : applicationWindow().pageStack.currentItem == root PageActionPropertyGroup { id: actionsGroup } /** * emitted When the application requests a Back action * For instance a global "back" shortcut or the Android * Back button has been pressed. * The page can manage the back event by itself, * and if it set event.accepted = true, it will stop the main * application to manage the back event. */ signal backRequested(var event); anchors.topMargin: (applicationWindow() && !applicationWindow().wideScreen && Settings.isMobile && applicationWindow().controlsVisible && applicationWindow().header ? applicationWindow().header.preferredHeight : 0) //NOTE: This exists just because control instances require it - contentItem: Item { + contentItem: Item { onChildrenChanged: { //NOTE: make sure OverlaySheets are directly under the root //so they are over all the contents and don't have margins //search for an OverlaySheet, unfortunately have to blind test properties //as there is no way to get the classname from qml objects //TODO: OverlaySheets should be Popup instead? for (var i = children.length -1; i >= 0; --i) { var child = children[i]; if (child.toString().indexOf("OverlaySheet") === 0 || (child.sheetOpen !== undefined && child.open !== undefined && child.close !== undefined)) { child.parent = root; child.z = 9997 } } } } //on material the shadow would bleed over clip: header !== undefined Loader { z: 9999 parent: root anchors { left: parent.left right: parent.right bottom: parent.bottom } height: item ? item.height : 0 source: (applicationWindow().header && applicationWindow().header.toString().indexOf("ToolBarApplicationHeader") === 0) || (applicationWindow().footer && applicationWindow().footer.visible && applicationWindow().footer.toString().indexOf("ToolBarApplicationHeader") === 0) ? "" : Qt.resolvedUrl("./private/ActionButton.qml") } Layout.fillWidth: true } diff --git a/src/controls/PageRow.qml b/src/controls/PageRow.qml index 70c9ab33..f6f04ec3 100644 --- a/src/controls/PageRow.qml +++ b/src/controls/PageRow.qml @@ -1,580 +1,580 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import QtQuick.Layouts 1.2 import QtQml.Models 2.2 import QtQuick.Templates 2.0 as T import QtQuick.Controls 2.0 as QQC2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 /** * PageRow implements a row-based navigation model, which can be used * with a set of interlinked information pages. Items are pushed in the * back of the row and the view scrolls until that row is visualized. * A PageRowcan show a single page or a multiple set of columns, depending * on the window width: on a phone a single column should be fullscreen, * while on a tablet or a desktop more than one column should be visible. * @inherit QtQuick.Templates.Control */ T.Control { id: root //BEGIN PROPERTIES /** * This property holds the number of items currently pushed onto the view */ readonly property int depth: popScrollAnim.running && popScrollAnim.pendingDepth > -1 ? popScrollAnim.pendingDepth : pagesLogic.count /** * The last Page in the Row */ readonly property Item lastItem: pagesLogic.count ? pagesLogic.get(pagesLogic.count - 1).page : null /** * The currently visible Item */ readonly property Item currentItem: mainView.currentItem ? mainView.currentItem.page : null /** * the index of the currently visible Item */ property alias currentIndex: mainView.currentIndex /** * The initial item when this PageRow is created */ property variant initialPage /** * The main flickable of this Row */ contentItem: mainView /** * The default width for a column * default is wide enough for 30 grid units. * Pages can override it with their Layout.fillWidth, * implicitWidth Layout.minimumWidth etc. */ property int defaultColumnWidth: Units.gridUnit * 20 /** * interactive: bool * If true it will be possible to go back/forward by dragging the * content themselves with a gesture. * Otherwise the only way to go back will be programmatically * default: true */ property alias interactive: mainView.interactive /** * wideMode: bool * If true, the PageRow is wide enough that willshow more than one column at once * @since 5.37 */ readonly property bool wideMode: root.width >= root.defaultColumnWidth*2 && pagesLogic.count >= 2 /** * separatorVisible: bool * True if the separator between pages should be visible * default: true * @since 5.38 */ property bool separatorVisible: true //END PROPERTIES //BEGIN FUNCTIONS /** * Pushes a page on the stack. * The page can be defined as a component, item or string. * If an item is used then the page will get re-parented. * If a string is used then it is interpreted as a url that is used to load a page * component. * * @param page The page can also be given as an array of pages. * In this case all those pages will * be pushed onto the stack. The items in the stack can be components, items or * strings just like for single pages. * Additionally an object can be used, which specifies a page and an optional * properties property. * This can be used to push multiple pages while still giving each of * them properties. * When an array is used the transition animation will only be to the last page. * * @param properties The properties argument is optional and allows defining a * map of properties to set on the page. * @return The new created page */ function push(page, properties) { //don't push again things already there if (page.createObject === undefined && typeof page != "string" && pagesLogic.containsPage(page)) { print("The item " + page + " is already in the PageRow"); return; } if (popScrollAnim.running) { popScrollAnim.running = false; popScrollAnim.popPageCleanup(popScrollAnim.pendingPage); } popScrollAnim.popPageCleanup(currentItem); // figure out if more than one page is being pushed var pages; if (page instanceof Array) { pages = page; page = pages.pop(); if (page.createObject === undefined && page.parent === undefined && typeof page != "string") { properties = properties || page.properties; page = page.page; } } // push any extra defined pages onto the stack if (pages) { var i; for (i = 0; i < pages.length; i++) { var tPage = pages[i]; var tProps; if (tPage.createObject === undefined && tPage.parent === undefined && typeof tPage != "string") { if (pagesLogic.containsPage(tPage)) { print("The item " + page + " is already in the PageRow"); continue; } tProps = tPage.properties; tPage = tPage.page; } var container = pagesLogic.initPage(tPage, tProps); pagesLogic.append(container); } } // initialize the page var container = pagesLogic.initPage(page, properties); pagesLogic.append(container); container.visible = container.page.visible = true; mainView.currentIndex = container.level; return container.page } /** * Pops a page off the stack. * @param page If page is specified then the stack is unwound to that page, * to unwind to the first page specify * page as null. * @return The page instance that was popped off the stack. */ function pop(page) { if (depth == 0) { return; } //if a pop was animating, stop it if (popScrollAnim.running) { popScrollAnim.running = false; popScrollAnim.popPageCleanup(popScrollAnim.pendingPage); //if a push was animating, stop it } else { mainView.positionViewAtIndex(mainView.currentIndex, ListView.Beginning); } popScrollAnim.from = mainView.contentX if ((!page || !page.parent) && pagesLogic.count > 1) { page = pagesLogic.get(pagesLogic.count - 2).page; } popScrollAnim.to = page && page.parent ? page.parent.x : 0; popScrollAnim.pendingPage = page; popScrollAnim.pendingDepth = page && page.parent ? page.parent.level + 1 : 0; popScrollAnim.running = true; } SequentialAnimation { id: popScrollAnim property real from property real to property var pendingPage property int pendingDepth: -1 function popPageCleanup(page) { if (pagesLogic.count == 0) { return; } if (popScrollAnim.running) { popScrollAnim.running = false; } var oldPage = pagesLogic.get(pagesLogic.count-1).page; if (page !== undefined) { // an unwind target has been specified - pop until we find it while (page != oldPage && pagesLogic.count > 1) { pagesLogic.removePage(oldPage.parent.level); oldPage = pagesLogic.get(pagesLogic.count-1).page; } } else { pagesLogic.removePage(pagesLogic.count-1); } } NumberAnimation { target: mainView properties: "contentX" duration: Units.shortDuration from: popScrollAnim.from to: popScrollAnim.to } ScriptAction { script: { //snap mainView.flick(100, 0) popScrollAnim.popPageCleanup(popScrollAnim.pendingPage); } } } /** * Replaces a page on the stack. * @param page The page can also be given as an array of pages. * In this case all those pages will * be pushed onto the stack. The items in the stack can be components, items or * strings just like for single pages. * Additionally an object can be used, which specifies a page and an optional * properties property. * This can be used to push multiple pages while still giving each of * them properties. * When an array is used the transition animation will only be to the last page. * @param properties The properties argument is optional and allows defining a * map of properties to set on the page. * @see push() for details. */ function replace(page, properties) { if (currentIndex>=1) popScrollAnim.popPageCleanup(pagesLogic.get(currentIndex-1).page); else if (currentIndex==0) popScrollAnim.popPageCleanup(); else console.warn("There's no page to replace"); return push(page, properties); } /** * Clears the page stack. * Destroy (or reparent) all the pages contained. */ function clear() { return pagesLogic.clearPages(); } /** * @return the page at idx * @param idx the depth of the page we want */ function get(idx) { return pagesLogic.get(idx).page; } /** * go back to the previous index and scroll to the left to show one more column */ function flickBack() { if (depth > 1) { currentIndex = Math.max(0, currentIndex - 1); } if (LayoutMirroring.enabled) { if (!mainView.atEnd) { mainViewScrollAnim.from = mainView.contentX mainViewScrollAnim.to = Math.min(mainView.contentWidth - mainView.width, mainView.contentX + defaultColumnWidth) mainViewScrollAnim.running = true; } } else { if (mainView.contentX - mainView.originX > 0) { mainViewScrollAnim.from = mainView.contentX mainViewScrollAnim.to = Math.max(mainView.originX, mainView.contentX - defaultColumnWidth) mainViewScrollAnim.running = true; } } } /** * layers: QtQuick.Controls.PageStack * Access to the modal layers. * Sometimes an application needs a modal page that always covers all the rows. * For instance the full screen image of an image viewer or a settings page. * @since 5.38 */ property alias layers: layersStack //END FUNCTIONS onInitialPageChanged: { clear(); if (initialPage) { push(initialPage, null) } } Keys.forwardTo: [currentItem] SequentialAnimation { id: mainViewScrollAnim property real from property real to NumberAnimation { target: mainView properties: "contentX" duration: Units.longDuration from: mainViewScrollAnim.from to: mainViewScrollAnim.to } ScriptAction { script: mainView.flick(100, 0) } } QQC2.StackView { id: layersStack z: 99 anchors.fill: parent initialItem: mainView function clear () { //don't let it kill the main page row var d = root.depth; for (var i = 1; i < d; ++i) { pop(); } } } ListView { id: mainView boundsBehavior: Flickable.StopAtBounds orientation: Qt.Horizontal snapMode: ListView.SnapToItem currentIndex: root.currentIndex property int marginForLast: count > 1 ? pagesLogic.get(count-1).page.width - pagesLogic.get(count-1).width : 0 leftMargin: LayoutMirroring.enabled ? marginForLast : 0 rightMargin: LayoutMirroring.enabled ? 0 : marginForLast preferredHighlightBegin: 0 preferredHighlightEnd: 0 highlightMoveDuration: Units.longDuration highlightFollowsCurrentItem: true onMovementEnded: currentIndex = Math.max(0, indexAt(contentX, 0)) onFlickEnded: onMovementEnded(); onCurrentIndexChanged: currentItem.page.forceActiveFocus() model: ObjectModel { id: pagesLogic readonly property var componentCache: new Array() readonly property int roundedDefaultColumnWidth: root.width < root.defaultColumnWidth*2 ? root.width : root.defaultColumnWidth function removePage(id) { if (id < 0 || id >= count) { print("Tried to remove an invalid page index:" + id); return; } var item = pagesLogic.get(id); if (item.owner) { item.page.visible = false; item.page.parent = item.owner; } //FIXME: why reparent ing is necessary? //is destroy just an async deleteLater() that isn't executed immediately or it actually leaks? pagesLogic.remove(id); item.parent = root; if (item.page.parent==item) { item.page.destroy(1) } item.destroy(); } function clearPages () { popScrollAnim.running = false; popScrollAnim.pendingDepth = -1; while (count > 0) { removePage(count-1); } } function initPage(page, properties) { var container = containerComponent.createObject(mainView, { "level": pagesLogic.count, "page": page }); var pageComp; if (page.createObject) { // page defined as component pageComp = page; } else if (typeof page == "string") { // page defined as string (a url) pageComp = pagesLogic.componentCache[page]; if (!pageComp) { pageComp = pagesLogic.componentCache[page] = Qt.createComponent(page); } } if (pageComp) { if (pageComp.status == Component.Error) { throw new Error("Error while loading page: " + pageComp.errorString()); } else { // instantiate page from component page = pageComp.createObject(container.pageParent, properties || {}); } } else { // copy properties to the page for (var prop in properties) { if (properties.hasOwnProperty(prop)) { page[prop] = properties[prop]; } } } container.page = page; if (page.parent == null || page.parent == container.pageParent) { container.owner = null; } // the page has to be reparented if (page.parent != container) { page.parent = container; } return container; } function containsPage(page) { for (var i = 0; i < pagesLogic.count; ++i) { var candidate = pagesLogic.get(i); if (candidate.page == page) { print("The item " + page + " is already in the PageRow"); return; } } } } T.ScrollIndicator.horizontal: T.ScrollIndicator { anchors { left: parent.left right: parent.right bottom: parent.bottom } height: Units.smallSpacing contentItem: Rectangle { height: Units.smallSpacing width: Units.smallSpacing color: Theme.textColor opacity: 0 onXChanged: { opacity = 0.3 scrollIndicatorTimer.restart(); } Behavior on opacity { OpacityAnimator { duration: Units.longDuration easing.type: Easing.InOutQuad } } Timer { id: scrollIndicatorTimer interval: Units.longDuration * 4 onTriggered: parent.opacity = 0; } } } onContentWidthChanged: mainView.positionViewAtIndex(root.currentIndex, ListView.Contain) } Component { id: containerComponent MouseArea { id: container height: mainView.height width: root.width state: page ? (!root.wideMode ? "vertical" : (container.level >= pagesLogic.count - 1 ? "last" : "middle")) : ""; property int level readonly property int hint: page && page.implicitWidth ? page.implicitWidth : root.defaultColumnWidth readonly property int roundedHint: Math.floor(root.width/hint) > 0 ? root.width/Math.floor(root.width/hint) : root.width property Item page property Item owner onPageChanged: { if (page) { owner = page.parent; page.parent = container; page.anchors.fill = container; } } drag.filterChildren: true onClicked: root.currentIndex = level; onFocusChanged: { if (focus) { root.currentIndex = level; } } Separator { z: 999 anchors { top: parent.top bottom: parent.bottom left: parent.left } visible: root.separatorVisible && container.level > 0 } states: [ State { name: "vertical" PropertyChanges { target: container width: root.width } PropertyChanges { target: container.page ? container.page.anchors : null rightMargin: 0 } }, State { name: "last" PropertyChanges { target: container width: pagesLogic.roundedDefaultColumnWidth } PropertyChanges { target: container.page.anchors rightMargin: { return -(root.width - pagesLogic.roundedDefaultColumnWidth*2); } } }, State { name: "middle" PropertyChanges { target: container width: pagesLogic.roundedDefaultColumnWidth } PropertyChanges { target: container.page.anchors rightMargin: 0 } } ] } } } diff --git a/src/controls/ScrollablePage.qml b/src/controls/ScrollablePage.qml index c7c6e972..464e1b64 100644 --- a/src/controls/ScrollablePage.qml +++ b/src/controls/ScrollablePage.qml @@ -1,148 +1,151 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import "private" /** * ScrollablePage is a container for all the app pages: everything pushed to the * ApplicationWindow stackView should be a Page or ScrollablePage instabnce. * This Page subclass is for content that has to be scrolled around, such as * bigger content than the screen that would normally go in a Flickable * or a ListView. * Scrolling and scrolling indicators will be automatically managed * * * @code * ScrollablePage { * id: root * //The rectangle will automatically bescrollable * Rectangle { * width: root.width * height: 99999 * } * } * @endcode * * @code * ScrollablePage { * id: root * * //support for the popular "pull down to refresh" behavior in mobile apps * supportsRefreshing: true * * //The ListView will automatically receive proper scroll indicators * ListView { * model: myModel * delegate: BasicListItem { ... } * } * } * @endcode * */ Page { id: root /** * refreshing: bool * If true the list is asking for refresh and will show a loading spinner. * it will automatically be set to true when the user pulls down enough the list. * This signals the application logic to start its refresh procedure. * The application itself will have to set back this property to false when done. */ property alias refreshing: scrollView.refreshing /** * supportsRefreshing: bool * If true the list supports the "pull down to refresh" behavior. * default is false. */ property alias supportsRefreshing: scrollView.supportsRefreshing /** * flickable: Flickable * The main Flickable item of this page */ property alias flickable: scrollView.flickableItem /** * The main content Item of this page. * In the case of a ListView or GridView, both contentItem and flickable * will be a pointer to the ListView (or GridView) * NOTE: can't be contentItem as Page's contentItem is final */ default property QtObject mainItem /** * keyboardNavigationEnabled: bool * If true, and if flickable is an item view, like a ListView or * a GridView, it will be possible to navigate the list current item * to next and previous items with keyboard up/down arrow buttons. * Also, any key event will be forwarded to the current list item. * default is true. */ property bool keyboardNavigationEnabled: true + Theme.colorSet: flickable && flickable.hasOwnProperty("model") ? Theme.View : Theme.Window + RefreshableScrollView { id: scrollView z: 0 //child of root as it shouldn't have margins parent: root topPadding: (applicationWindow() && applicationWindow().header ? applicationWindow().header.preferredHeight : 0) + (contentItem == flickable ? 0 : root.topPadding) leftPadding: root.leftPadding rightPadding: root.rightPadding bottomPadding: contentItem == flickable ? 0 : root.bottomPadding anchors { fill: parent topMargin: root.header ? root.header.height : 0 bottomMargin: root.footer ? root.footer.height : 0 } } + anchors.topMargin: 0 Keys.forwardTo: root.keyboardNavigationEnabled && root.flickable ? (("currentItem" in root.flickable) && root.flickable.currentItem ? [ root.flickable.currentItem, root.flickable ] : [ root.flickable ]) : [] Item { id: overlay parent: root z: 9998 anchors.fill: parent property QtObject oldMainItem } //HACK to get the mainItem as the last one, all the other eventual items as an overlay //no idea if is the way the user expects onMainItemChanged: { if (mainItem.hasOwnProperty("anchors")) { scrollView.contentItem = mainItem //don't try to reparent drawers } else if (mainItem.hasOwnProperty("dragMargin")) { return; } if (overlay.oldMainItem && overlay.oldMainItem.hasOwnProperty("parent") && overlay.oldMainItem.parent != applicationWindow().overlay) { overlay.oldMainItem.parent = overlay } overlay.oldMainItem = mainItem } } diff --git a/src/controls/Separator.qml b/src/controls/Separator.qml index 8b97a310..99132f62 100644 --- a/src/controls/Separator.qml +++ b/src/controls/Separator.qml @@ -1,36 +1,36 @@ /* * Copyright 2012 Marco Martin * Copyright 2016 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 /** * A visual separator * * Useful for splitting one set of items from another. * * @inherit QtQuick.Rectangle */ Rectangle { height: Units.devicePixelRatio width: Units.devicePixelRatio - color: Qt.tint(Theme.textColor, Qt.rgba(Theme.viewBackgroundColor.r, Theme.viewBackgroundColor.g, Theme.viewBackgroundColor.b, 0.7)) + color: Qt.tint(Theme.textColor, Qt.rgba(Theme.backgroundColor.r, Theme.backgroundColor.g, Theme.backgroundColor.b, 0.7)) } diff --git a/src/controls/Theme.qml b/src/controls/Theme.qml index daba0eec..40fdad85 100644 --- a/src/controls/Theme.qml +++ b/src/controls/Theme.qml @@ -1,57 +1,77 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.4 -pragma Singleton +//pragma Singleton /** * A set of named colors for the application * @inherit QtQuick.QtObject */ QtObject { id: theme property color textColor: "#31363b" property color disabledTextColor: "#9931363b" property color highlightColor: "#2196F3" property color highlightedTextColor: "#eff0fa" property color backgroundColor: "#eff0f1" + property color activeTextColor: "#0176D3" property color linkColor: "#2196F3" property color visitedLinkColor: "#2196F3" + property color negativeTextColor: "#DA4453" + property color neutralTextColor: "#F67400" + property color positiveTextColor: "#27AE60" + property color buttonTextColor: "#31363b" property color buttonBackgroundColor: "#eff0f1" property color buttonHoverColor: "#2196F3" property color buttonFocusColor: "#2196F3" property color viewTextColor: "#31363b" property color viewBackgroundColor: "#fcfcfc" property color viewHoverColor: "#2196F3" property color viewFocusColor: "#2196F3" + property color selectionTextColor: "#eff0fa" + property color selectionBackgroundColor: "#2196F3" + property color selectionHoverColor: "#2196F3" + property color selectionFocusColor: "#2196F3" + + property color tooltipTextColor: "#eff0f1" + property color tooltipBackgroundColor: "#31363b" + property color tooltipHoverColor: "#2196F3" + property color tooltipFocusColor: "#2196F3" + + property color complementaryTextColor: "#eff0f1" + property color complementaryBackgroundColor: "#31363b" + property color complementaryHoverColor: "#2196F3" + property color complementaryFocusColor: "#2196F3" + property font defaultFont: fontMetrics.font property list children: [ TextMetrics { id: fontMetrics } ] } diff --git a/src/controls/ToolBarApplicationHeader.qml b/src/controls/ToolBarApplicationHeader.qml index 0a98b477..18e63ba5 100644 --- a/src/controls/ToolBarApplicationHeader.qml +++ b/src/controls/ToolBarApplicationHeader.qml @@ -1,158 +1,158 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 import "private" -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 /** * This Application header represents a toolbar that * will display the actions of the current page. * Both Contextual actions and the main, left and right actions */ ApplicationHeader { id: header preferredHeight: 38 maximumHeight: preferredHeight headerStyle: ApplicationHeaderStyle.Titles //FIXME: needs a property difinition to have its own type in qml property string _internal: "" pageDelegate: Item { id: delegateItem readonly property bool current: __appWindow.pageStack.currentIndex == index property Row layout //don't scroll except just the button implicitWidth: parent.parent.width - height width: parent.width height: parent.height Row { id: layout anchors.verticalCenter: parent.verticalCenter spacing: 2 Separator { anchors.verticalCenter: parent.verticalCenter height: parent.height * 0.6 visible: index > 0 } PrivateActionToolButton { anchors.verticalCenter: parent.verticalCenter action: page && page.actions ? page.actions.left : null showText: false } PrivateActionToolButton { anchors.verticalCenter: parent.verticalCenter action: page && page.actions ? page.actions.main : null showText: false } PrivateActionToolButton { anchors.verticalCenter: parent.verticalCenter action: page && page.actions ? page.actions.right : null showText: false } Separator { anchors.verticalCenter: parent.verticalCenter height: parent.height * 0.6 visible: page && page.actions && (page.actions.left || page.actions.main || page.actions.right) } Repeater { id: repeater model: page && page.actions.contextualActions ? page.actions.contextualActions : null delegate: PrivateActionToolButton { anchors.verticalCenter: parent.verticalCenter action: modelData visible: modelData.visible && x+layout.x+width < delegateItem.width onVisibleChanged: { if (!modelData.visible) { return; } if (!visible) { menu.visibleChildren++; } else { menu.visibleChildren = Math.max(0, menu.visibleChildren-1); } } } } } Heading { id: heading anchors.verticalCenter: parent.verticalCenter visible: layout.width <= 0 opacity: delegateItem.current ? 1 : 0.4 color: Theme.textColor elide: Text.ElideRight text: page ? page.title : "" font.pointSize: Math.max(1, (parent.height / 1.6) / Units.devicePixelRatio) } Controls.ToolButton { id: moreButton anchors { right: parent.right verticalCenter: parent.verticalCenter } //TODO: we need a kebab icon //iconName: "application-menu" Icon { anchors.fill: parent source: "application-menu" anchors.margins: 4 } checkable: true checked: menu.visible visible: menu.visibleChildren > 0 onClicked: menu.open() Controls.Menu { id: menu y: moreButton.height property int visibleChildren: 0 Repeater { model: page && page.actions.contextualActions ? page.actions.contextualActions : null delegate: Controls.MenuItem { text: modelData ? modelData.text : "" checkable: modelData.checkable //FIXME: icons //iconName: modelData.iconName onTriggered: modelData.trigger(); //skip the 3 buttons and 2 separators visible: modelData.visible height: visible ? implicitHeight : 0 enabled: modelData.enabled Component.onCompleted: { menu.addItem(this); menu.implicitWidth = Math.max(this.implicitWidth, menu.implicitWidth); } } } } } } } diff --git a/src/controls/Units.qml b/src/controls/Units.qml index 357a5c50..f3bdbc59 100644 --- a/src/controls/Units.qml +++ b/src/controls/Units.qml @@ -1,114 +1,114 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.4 import QtQuick.Window 2.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 pragma Singleton /** * A set of values to define semantically sizes and durations * @inherit QtQuick.QtObject */ QtObject { id: units /** * The fundamental unit of space that should be used for sizes, expressed in pixels. * Given the screen has an accurate DPI settings, it corresponds to a width of * the capital letter M */ property int gridUnit: fontMetrics.height /** * units.iconSizes provides access to platform-dependent icon sizing * * The icon sizes provided are normalized for different DPI, so icons * will scale depending on the DPI. * * Icon sizes from KIconLoader, adjusted to devicePixelRatio: * * small * * smallMedium * * medium * * large * * huge * * enormous * * Not devicePixelRation-adjusted:: * * desktop */ property QtObject iconSizes: QtObject { property int small: 16 * devicePixelRatio * (Settings.isMobile ? 1.5 : 1) property int smallMedium: 22 * devicePixelRatio * (Settings.isMobile ? 1.5 : 1) property int medium: 32 * devicePixelRatio * (Settings.isMobile ? 1.5 : 1) property int large: 48 * devicePixelRatio * (Settings.isMobile ? 1.5 : 1) property int huge: 64 * devicePixelRatio * (Settings.isMobile ? 1.5 : 1) property int enormous: 128 * devicePixelRatio * (Settings.isMobile ? 1.5 : 1) } /** * units.smallSpacing is the amount of spacing that should be used around smaller UI elements, * for example as spacing in Columns. Internally, this size depends on the size of * the default font as rendered on the screen, so it takes user-configured font size and DPI * into account. */ property int smallSpacing: Math.floor(gridUnit/4) /** * units.largeSpacing is the amount of spacing that should be used inside bigger UI elements, * for example between an icon and the corresponding text. Internally, this size depends on * the size of the default font as rendered on the screen, so it takes user-configured font * size and DPI into account. */ property int largeSpacing: gridUnit /** * The ratio between physical and device-independent pixels. This value does not depend on the \ * size of the configured font. If you want to take font sizes into account when scaling elements, * use theme.mSize(theme.defaultFont), units.smallSpacing and units.largeSpacing. * The devicePixelRatio follows the definition of "device independent pixel" by Microsoft. */ property real devicePixelRatio: Math.max(1, (fontMetrics.font.pixelSize / fontMetrics.font.pointSize)) /** * units.longDuration should be used for longer, screen-covering animations, for opening and * closing of dialogs and other "not too small" animations */ property int longDuration: 250 /** * units.shortDuration should be used for short animations, such as accentuating a UI event, * hover events, etc.. */ property int shortDuration: 150 /** * How much the mouse scroll wheel scrolls, expressed in lines of text. * Note: this is strictly for classical mouse wheels, touchpads 2 figer scrolling won't be affected */ readonly property int wheelScrollLines: 3 /** * metrics used by the default font */ property variant fontMetrics: TextMetrics { text: "M" } } diff --git a/src/controls/plugins.qmltypes b/src/controls/plugins.qmltypes index 457776a3..dba98e03 100644 --- a/src/controls/plugins.qmltypes +++ b/src/controls/plugins.qmltypes @@ -1,1599 +1,1598 @@ import QtQuick.tooling 1.2 // This file describes the plugin-supplied types contained in the library. // It is used for QML tooling purposes only. // // This file was auto-generated by: // 'qmlplugindump -noinstantiate -notrelocatable org.kde.kirigami 2.0 /opt/kde5/qml' Module { dependencies: [ "QtGraphicalEffects 1.0", "QtQml 2.1", "QtQml.Models 2.2", "QtQuick 2.9", "QtQuick.Controls 2.2", "QtQuick.Controls.Material 2.2", "QtQuick.Controls.Material.impl 2.2", "QtQuick.Controls.Styles 1.4", "QtQuick.Controls.Styles.Plasma 2.0", "QtQuick.Controls.Universal 2.2", "QtQuick.Controls.Universal.impl 2.2", "QtQuick.Controls.impl 2.2", "QtQuick.Extras 1.4", "QtQuick.Extras.Private.CppUtils 1.1", "QtQuick.Layouts 1.2", "QtQuick.Templates 2.2", "QtQuick.Window 2.3", "org.kde.kconfig 1.0", "org.kde.kquickcontrolsaddons 2.0", "org.kde.plasma.components 2.0", "org.kde.plasma.core 2.0", "org.kde.plasma.extras 2.0" ] Component { name: "ApplicationHeaderStyle" prototype: "QObject" exports: ["org.kde.kirigami/ApplicationHeaderStyle 2.0"] isCreatable: false exportMetaObjectRevisions: [0] Enum { name: "Status" values: { "Auto": 0, "Breadcrumb": 1, "Titles": 2, "TabBar": 3 } } } Component { name: "DesktopIcon" defaultProperty: "data" prototype: "QQuickItem" exports: ["org.kde.kirigami/Icon 2.0"] exportMetaObjectRevisions: [0] Property { name: "source"; type: "QVariant" } Property { name: "smooth"; type: "bool" } Property { name: "implicitWidth"; type: "int"; isReadonly: true } Property { name: "implicitHeight"; type: "int"; isReadonly: true } Property { name: "enabled"; type: "bool" } Property { name: "active"; type: "bool" } Property { name: "valid"; type: "bool"; isReadonly: true } Property { name: "selected"; type: "bool" } } Component { name: "Settings" prototype: "QObject" exports: ["org.kde.kirigami/Settings 2.0"] isCreatable: false isSingleton: true exportMetaObjectRevisions: [0] Property { name: "isMobile"; type: "bool"; isReadonly: true } Property { name: "style"; type: "string"; isReadonly: true } } Component { prototype: "QQuickItem" name: "org.kde.kirigami/AbstractApplicationHeader 2.0" exports: ["org.kde.kirigami/AbstractApplicationHeader 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentItem" Property { name: "minimumHeight"; type: "int" } Property { name: "preferredHeight"; type: "int" } Property { name: "maximumHeight"; type: "int" } Property { name: "paintedHeight"; type: "int"; isReadonly: true } Property { name: "__appWindow"; type: "QObject"; isPointer: true } Property { name: "background"; type: "QQuickItem"; isPointer: true } Property { name: "contentItem"; type: "QObject"; isList: true; isReadonly: true } } Component { prototype: "QQuickItem" name: "org.kde.kirigami/AbstractApplicationItem 2.1" exports: ["org.kde.kirigami/AbstractApplicationItem 2.1"] exportMetaObjectRevisions: [1] isComposite: true defaultProperty: "__data" Property { name: "pageStack"; type: "QQuickItem"; isPointer: true } Property { name: "activeFocusItem"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "header"; type: "QQuickItem"; isPointer: true } Property { name: "footer"; type: "QQuickItem"; isPointer: true } Property { name: "controlsVisible"; type: "bool" } Property { name: "globalDrawer"; type: "OverlayDrawer_QMLTYPE_8"; isPointer: true } Property { name: "wideScreen"; type: "bool" } Property { name: "contextDrawer"; type: "OverlayDrawer_QMLTYPE_8"; isPointer: true } Property { name: "reachableMode"; type: "bool" } Property { name: "reachableModeEnabled"; type: "bool" } Property { name: "contentItem"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "overlay"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "__data"; type: "QObject"; isList: true; isReadonly: true } Method { name: "showPassiveNotification" type: "QVariant" Parameter { name: "message"; type: "QVariant" } Parameter { name: "timeout"; type: "QVariant" } Parameter { name: "actionText"; type: "QVariant" } Parameter { name: "callBack"; type: "QVariant" } } Method { name: "hidePassiveNotification"; type: "QVariant" } Method { name: "applicationWindow"; type: "QVariant" } } Component { prototype: "QQuickApplicationWindow" name: "org.kde.kirigami/AbstractApplicationWindow 2.0" exports: ["org.kde.kirigami/AbstractApplicationWindow 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" Property { name: "pageStack"; type: "QQuickItem"; isPointer: true } Property { name: "controlsVisible"; type: "bool" } Property { name: "globalDrawer"; type: "OverlayDrawer_QMLTYPE_8"; isPointer: true } Property { name: "wideScreen"; type: "bool" } Property { name: "contextDrawer"; type: "OverlayDrawer_QMLTYPE_8"; isPointer: true } Property { name: "reachableMode"; type: "bool" } Property { name: "reachableModeEnabled"; type: "bool" } Method { name: "showPassiveNotification" type: "QVariant" Parameter { name: "message"; type: "QVariant" } Parameter { name: "timeout"; type: "QVariant" } Parameter { name: "actionText"; type: "QVariant" } Parameter { name: "callBack"; type: "QVariant" } } Method { name: "hidePassiveNotification"; type: "QVariant" } Method { name: "applicationWindow"; type: "QVariant" } } Component { prototype: "QQuickAbstractButton" name: "QtQuick.Controls/AbstractButton 2.0" exports: ["QtQuick.Controls/AbstractButton 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickControl" name: "org.kde.kirigami/AbstractItemViewHeader 2.1" exports: ["org.kde.kirigami/AbstractItemViewHeader 2.1"] exportMetaObjectRevisions: [1] isComposite: true defaultProperty: "data" Property { name: "minimumHeight"; type: "int" } Property { name: "maximumHeight"; type: "int" } Property { name: "view"; type: "QQuickListView"; isPointer: true } } Component { prototype: "QQuickItemDelegate" name: "org.kde.kirigami/AbstractListItem 2.0" exports: ["org.kde.kirigami/AbstractListItem 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "_default" Property { name: "supportsMouseEvents"; type: "bool" } Property { name: "sectionDelegate"; type: "bool" } Property { name: "separatorVisible"; type: "bool" } Property { name: "textColor"; type: "QColor" } Property { name: "backgroundColor"; type: "QColor" } Property { name: "activeTextColor"; type: "QColor" } Property { name: "activeBackgroundColor"; type: "QColor" } Property { name: "containsMouse"; type: "bool"; isReadonly: true } Property { name: "_default"; type: "QQuickItem"; isPointer: true } } Component { prototype: "QObject" name: "org.kde.kirigami/Action 2.0" exports: ["org.kde.kirigami/Action 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "children" Property { name: "visible"; type: "bool" } Property { name: "checkable"; type: "bool" } Property { name: "checked"; type: "bool" } Property { name: "enabled"; type: "bool" } Property { name: "iconName"; type: "string" } Property { name: "iconSource"; type: "string" } Property { name: "text"; type: "string" } Property { name: "tooltip"; type: "string" } Property { name: "__children"; type: "QObject"; isList: true; isReadonly: true } Property { name: "__shortcut"; type: "QQuickShortcut"; isPointer: true } Property { name: "shortcut"; type: "QVariant" } Property { name: "children"; type: "QObject"; isList: true; isReadonly: true } Signal { name: "toggled" Parameter { name: "checked"; type: "bool" } } Signal { name: "triggered" Parameter { name: "source"; type: "QObject"; isPointer: true } } Method { name: "trigger" type: "QVariant" Parameter { name: "source"; type: "QVariant" } } } Component { prototype: "QQuickItem" name: "org.kde.kirigami/ApplicationHeader 2.0" exports: ["org.kde.kirigami/ApplicationHeader 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentItem" Property { name: "headerStyle"; type: "int" } Property { name: "pageDelegate"; type: "QQmlComponent"; isPointer: true } Property { name: "minimumHeight"; type: "int" } Property { name: "preferredHeight"; type: "int" } Property { name: "maximumHeight"; type: "int" } Property { name: "paintedHeight"; type: "int"; isReadonly: true } Property { name: "__appWindow"; type: "QObject"; isPointer: true } Property { name: "background"; type: "QQuickItem"; isPointer: true } Property { name: "contentItem"; type: "QObject"; isList: true; isReadonly: true } } Component { prototype: "QQuickItem" name: "org.kde.kirigami/ApplicationItem 2.1" exports: ["org.kde.kirigami/ApplicationItem 2.1"] exportMetaObjectRevisions: [1] isComposite: true defaultProperty: "__data" Property { name: "pageStack"; type: "PageRow_QMLTYPE_35"; isReadonly: true; isPointer: true } Property { name: "activeFocusItem"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "header"; type: "QQuickItem"; isPointer: true } Property { name: "footer"; type: "QQuickItem"; isPointer: true } Property { name: "controlsVisible"; type: "bool" } Property { name: "globalDrawer"; type: "OverlayDrawer_QMLTYPE_8"; isPointer: true } Property { name: "wideScreen"; type: "bool" } Property { name: "contextDrawer"; type: "OverlayDrawer_QMLTYPE_8"; isPointer: true } Property { name: "reachableMode"; type: "bool" } Property { name: "reachableModeEnabled"; type: "bool" } Property { name: "contentItem"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "overlay"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "__data"; type: "QObject"; isList: true; isReadonly: true } Method { name: "showPassiveNotification" type: "QVariant" Parameter { name: "message"; type: "QVariant" } Parameter { name: "timeout"; type: "QVariant" } Parameter { name: "actionText"; type: "QVariant" } Parameter { name: "callBack"; type: "QVariant" } } Method { name: "hidePassiveNotification"; type: "QVariant" } Method { name: "applicationWindow"; type: "QVariant" } } Component { prototype: "QQuickApplicationWindow" name: "QtQuick.Controls/ApplicationWindow 2.0" exports: ["QtQuick.Controls/ApplicationWindow 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickApplicationWindow" name: "org.kde.kirigami/ApplicationWindow 2.0" exports: ["org.kde.kirigami/ApplicationWindow 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" Property { name: "pageStack"; type: "PageRow_QMLTYPE_35"; isReadonly: true; isPointer: true } Property { name: "controlsVisible"; type: "bool" } Property { name: "globalDrawer"; type: "OverlayDrawer_QMLTYPE_8"; isPointer: true } Property { name: "wideScreen"; type: "bool" } Property { name: "contextDrawer"; type: "OverlayDrawer_QMLTYPE_8"; isPointer: true } Property { name: "reachableMode"; type: "bool" } Property { name: "reachableModeEnabled"; type: "bool" } Method { name: "showPassiveNotification" type: "QVariant" Parameter { name: "message"; type: "QVariant" } Parameter { name: "timeout"; type: "QVariant" } Parameter { name: "actionText"; type: "QVariant" } Parameter { name: "callBack"; type: "QVariant" } } Method { name: "hidePassiveNotification"; type: "QVariant" } Method { name: "applicationWindow"; type: "QVariant" } } Component { prototype: "QQuickItemDelegate" name: "org.kde.kirigami/BasicListItem 2.0" exports: ["org.kde.kirigami/BasicListItem 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "_basicDefault" Property { name: "label"; type: "string" } Property { name: "icon"; type: "QVariant" } Property { name: "reserveSpaceForIcon"; type: "bool" } Property { name: "_basicDefault"; type: "QQuickItem"; isList: true; isReadonly: true } Property { name: "supportsMouseEvents"; type: "bool" } Property { name: "sectionDelegate"; type: "bool" } Property { name: "separatorVisible"; type: "bool" } Property { name: "textColor"; type: "QColor" } Property { name: "backgroundColor"; type: "QColor" } Property { name: "activeTextColor"; type: "QColor" } Property { name: "activeBackgroundColor"; type: "QColor" } Property { name: "containsMouse"; type: "bool"; isReadonly: true } Property { name: "_default"; type: "QQuickItem"; isPointer: true } } Component { prototype: "QQuickItem" name: "QtQuick.Controls.Material.impl/BoxShadow 2.0" exports: ["QtQuick.Controls.Material.impl/BoxShadow 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "offsetX"; type: "int" } Property { name: "offsetY"; type: "int" } Property { name: "blurRadius"; type: "int" } Property { name: "spreadRadius"; type: "int" } Property { name: "source"; type: "QQuickItem"; isPointer: true } Property { name: "fullWidth"; type: "bool" } Property { name: "fullHeight"; type: "bool" } Property { name: "glowRadius"; type: "double" } Property { name: "spread"; type: "double" } Property { name: "color"; type: "QColor" } Property { name: "cornerRadius"; type: "double" } Property { name: "cached"; type: "bool" } } Component { prototype: "QQuickBusyIndicator" name: "QtQuick.Controls/BusyIndicator 2.0" exports: ["QtQuick.Controls/BusyIndicator 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickButton" name: "QtQuick.Controls/Button 2.0" exports: ["QtQuick.Controls/Button 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickButtonGroup" name: "QtQuick.Controls/ButtonGroup 2.0" exports: ["QtQuick.Controls/ButtonGroup 2.0"] exportMetaObjectRevisions: [0] isComposite: true } Component { prototype: "QQuickCheckBox" name: "QtQuick.Controls/CheckBox 2.0" exports: ["QtQuick.Controls/CheckBox 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickCheckDelegate" name: "QtQuick.Controls/CheckDelegate 2.0" exports: ["QtQuick.Controls/CheckDelegate 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickRectangle" name: "QtQuick.Controls.impl/CheckIndicator 2.0" exports: ["QtQuick.Controls.impl/CheckIndicator 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "control"; type: "QQuickItem"; isPointer: true } } Component { prototype: "QQuickRectangle" name: "QtQuick.Controls.Universal.impl/CheckIndicator 2.0" exports: ["QtQuick.Controls.Universal.impl/CheckIndicator 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "control"; type: "QQuickItem"; isPointer: true } Property { name: "partiallyChecked"; type: "bool"; isReadonly: true } } Component { prototype: "QQuickRectangle" name: "QtQuick.Controls.Material.impl/CheckIndicator 2.0" exports: ["QtQuick.Controls.Material.impl/CheckIndicator 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "control"; type: "QQuickItem"; isPointer: true } } Component { prototype: "QQuickFocusScope" name: "QtQuick.Extras.Private/CircularButton 1.0" exports: ["QtQuick.Extras.Private/CircularButton 1.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "isDefault"; type: "bool" } Property { name: "menu"; type: "Menu_QMLTYPE_83"; isPointer: true } Property { name: "checkable"; type: "bool" } Property { name: "checked"; type: "bool" } Property { name: "exclusiveGroup"; type: "QQuickExclusiveGroup1"; isPointer: true } Property { name: "action"; type: "QQuickAction1"; isPointer: true } Property { name: "activeFocusOnPress"; type: "bool" } Property { name: "text"; type: "string" } Property { name: "tooltip"; type: "string" } Property { name: "iconSource"; type: "QUrl" } Property { name: "iconName"; type: "string" } Property { name: "__position"; type: "string" } Property { name: "__iconOverriden"; type: "bool"; isReadonly: true } Property { name: "__action"; type: "QQuickAction1"; isPointer: true } Property { name: "__iconAction"; type: "QQuickAction1"; isReadonly: true; isPointer: true } Property { name: "__behavior"; type: "QVariant" } Property { name: "__effectivePressed"; type: "bool" } Property { name: "pressed"; type: "bool"; isReadonly: true } Property { name: "hovered"; type: "bool"; isReadonly: true } Signal { name: "clicked" } Method { name: "accessiblePressAction"; type: "QVariant" } Property { name: "style"; type: "QQmlComponent"; isPointer: true } Property { name: "__style"; type: "QObject"; isPointer: true } Property { name: "__panel"; type: "QQuickItem"; isPointer: true } Property { name: "styleHints"; type: "QVariant" } Property { name: "__styleData"; type: "QObject"; isPointer: true } } Component { prototype: "QObject" name: "QtQuick.Extras.Private/CircularButtonStyleHelper 1.0" exports: ["QtQuick.Extras.Private/CircularButtonStyleHelper 1.0"] exportMetaObjectRevisions: [0] isComposite: true Property { name: "control"; type: "QQuickItem"; isPointer: true } Property { name: "buttonColorUpTop"; type: "QColor" } Property { name: "buttonColorUpBottom"; type: "QColor" } Property { name: "buttonColorDownTop"; type: "QColor" } Property { name: "buttonColorDownBottom"; type: "QColor" } Property { name: "outerArcColorTop"; type: "QColor" } Property { name: "outerArcColorBottom"; type: "QColor" } Property { name: "innerArcColorTop"; type: "QColor" } Property { name: "innerArcColorBottom"; type: "QColor" } Property { name: "innerArcColorBottomStop"; type: "double" } Property { name: "shineColor"; type: "QColor" } Property { name: "smallestAxis"; type: "double" } Property { name: "outerArcLineWidth"; type: "double" } Property { name: "innerArcLineWidth"; type: "double" } Property { name: "shineArcLineWidth"; type: "double" } Property { name: "implicitWidth"; type: "double" } Property { name: "implicitHeight"; type: "double" } Property { name: "textColorUp"; type: "QColor" } Property { name: "textColorDown"; type: "QColor" } Property { name: "textRaisedColorUp"; type: "QColor" } Property { name: "textRaisedColorDown"; type: "QColor" } Property { name: "radius"; type: "double" } Property { name: "halfRadius"; type: "double" } Property { name: "outerArcRadius"; type: "double" } Property { name: "innerArcRadius"; type: "double" } Property { name: "shineArcRadius"; type: "double" } Property { name: "zeroAngle"; type: "double" } Property { name: "buttonColorTop"; type: "QColor" } Property { name: "buttonColorBottom"; type: "QColor" } Method { name: "toPixels" type: "QVariant" Parameter { name: "percentageOfSmallestAxis"; type: "QVariant" } } Method { name: "paintBackground" type: "QVariant" Parameter { name: "ctx"; type: "QVariant" } } } Component { prototype: "QQuickFocusScope" name: "QtQuick.Extras/CircularGauge 1.0" exports: ["QtQuick.Extras/CircularGauge 1.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "tickmarksVisible"; type: "bool" } Property { name: "minimumValue"; type: "double" } Property { name: "maximumValue"; type: "double" } Property { name: "value"; type: "double" } Property { name: "stepSize"; type: "double" } Property { name: "style"; type: "QQmlComponent"; isPointer: true } Property { name: "__style"; type: "QObject"; isPointer: true } Property { name: "__panel"; type: "QQuickItem"; isPointer: true } Property { name: "styleHints"; type: "QVariant" } Property { name: "__styleData"; type: "QObject"; isPointer: true } } Component { prototype: "QQuickFocusScope" name: "QtQuick.Extras.Private/CircularTickmarkLabel 1.0" exports: ["QtQuick.Extras.Private/CircularTickmarkLabel 1.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "minimumValueAngle"; type: "double" } Property { name: "maximumValueAngle"; type: "double" } Property { name: "angleRange"; type: "double"; isReadonly: true } Property { name: "tickmarkStepSize"; type: "double" } Property { name: "tickmarkInset"; type: "double" } Property { name: "tickmarkCount"; type: "int"; isReadonly: true } Property { name: "minorTickmarkCount"; type: "int" } Property { name: "minorTickmarkInset"; type: "double" } Property { name: "labelInset"; type: "double" } Property { name: "labelStepSize"; type: "double" } Property { name: "labelCount"; type: "int"; isReadonly: true } Property { name: "__tickmarkCount"; type: "double"; isReadonly: true } Property { name: "tickmarksVisible"; type: "bool" } Property { name: "minimumValue"; type: "double" } Property { name: "maximumValue"; type: "double" } Property { name: "stepSize"; type: "double" } Method { name: "valueToAngle" type: "QVariant" Parameter { name: "value"; type: "QVariant" } } Property { name: "style"; type: "QQmlComponent"; isPointer: true } Property { name: "__style"; type: "QObject"; isPointer: true } Property { name: "__panel"; type: "QQuickItem"; isPointer: true } Property { name: "styleHints"; type: "QVariant" } Property { name: "__styleData"; type: "QObject"; isPointer: true } } Component { prototype: "QQuickComboBox" name: "QtQuick.Controls/ComboBox 2.0" exports: ["QtQuick.Controls/ComboBox 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickContainer" name: "QtQuick.Controls/Container 2.0" exports: ["QtQuick.Controls/Container 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickDrawer" name: "org.kde.kirigami/ContextDrawer 2.0" exports: ["org.kde.kirigami/ContextDrawer 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" Property { name: "title"; type: "string" } Property { name: "actions"; type: "QVariant" } Property { name: "drawerOpen"; type: "bool" } Property { name: "enabled"; type: "bool" } Property { name: "peeking"; type: "bool" } Property { name: "animating"; type: "bool"; isReadonly: true } Property { name: "handleVisible"; type: "bool" } Property { name: "handle"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "__internal"; type: "QObject"; isPointer: true } } Component { prototype: "QQuickControl" name: "QtQuick.Controls/Control 2.0" exports: ["QtQuick.Controls/Control 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickRectangle" name: "QtQuick.Controls.Material.impl/CursorDelegate 2.0" exports: ["QtQuick.Controls.Material.impl/CursorDelegate 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickFocusScope" name: "QtQuick.Extras/DelayButton 1.0" exports: ["QtQuick.Extras/DelayButton 1.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "delay"; type: "int" } Property { name: "__progress"; type: "double" } Property { name: "progress"; type: "double"; isReadonly: true } Signal { name: "activated" } Property { name: "isDefault"; type: "bool" } Property { name: "menu"; type: "Menu_QMLTYPE_83"; isPointer: true } Property { name: "checkable"; type: "bool" } Property { name: "checked"; type: "bool" } Property { name: "exclusiveGroup"; type: "QQuickExclusiveGroup1"; isPointer: true } Property { name: "action"; type: "QQuickAction1"; isPointer: true } Property { name: "activeFocusOnPress"; type: "bool" } Property { name: "text"; type: "string" } Property { name: "tooltip"; type: "string" } Property { name: "iconSource"; type: "QUrl" } Property { name: "iconName"; type: "string" } Property { name: "__position"; type: "string" } Property { name: "__iconOverriden"; type: "bool"; isReadonly: true } Property { name: "__action"; type: "QQuickAction1"; isPointer: true } Property { name: "__iconAction"; type: "QQuickAction1"; isReadonly: true; isPointer: true } Property { name: "__behavior"; type: "QVariant" } Property { name: "__effectivePressed"; type: "bool" } Property { name: "pressed"; type: "bool"; isReadonly: true } Property { name: "hovered"; type: "bool"; isReadonly: true } Signal { name: "clicked" } Method { name: "accessiblePressAction"; type: "QVariant" } Property { name: "style"; type: "QQmlComponent"; isPointer: true } Property { name: "__style"; type: "QObject"; isPointer: true } Property { name: "__panel"; type: "QQuickItem"; isPointer: true } Property { name: "styleHints"; type: "QVariant" } Property { name: "__styleData"; type: "QObject"; isPointer: true } } Component { prototype: "QQuickDelayButton" name: "QtQuick.Controls/DelayButton 2.2" exports: ["QtQuick.Controls/DelayButton 2.2"] exportMetaObjectRevisions: [2] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickFocusScope" name: "QtQuick.Extras/Dial 1.0" exports: ["QtQuick.Extras/Dial 1.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "__wrap"; type: "bool" } Property { name: "activeFocusOnPress"; type: "bool" } Property { name: "tickmarksVisible"; type: "bool" } Property { name: "value"; type: "double" } Property { name: "minimumValue"; type: "double" } Property { name: "maximumValue"; type: "double" } Property { name: "hovered"; type: "bool"; isReadonly: true } Property { name: "stepSize"; type: "double" } Property { name: "pressed"; type: "bool"; isReadonly: true } Property { name: "style"; type: "QQmlComponent"; isPointer: true } Property { name: "__style"; type: "QObject"; isPointer: true } Property { name: "__panel"; type: "QQuickItem"; isPointer: true } Property { name: "styleHints"; type: "QVariant" } Property { name: "__styleData"; type: "QObject"; isPointer: true } } Component { prototype: "QQuickFocusScope" name: "QtQuick.Extras/Dial 1.1" exports: ["QtQuick.Extras/Dial 1.1"] exportMetaObjectRevisions: [1] isComposite: true defaultProperty: "data" Property { name: "__wrap"; type: "bool" } Property { name: "activeFocusOnPress"; type: "bool" } Property { name: "tickmarksVisible"; type: "bool" } Property { name: "value"; type: "double" } Property { name: "minimumValue"; type: "double" } Property { name: "maximumValue"; type: "double" } Property { name: "hovered"; type: "bool"; isReadonly: true } Property { name: "stepSize"; type: "double" } Property { name: "pressed"; type: "bool"; isReadonly: true } Property { name: "style"; type: "QQmlComponent"; isPointer: true } Property { name: "__style"; type: "QObject"; isPointer: true } Property { name: "__panel"; type: "QQuickItem"; isPointer: true } Property { name: "styleHints"; type: "QVariant" } Property { name: "__styleData"; type: "QObject"; isPointer: true } } Component { prototype: "QQuickDial" name: "QtQuick.Controls/Dial 2.0" exports: ["QtQuick.Controls/Dial 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickDialog" name: "QtQuick.Controls/Dialog 2.1" exports: ["QtQuick.Controls/Dialog 2.1"] exportMetaObjectRevisions: [1] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickDialogButtonBox" name: "QtQuick.Controls/DialogButtonBox 2.1" exports: ["QtQuick.Controls/DialogButtonBox 2.1"] exportMetaObjectRevisions: [1] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickDrawer" name: "QtQuick.Controls/Drawer 2.0" exports: ["QtQuick.Controls/Drawer 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickItem" name: "QtQuick.Controls.Material.impl/ElevationEffect 2.0" exports: ["QtQuick.Controls.Material.impl/ElevationEffect 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "source"; type: "QVariant" } Property { name: "elevation"; type: "int" } Property { name: "fullWidth"; type: "bool" } Property { name: "fullHeight"; type: "bool" } Property { name: "sourceItem"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "_shadows"; type: "QVariant"; isReadonly: true } Property { name: "_shadow"; type: "QVariant"; isReadonly: true } } Component { prototype: "QQuickFrame" name: "QtQuick.Controls/Frame 2.0" exports: ["QtQuick.Controls/Frame 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickFocusScope" name: "QtQuick.Extras/Gauge 1.0" exports: ["QtQuick.Extras/Gauge 1.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "orientation"; type: "int" } Property { name: "tickmarkAlignment"; type: "int" } Property { name: "__tickmarkAlignment"; type: "int" } Property { name: "__tickmarksInside"; type: "bool" } Property { name: "tickmarkStepSize"; type: "double" } Property { name: "minorTickmarkCount"; type: "int" } Property { name: "formatValue"; type: "QVariant" } Property { name: "minimumValue"; type: "double" } Property { name: "value"; type: "double" } Property { name: "maximumValue"; type: "double" } Property { name: "font"; type: "QFont" } Property { name: "__hiddenText"; type: "QQuickText"; isReadonly: true; isPointer: true } Property { name: "style"; type: "QQmlComponent"; isPointer: true } Property { name: "__style"; type: "QObject"; isPointer: true } Property { name: "__panel"; type: "QQuickItem"; isPointer: true } Property { name: "styleHints"; type: "QVariant" } Property { name: "__styleData"; type: "QObject"; isPointer: true } } Component { prototype: "QQuickDrawer" name: "org.kde.kirigami/GlobalDrawer 2.0" exports: ["org.kde.kirigami/GlobalDrawer 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "content" Property { name: "actions"; type: "QObject"; isList: true; isReadonly: true } Property { name: "resetMenuOnTriggered"; type: "bool" } Property { name: "currentSubMenu"; type: "Action_QMLTYPE_26"; isReadonly: true; isPointer: true } Property { name: "title"; type: "string" } Property { name: "titleIcon"; type: "QVariant" } Property { name: "bannerImageSource"; type: "QUrl" } Property { name: "content"; type: "QObject"; isList: true; isReadonly: true } Property { name: "topContent"; type: "QObject"; isList: true; isReadonly: true } Signal { name: "bannerClicked" } Method { name: "resetMenu"; type: "QVariant" } Property { name: "drawerOpen"; type: "bool" } Property { name: "enabled"; type: "bool" } Property { name: "peeking"; type: "bool" } Property { name: "animating"; type: "bool"; isReadonly: true } Property { name: "handleVisible"; type: "bool" } Property { name: "handle"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "__internal"; type: "QObject"; isPointer: true } } Component { prototype: "QQuickGroupBox" name: "QtQuick.Controls/GroupBox 2.0" exports: ["QtQuick.Controls/GroupBox 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickLabel" name: "org.kde.kirigami/Heading 2.0" exports: ["org.kde.kirigami/Heading 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "level"; type: "int" } Property { name: "step"; type: "int" } Method { name: "headerPointSize" type: "QVariant" Parameter { name: "l"; type: "QVariant" } } } Component { prototype: "QQuickItemDelegate" name: "QtQuick.Controls/ItemDelegate 2.0" exports: ["QtQuick.Controls/ItemDelegate 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickControl" name: "org.kde.kirigami/ItemViewHeader 2.1" exports: ["org.kde.kirigami/ItemViewHeader 2.1"] exportMetaObjectRevisions: [1] isComposite: true defaultProperty: "data" Property { name: "title"; type: "string" } Property { name: "color"; type: "QColor" } Property { name: "backgroundImage"; type: "QQuickImage"; isReadonly: true; isPointer: true } Property { name: "minimumHeight"; type: "int" } Property { name: "maximumHeight"; type: "int" } Property { name: "view"; type: "QQuickListView"; isPointer: true } } Component { prototype: "QQuickLabel" name: "org.kde.kirigami/Label 2.0" exports: ["org.kde.kirigami/Label 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickLabel" name: "QtQuick.Controls/Label 2.0" exports: ["QtQuick.Controls/Label 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickMenu" name: "QtQuick.Controls/Menu 2.0" exports: ["QtQuick.Controls/Menu 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickMenuItem" name: "QtQuick.Controls/MenuItem 2.0" exports: ["QtQuick.Controls/MenuItem 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickMenuSeparator" name: "QtQuick.Controls/MenuSeparator 2.1" exports: ["QtQuick.Controls/MenuSeparator 2.1"] exportMetaObjectRevisions: [1] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickDrawer" name: "org.kde.kirigami/OverlayDrawer 2.0" exports: ["org.kde.kirigami/OverlayDrawer 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" Property { name: "drawerOpen"; type: "bool" } Property { name: "enabled"; type: "bool" } Property { name: "peeking"; type: "bool" } Property { name: "animating"; type: "bool"; isReadonly: true } Property { name: "handleVisible"; type: "bool" } Property { name: "handle"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "__internal"; type: "QObject"; isPointer: true } } Component { prototype: "QObject" name: "org.kde.kirigami/OverlaySheet 2.0" exports: ["org.kde.kirigami/OverlaySheet 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentItem" Property { name: "contentItem"; type: "QQuickItem"; isPointer: true } Property { name: "sheetOpen"; type: "bool" } Property { name: "leftPadding"; type: "int" } Property { name: "topPadding"; type: "int" } Property { name: "rightPadding"; type: "int" } Property { name: "bottomPadding"; type: "int" } Property { name: "background"; type: "QQuickItem"; isPointer: true } Property { name: "parent"; type: "QQuickItem"; isPointer: true } Property { name: "rootItem"; type: "QQuickItem"; isReadonly: true; isPointer: true } Method { name: "open"; type: "QVariant" } Method { name: "close"; type: "QVariant" } } Component { prototype: "QQuickPage" name: "QtQuick.Controls/Page 2.0" exports: ["QtQuick.Controls/Page 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickPage" name: "org.kde.kirigami/Page 2.0" exports: ["org.kde.kirigami/Page 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" Property { name: "flickable"; type: "QQuickFlickable"; isPointer: true } Property { name: "isCurrentPage"; type: "bool"; isReadonly: true } Property { name: "contextualActions"; type: "QObject"; isList: true; isReadonly: true } Property { name: "mainAction"; type: "QObject"; isPointer: true } Property { name: "leftAction"; type: "QObject"; isPointer: true } Property { name: "rightAction"; type: "QObject"; isPointer: true } Property { name: "actions" type: "PageActionPropertyGroup_QMLTYPE_29" isReadonly: true isPointer: true } Signal { name: "backRequested" Parameter { name: "event"; type: "QVariant" } } } Component { prototype: "QQuickPageIndicator" name: "QtQuick.Controls/PageIndicator 2.0" exports: ["QtQuick.Controls/PageIndicator 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickControl" name: "org.kde.kirigami/PageRow 2.0" exports: ["org.kde.kirigami/PageRow 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "depth"; type: "int"; isReadonly: true } Property { name: "lastItem"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "currentItem"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "initialPage"; type: "QVariant" } Property { name: "defaultColumnWidth"; type: "int" } Property { name: "wideMode"; type: "bool"; isReadonly: true } Property { name: "currentIndex"; type: "int" } Property { name: "interactive"; type: "bool" } Method { name: "push" type: "QVariant" Parameter { name: "page"; type: "QVariant" } Parameter { name: "properties"; type: "QVariant" } } Method { name: "pop" type: "QVariant" Parameter { name: "page"; type: "QVariant" } } Method { name: "replace" type: "QVariant" Parameter { name: "page"; type: "QVariant" } Parameter { name: "properties"; type: "QVariant" } } Method { name: "clear"; type: "QVariant" } Method { name: "get" type: "QVariant" Parameter { name: "idx"; type: "QVariant" } } Method { name: "flickBack"; type: "QVariant" } } Component { prototype: "QQuickPane" name: "QtQuick.Controls/Pane 2.0" exports: ["QtQuick.Controls/Pane 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickFocusScope" name: "QtQuick.Extras/PieMenu 1.0" exports: ["QtQuick.Extras/PieMenu 1.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "menuItems" Property { name: "selectionAngle"; type: "double"; isReadonly: true } Property { name: "triggerMode"; type: "int" } Property { name: "title"; type: "string" } Property { name: "boundingItem"; type: "QQuickItem"; isPointer: true } Property { name: "__protectedScope"; type: "QObject"; isPointer: true } Property { name: "activationMode"; type: "int" } Property { name: "menuItems"; type: "QQuickMenuItem1"; isList: true; isReadonly: true } Property { name: "currentIndex"; type: "int"; isReadonly: true } Property { name: "currentItem"; type: "QQuickMenuItem1"; isReadonly: true; isPointer: true } Property { name: "__mouseThief"; type: "QQuickMouseThief"; isReadonly: true; isPointer: true } Method { name: "popup" type: "QVariant" Parameter { name: "x"; type: "QVariant" } Parameter { name: "y"; type: "QVariant" } } Method { name: "addItem" type: "QVariant" Parameter { name: "text"; type: "QVariant" } } Method { name: "insertItem" type: "QVariant" Parameter { name: "before"; type: "QVariant" } Parameter { name: "text"; type: "QVariant" } } Method { name: "removeItem" type: "QVariant" Parameter { name: "item"; type: "QVariant" } } Property { name: "style"; type: "QQmlComponent"; isPointer: true } Property { name: "__style"; type: "QObject"; isPointer: true } Property { name: "__panel"; type: "QQuickItem"; isPointer: true } Property { name: "styleHints"; type: "QVariant" } Property { name: "__styleData"; type: "QObject"; isPointer: true } } Component { prototype: "QQuickLoader" name: "QtQuick.Extras.Private/PieMenuIcon 1.0" exports: ["QtQuick.Extras.Private/PieMenuIcon 1.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "control"; type: "PieMenu_QMLTYPE_165"; isPointer: true } Property { name: "styleData"; type: "QObject"; isPointer: true } Property { name: "iconSource"; type: "string"; isReadonly: true } } Component { prototype: "QQuickPopup" name: "QtQuick.Controls/Popup 2.0" exports: ["QtQuick.Controls/Popup 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickProgressBar" name: "QtQuick.Controls/ProgressBar 2.0" exports: ["QtQuick.Controls/ProgressBar 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickRadioButton" name: "QtQuick.Controls/RadioButton 2.0" exports: ["QtQuick.Controls/RadioButton 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickRadioDelegate" name: "QtQuick.Controls/RadioDelegate 2.0" exports: ["QtQuick.Controls/RadioDelegate 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickRectangle" name: "QtQuick.Controls.Universal.impl/RadioIndicator 2.0" exports: ["QtQuick.Controls.Universal.impl/RadioIndicator 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "control"; type: "QVariant" } } Component { prototype: "QQuickRectangle" name: "QtQuick.Controls.Material.impl/RadioIndicator 2.0" exports: ["QtQuick.Controls.Material.impl/RadioIndicator 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "control"; type: "QQuickItem"; isPointer: true } } Component { prototype: "QQuickRectangle" name: "QtQuick.Controls.impl/RadioIndicator 2.0" exports: ["QtQuick.Controls.impl/RadioIndicator 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "control"; type: "QQuickItem"; isPointer: true } } Component { prototype: "QQuickRangeSlider" name: "QtQuick.Controls/RangeSlider 2.0" exports: ["QtQuick.Controls/RangeSlider 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickItem" name: "QtQuick.Controls.Material.impl/RectangularGlow 2.0" exports: ["QtQuick.Controls.Material.impl/RectangularGlow 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "glowRadius"; type: "double" } Property { name: "spread"; type: "double" } Property { name: "color"; type: "QColor" } Property { name: "cornerRadius"; type: "double" } Property { name: "cached"; type: "bool" } } Component { prototype: "QQuickRoundButton" name: "QtQuick.Controls/RoundButton 2.1" exports: ["QtQuick.Controls/RoundButton 2.1"] exportMetaObjectRevisions: [1] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickScrollBar" name: "QtQuick.Controls/ScrollBar 2.0" exports: ["QtQuick.Controls/ScrollBar 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickScrollIndicator" name: "QtQuick.Controls/ScrollIndicator 2.0" exports: ["QtQuick.Controls/ScrollIndicator 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickScrollView" name: "QtQuick.Controls/ScrollView 2.2" exports: ["QtQuick.Controls/ScrollView 2.2"] exportMetaObjectRevisions: [2] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickPage" name: "org.kde.kirigami/ScrollablePage 2.0" exports: ["org.kde.kirigami/ScrollablePage 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "mainItem" Property { name: "mainItem"; type: "QObject"; isPointer: true } Property { name: "keyboardNavigationEnabled"; type: "bool" } Property { name: "refreshing"; type: "bool" } Property { name: "supportsRefreshing"; type: "bool" } Property { name: "flickable"; type: "QQuickFlickable"; isPointer: true } Property { name: "isCurrentPage"; type: "bool"; isReadonly: true } Property { name: "contextualActions"; type: "QObject"; isList: true; isReadonly: true } Property { name: "mainAction"; type: "QObject"; isPointer: true } Property { name: "leftAction"; type: "QObject"; isPointer: true } Property { name: "rightAction"; type: "QObject"; isPointer: true } Property { name: "actions" type: "PageActionPropertyGroup_QMLTYPE_29" isReadonly: true isPointer: true } Signal { name: "backRequested" Parameter { name: "event"; type: "QVariant" } } } Component { prototype: "QQuickRectangle" name: "org.kde.kirigami/Separator 2.0" exports: ["org.kde.kirigami/Separator 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickSlider" name: "QtQuick.Controls/Slider 2.0" exports: ["QtQuick.Controls/Slider 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickItem" name: "QtQuick.Controls.Material.impl/SliderHandle 2.0" exports: ["QtQuick.Controls.Material.impl/SliderHandle 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "value"; type: "double" } Property { name: "handleHasFocus"; type: "bool" } Property { name: "handlePressed"; type: "bool" } Property { name: "handleHovered"; type: "bool" } Property { name: "initialSize"; type: "int"; isReadonly: true } Property { name: "horizontal"; type: "bool"; isReadonly: true } Property { name: "control"; type: "QVariant"; isReadonly: true } } Component { prototype: "QQuickSpinBox" name: "QtQuick.Controls/SpinBox 2.0" exports: ["QtQuick.Controls/SpinBox 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickStackView" name: "QtQuick.Controls/StackView 2.0" exports: ["QtQuick.Controls/StackView 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickFocusScope" name: "QtQuick.Extras/StatusIndicator 1.1" exports: ["QtQuick.Extras/StatusIndicator 1.1"] exportMetaObjectRevisions: [1] isComposite: true defaultProperty: "data" Property { name: "active"; type: "bool" } Property { name: "color"; type: "QColor" } Property { name: "on"; type: "bool" } Property { name: "style"; type: "QQmlComponent"; isPointer: true } Property { name: "__style"; type: "QObject"; isPointer: true } Property { name: "__panel"; type: "QQuickItem"; isPointer: true } Property { name: "styleHints"; type: "QVariant" } Property { name: "__styleData"; type: "QObject"; isPointer: true } } Component { prototype: "QQuickFocusScope" name: "QtQuick.Extras/StatusIndicator 1.0" exports: ["QtQuick.Extras/StatusIndicator 1.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "active"; type: "bool" } Property { name: "color"; type: "QColor" } Property { name: "on"; type: "bool" } Property { name: "style"; type: "QQmlComponent"; isPointer: true } Property { name: "__style"; type: "QObject"; isPointer: true } Property { name: "__panel"; type: "QQuickItem"; isPointer: true } Property { name: "styleHints"; type: "QVariant" } Property { name: "__styleData"; type: "QObject"; isPointer: true } } Component { prototype: "QQuickSwipeDelegate" name: "QtQuick.Controls/SwipeDelegate 2.0" exports: ["QtQuick.Controls/SwipeDelegate 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickItemDelegate" name: "org.kde.kirigami/SwipeListItem 2.0" exports: ["org.kde.kirigami/SwipeListItem 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "_default" Property { name: "sectionDelegate"; type: "bool" } Property { name: "separatorVisible"; type: "bool" } Property { name: "actions"; type: "Action_QMLTYPE_26"; isList: true; isReadonly: true } Property { name: "textColor"; type: "QColor" } Property { name: "backgroundColor"; type: "QColor" } Property { name: "activeTextColor"; type: "QColor" } Property { name: "activeBackgroundColor"; type: "QColor" } Property { name: "supportsMouseEvents"; type: "bool" } Property { name: "containsMouse"; type: "bool"; isReadonly: true } Property { name: "_default"; type: "QQuickItem"; isPointer: true } } Component { prototype: "QQuickSwipeView" name: "QtQuick.Controls/SwipeView 2.0" exports: ["QtQuick.Controls/SwipeView 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickSwitch" name: "QtQuick.Controls/Switch 2.0" exports: ["QtQuick.Controls/Switch 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickSwitchDelegate" name: "QtQuick.Controls/SwitchDelegate 2.0" exports: ["QtQuick.Controls/SwitchDelegate 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickItem" name: "QtQuick.Controls.Material.impl/SwitchIndicator 2.0" exports: ["QtQuick.Controls.Material.impl/SwitchIndicator 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "control"; type: "QQuickItem"; isPointer: true } Property { name: "handle"; type: "QQuickRectangle"; isReadonly: true; isPointer: true } } Component { prototype: "QQuickItem" name: "QtQuick.Controls.Universal.impl/SwitchIndicator 2.0" exports: ["QtQuick.Controls.Universal.impl/SwitchIndicator 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "control"; type: "QQuickItem"; isPointer: true } } Component { prototype: "QQuickItem" name: "QtQuick.Controls.impl/SwitchIndicator 2.0" exports: ["QtQuick.Controls.impl/SwitchIndicator 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "control"; type: "QQuickItem"; isPointer: true } } Component { prototype: "QQuickTabBar" name: "QtQuick.Controls/TabBar 2.0" exports: ["QtQuick.Controls/TabBar 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickTabButton" name: "QtQuick.Controls/TabButton 2.0" exports: ["QtQuick.Controls/TabButton 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickTextArea" name: "QtQuick.Controls/TextArea 2.0" exports: ["QtQuick.Controls/TextArea 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickTextField" name: "QtQuick.Controls/TextField 2.0" exports: ["QtQuick.Controls/TextField 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickText" name: "QtQuick.Extras.Private/TextSingleton 1.0" exports: ["QtQuick.Extras.Private/TextSingleton 1.0"] exportMetaObjectRevisions: [0] isComposite: true isCreatable: false isSingleton: true defaultProperty: "data" } Component { prototype: "QObject" name: "org.kde.kirigami/Theme 2.0" exports: ["org.kde.kirigami/Theme 2.0"] exportMetaObjectRevisions: [0] isComposite: true isCreatable: false - isSingleton: true Property { name: "textColor"; type: "QColor" } Property { name: "disabledTextColor"; type: "QColor" } Property { name: "highlightColor"; type: "QColor" } Property { name: "highlightedTextColor"; type: "QColor" } Property { name: "backgroundColor"; type: "QColor" } Property { name: "linkColor"; type: "QColor" } Property { name: "visitedLinkColor"; type: "QColor" } Property { name: "buttonTextColor"; type: "QColor" } Property { name: "buttonBackgroundColor"; type: "QColor" } Property { name: "buttonHoverColor"; type: "QColor" } Property { name: "buttonFocusColor"; type: "QColor" } Property { name: "viewTextColor"; type: "QColor" } Property { name: "viewBackgroundColor"; type: "QColor" } Property { name: "viewHoverColor"; type: "QColor" } Property { name: "viewFocusColor"; type: "QColor" } Property { name: "defaultFont"; type: "QFont" } Property { name: "children"; type: "QObject"; isList: true; isReadonly: true } } Component { prototype: "QQuickFocusScope" name: "QtQuick.Extras/ToggleButton 1.0" exports: ["QtQuick.Extras/ToggleButton 1.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" Property { name: "isDefault"; type: "bool" } Property { name: "menu"; type: "Menu_QMLTYPE_83"; isPointer: true } Property { name: "checkable"; type: "bool" } Property { name: "checked"; type: "bool" } Property { name: "exclusiveGroup"; type: "QQuickExclusiveGroup1"; isPointer: true } Property { name: "action"; type: "QQuickAction1"; isPointer: true } Property { name: "activeFocusOnPress"; type: "bool" } Property { name: "text"; type: "string" } Property { name: "tooltip"; type: "string" } Property { name: "iconSource"; type: "QUrl" } Property { name: "iconName"; type: "string" } Property { name: "__position"; type: "string" } Property { name: "__iconOverriden"; type: "bool"; isReadonly: true } Property { name: "__action"; type: "QQuickAction1"; isPointer: true } Property { name: "__iconAction"; type: "QQuickAction1"; isReadonly: true; isPointer: true } Property { name: "__behavior"; type: "QVariant" } Property { name: "__effectivePressed"; type: "bool" } Property { name: "pressed"; type: "bool"; isReadonly: true } Property { name: "hovered"; type: "bool"; isReadonly: true } Signal { name: "clicked" } Method { name: "accessiblePressAction"; type: "QVariant" } Property { name: "style"; type: "QQmlComponent"; isPointer: true } Property { name: "__style"; type: "QObject"; isPointer: true } Property { name: "__panel"; type: "QQuickItem"; isPointer: true } Property { name: "styleHints"; type: "QVariant" } Property { name: "__styleData"; type: "QObject"; isPointer: true } } Component { prototype: "QQuickToolBar" name: "QtQuick.Controls/ToolBar 2.0" exports: ["QtQuick.Controls/ToolBar 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickItem" name: "org.kde.kirigami/ToolBarApplicationHeader 2.0" exports: ["org.kde.kirigami/ToolBarApplicationHeader 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentItem" Property { name: "_internal"; type: "string" } Property { name: "headerStyle"; type: "int" } Property { name: "pageDelegate"; type: "QQmlComponent"; isPointer: true } Property { name: "minimumHeight"; type: "int" } Property { name: "preferredHeight"; type: "int" } Property { name: "maximumHeight"; type: "int" } Property { name: "paintedHeight"; type: "int"; isReadonly: true } Property { name: "__appWindow"; type: "QObject"; isPointer: true } Property { name: "background"; type: "QQuickItem"; isPointer: true } Property { name: "contentItem"; type: "QObject"; isList: true; isReadonly: true } } Component { prototype: "QQuickToolButton" name: "QtQuick.Controls/ToolButton 2.0" exports: ["QtQuick.Controls/ToolButton 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickToolSeparator" name: "QtQuick.Controls/ToolSeparator 2.1" exports: ["QtQuick.Controls/ToolSeparator 2.1"] exportMetaObjectRevisions: [1] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickToolTip" name: "QtQuick.Controls/ToolTip 2.0" exports: ["QtQuick.Controls/ToolTip 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "contentData" } Component { prototype: "QQuickTumbler" name: "QtQuick.Controls/Tumbler 2.0" exports: ["QtQuick.Controls/Tumbler 2.0"] exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" } Component { prototype: "QQuickFocusScope" name: "QtQuick.Extras/Tumbler 1.2" exports: ["QtQuick.Extras/Tumbler 1.2"] exportMetaObjectRevisions: [2] isComposite: true defaultProperty: "data" Property { name: "__highlightMoveDuration"; type: "int" } Property { name: "columnCount"; type: "int"; isReadonly: true } Property { name: "__columnRow"; type: "QQuickRow"; isReadonly: true; isPointer: true } Property { name: "__movementDelayTimer"; type: "QQmlTimer"; isReadonly: true; isPointer: true } Method { name: "__isValidColumnIndex" type: "QVariant" Parameter { name: "index"; type: "QVariant" } } Method { name: "__isValidColumnAndItemIndex" type: "QVariant" Parameter { name: "columnIndex"; type: "QVariant" } Parameter { name: "itemIndex"; type: "QVariant" } } Method { name: "currentIndexAt" type: "QVariant" Parameter { name: "columnIndex"; type: "QVariant" } } Method { name: "setCurrentIndexAt" type: "QVariant" Parameter { name: "columnIndex"; type: "QVariant" } Parameter { name: "itemIndex"; type: "QVariant" } Parameter { name: "interval"; type: "QVariant" } } Method { name: "getColumn" type: "QVariant" Parameter { name: "columnIndex"; type: "QVariant" } } Method { name: "addColumn" type: "QVariant" Parameter { name: "column"; type: "QVariant" } } Method { name: "insertColumn" type: "QVariant" Parameter { name: "index"; type: "QVariant" } Parameter { name: "column"; type: "QVariant" } } Method { name: "__viewAt" type: "QVariant" Parameter { name: "index"; type: "QVariant" } } Property { name: "style"; type: "QQmlComponent"; isPointer: true } Property { name: "__style"; type: "QObject"; isPointer: true } Property { name: "__panel"; type: "QQuickItem"; isPointer: true } Property { name: "styleHints"; type: "QVariant" } Property { name: "__styleData"; type: "QObject"; isPointer: true } } Component { prototype: "QObject" name: "QtQuick.Extras/TumblerColumn 1.2" exports: ["QtQuick.Extras/TumblerColumn 1.2"] exportMetaObjectRevisions: [2] isComposite: true Property { name: "__tumbler"; type: "QQuickItem"; isPointer: true } Property { name: "__index"; type: "int" } Property { name: "__currentIndex"; type: "int" } Property { name: "model"; type: "QVariant" } Property { name: "role"; type: "string" } Property { name: "delegate"; type: "QQmlComponent"; isPointer: true } Property { name: "highlight"; type: "QQmlComponent"; isPointer: true } Property { name: "columnForeground"; type: "QQmlComponent"; isPointer: true } Property { name: "visible"; type: "bool" } Property { name: "activeFocus"; type: "bool"; isReadonly: true } Property { name: "width"; type: "double" } Property { name: "currentIndex"; type: "int"; isReadonly: true } } Component { prototype: "QObject" name: "org.kde.kirigami/Units 2.0" exports: ["org.kde.kirigami/Units 2.0"] exportMetaObjectRevisions: [0] isComposite: true isCreatable: false isSingleton: true Property { name: "gridUnit"; type: "int" } Property { name: "iconSizes"; type: "QObject"; isPointer: true } Property { name: "smallSpacing"; type: "int" } Property { name: "largeSpacing"; type: "int" } Property { name: "devicePixelRatio"; type: "double" } Property { name: "longDuration"; type: "int" } Property { name: "shortDuration"; type: "int" } Property { name: "__styleItem"; type: "QObject"; isReadonly: true; isPointer: true } Property { name: "wheelScrollLines"; type: "int"; isReadonly: true } Property { name: "fontMetrics"; type: "QVariant" } } } diff --git a/src/controls/private/ActionButton.qml b/src/controls/private/ActionButton.qml index ddbf2303..c668124c 100644 --- a/src/controls/private/ActionButton.qml +++ b/src/controls/private/ActionButton.qml @@ -1,439 +1,441 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.2 import QtGraphicalEffects 1.0 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import "../templates/private" Item { id: root + Theme.colorSet: Theme.Button + Theme.inherit: false anchors { left: parent.left right: parent.right bottom: parent.bottom bottomMargin: root.parent.parent.footer ? root.parent.parent.footer.height : 0 } //smallSpacing for the shadow height: button.height + Units.smallSpacing clip: true //either Action or QAction should work here readonly property QtObject action: root.parent.parent ? root.parent.parent.mainAction : null readonly property QtObject leftAction: root.parent.parent ? root.parent.parent.leftAction : null readonly property QtObject rightAction: root.parent.parent ? root.parent.parent.rightAction : null transform: Translate { id: translateTransform y: mouseArea.internalVisibility ? 0 : button.height Behavior on y { NumberAnimation { duration: Units.longDuration easing.type: mouseArea.internalVisibility == true ? Easing.InQuad : Easing.OutQuad } } } Item { id: button x: root.width/2 - button.width/2 anchors { bottom: parent.bottom bottomMargin: Units.smallSpacing } implicitWidth: implicitHeight + Units.iconSizes.smallMedium*2 + Units.gridUnit implicitHeight: Units.iconSizes.medium + Units.largeSpacing onXChanged: { if (mouseArea.pressed || edgeMouseArea.pressed || fakeContextMenuButton.pressed) { if (globalDrawer && globalDrawer.enabled && globalDrawer.modal) { globalDrawer.peeking = true; globalDrawer.visible = true; globalDrawer.position = Math.min(1, Math.max(0, (x - root.width/2 + button.width/2)/globalDrawer.contentItem.width + mouseArea.drawerShowAdjust)); } if (contextDrawer && contextDrawer.enabled && contextDrawer.modal) { contextDrawer.peeking = true; contextDrawer.visible = true; contextDrawer.position = Math.min(1, Math.max(0, (root.width/2 - button.width/2 - x)/contextDrawer.contentItem.width + mouseArea.drawerShowAdjust)); } } } MouseArea { id: mouseArea anchors.fill: parent visible: action != null || leftAction != null || rightAction != null property bool internalVisibility: (applicationWindow === undefined || (applicationWindow().controlsVisible && applicationWindow().height > root.height*2)) && (root.action === null || root.action.visible === undefined || root.action.visible) preventStealing: true drag { target: button //filterChildren: true axis: Drag.XAxis minimumX: contextDrawer && contextDrawer.enabled && contextDrawer.modal ? 0 : root.width/2 - button.width/2 maximumX: globalDrawer && globalDrawer.enabled && globalDrawer.modal ? root.width : root.width/2 - button.width/2 } property var downTimestamp; property int startX property int startMouseY property real drawerShowAdjust property bool buttonPressedUnderMouse: false property bool leftButtonPressedUnderMouse: false property bool rightButtonPressedUnderMouse: false onPressed: { //search if we have a page to set to current if (applicationWindow !== undefined && applicationWindow().pageStack.currentIndex !== undefined && root.parent.parent.parent.level !== undefined) { //search the button parent's parent, that is the page parent //this will make the context drawer open for the proper page applicationWindow().pageStack.currentIndex = root.parent.parent.parent.level; } downTimestamp = (new Date()).getTime(); startX = button.x + button.width/2; startMouseY = mouse.y; drawerShowAdjust = 0; buttonPressedUnderMouse = mouse.x > buttonGraphics.x && mouse.x < buttonGraphics.x + buttonGraphics.width; leftButtonPressedUnderMouse = !buttonPressedUnderMouse && leftAction && mouse.x < buttonGraphics.x; rightButtonPressedUnderMouse = !buttonPressedUnderMouse && rightAction && mouse.x > buttonGraphics.x + buttonGraphics.width; } onReleased: { if (globalDrawer) globalDrawer.peeking = false; if (contextDrawer) contextDrawer.peeking = false; //pixel/second var x = button.x + button.width/2; var speed = ((x - startX) / ((new Date()).getTime() - downTimestamp) * 1000); drawerShowAdjust = 0; //project where it would be a full second in the future if (globalDrawer && globalDrawer.modal && x + speed > Math.min(root.width/4*3, root.width/2 + globalDrawer.contentItem.width/2)) { globalDrawer.open(); contextDrawer.close(); } else if (contextDrawer && x + speed < Math.max(root.width/4, root.width/2 - contextDrawer.contentItem.width/2)) { if (contextDrawer && contextDrawer.modal) { contextDrawer.open(); } if (globalDrawer && globalDrawer.modal) { globalDrawer.close(); } } else { if (globalDrawer && globalDrawer.modal) { globalDrawer.close(); } if (contextDrawer && contextDrawer.modal) { contextDrawer.close(); } } //Don't rely on native onClicked, but fake it here: //Qt.startDragDistance is not adapted to devices dpi in case //of Android, so consider the button "clicked" when: //*the button has been dragged less than a gridunit //*the finger is still on the button if (Math.abs((button.x + button.width/2) - startX) < Units.gridUnit && mouse.y > 0) { var action; if (buttonPressedUnderMouse) { action = root.action; } else if (leftButtonPressedUnderMouse) { action = root.leftAction; } else if (rightButtonPressedUnderMouse) { action = root.rightAction; } if (!action) { return; } //if an action has been assigned, trigger it if (action && action.trigger) { action.trigger(); } } } onPositionChanged: { drawerShowAdjust = Math.min(0.3, Math.max(0, (startMouseY - mouse.y)/(Units.gridUnit*15))); button.xChanged(); } onPressAndHold: { var action; if (buttonPressedUnderMouse) { action = root.action; } else if (leftButtonPressedUnderMouse) { action = root.leftAction; } else if (rightButtonPressedUnderMouse) { action = root.rightAction; } if (!action) { return; } //if an action has been assigned, show a message like a tooltip if (action && action.text) { showPassiveNotification(action.text); } } Connections { target: globalDrawer onPositionChanged: { if ( globalDrawer && globalDrawer.modal && !mouseArea.pressed && !edgeMouseArea.pressed && !fakeContextMenuButton.pressed) { button.x = globalDrawer.contentItem.width * globalDrawer.position + root.width/2 - button.width/2; } } } Connections { target: contextDrawer onPositionChanged: { if (contextDrawer && contextDrawer.modal && !mouseArea.pressed && !edgeMouseArea.pressed && !fakeContextMenuButton.pressed) { button.x = root.width/2 - button.width/2 - contextDrawer.contentItem.width * contextDrawer.position; } } } Item { id: background anchors { fill: parent } Rectangle { id: buttonGraphics radius: width/2 anchors.centerIn: parent height: parent.height - Units.smallSpacing*2 width: height visible: root.action readonly property bool pressed: root.action && ((mouseArea.buttonPressedUnderMouse && mouseArea.pressed) || root.action.checked) - color: pressed ? Qt.lighter(Theme.buttonHoverColor, 1.3) : Theme.buttonHoverColor + color: pressed ? Qt.lighter(Theme.hoverColor, 1.3) : Theme.hoverColor Icon { id: icon source: root.action && root.action.iconName ? root.action.iconName : "" selected: true anchors { fill: parent margins: Units.smallSpacing * 3 } } Behavior on color { ColorAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } Behavior on x { NumberAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } } //left button Rectangle { id: leftButtonGraphics z: -1 anchors { left: parent.left //verticalCenter: parent.verticalCenter bottom: parent.bottom bottomMargin: Units.smallSpacing } radius: Units.devicePixelRatio*2 height: Units.iconSizes.smallMedium + Units.smallSpacing * 2 width: height + (root.action ? Units.gridUnit*2 : 0) visible: root.leftAction readonly property bool pressed: root.leftAction && ((mouseArea.leftButtonPressedUnderMouse && mouseArea.pressed) || root.leftAction.checked) - color: pressed ? Theme.buttonHoverColor : Theme.buttonBackgroundColor + color: pressed ? Theme.hoverColor : Theme.backgroundColor Behavior on color { ColorAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } Icon { source: root.leftAction && root.leftAction.iconName ? root.leftAction.iconName : "" width: height selected: leftButtonGraphics.pressed anchors { left: parent.left top: parent.top bottom: parent.bottom margins: Units.smallSpacing * 2 } } } //right button Rectangle { id: rightButtonGraphics z: -1 anchors { right: parent.right //verticalCenter: parent.verticalCenter bottom: parent.bottom bottomMargin: Units.smallSpacing } radius: Units.devicePixelRatio*2 height: Units.iconSizes.smallMedium + Units.smallSpacing * 2 width: height + (root.action ? Units.gridUnit*2 : 0) visible: root.rightAction readonly property bool pressed: root.rightAction && ((mouseArea.rightButtonPressedUnderMouse && mouseArea.pressed) || root.rightAction.checked) - color: pressed ? Theme.buttonHoverColor : Theme.buttonBackgroundColor + color: pressed ? Theme.hoverColor : Theme.backgroundColor Behavior on color { ColorAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } Icon { source: root.rightAction && root.rightAction.iconName ? root.rightAction.iconName : "" width: height selected: rightButtonGraphics.pressed anchors { right: parent.right top: parent.top bottom: parent.bottom margins: Units.smallSpacing * 2 } } } } DropShadow { anchors.fill: background horizontalOffset: 0 verticalOffset: Units.devicePixelRatio radius: Units.gridUnit /2 samples: 16 color: Qt.rgba(0, 0, 0, mouseArea.pressed ? 0.6 : 0.4) source: background } } } MouseArea { id: fakeContextMenuButton anchors { right: edgeMouseArea.right bottom: edgeMouseArea.bottom } drag { target: button axis: Drag.XAxis minimumX: contextDrawer && contextDrawer.enabled && contextDrawer.modal ? 0 : root.width/2 - button.width/2 maximumX: globalDrawer && globalDrawer.enabled && globalDrawer.modal ? root.width : root.width/2 - button.width/2 } visible: root.parent.parent.actions.contextualActions.length > 0 && (applicationWindow === undefined || applicationWindow().wideScreen) //using internal pagerow api && root.parent.parent.parent.level < applicationWindow().pageStack.depth-1 width: Units.iconSizes.medium + Units.smallSpacing*2 height: width Item { anchors { fill:parent margins: -Units.gridUnit } DropShadow { anchors.fill: handleGraphics horizontalOffset: 0 verticalOffset: Units.devicePixelRatio radius: Units.gridUnit /2 samples: 16 color: Qt.rgba(0, 0, 0, fakeContextMenuButton.pressed ? 0.6 : 0.4) source: handleGraphics } Rectangle { id: handleGraphics anchors.centerIn: parent - color: fakeContextMenuButton.pressed ? Theme.highlightColor : Theme.buttonBackgroundColor + color: fakeContextMenuButton.pressed ? Theme.highlightColor : Theme.backgroundColor width: Units.iconSizes.smallMedium + Units.smallSpacing * 2 height: width radius: Units.devicePixelRatio ContextIcon { anchors.centerIn: parent width: height height: Units.iconSizes.smallMedium - color: fakeContextMenuButton.pressed ? Theme.highlightedTextColor : Theme.buttonTextColor + color: fakeContextMenuButton.pressed ? Theme.highlightedTextColor : Theme.textColor } Behavior on color { ColorAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } } } onPressed: mouseArea.onPressed(mouse) onReleased: { if (globalDrawer) { globalDrawer.peeking = false; } if (contextDrawer) { contextDrawer.peeking = false; } var pos = root.mapFromItem(fakeContextMenuButton, mouse.x, mouse.y); if (contextDrawer) { if (pos.x < root.width/2 || (!contextDrawer.drawerOpen && mouse.x > 0 && mouse.x < width)) { contextDrawer.open(); } else if (contextDrawer.drawerOpen && mouse.x > 0 && mouse.x < width) { contextDrawer.close(); } } if (globalDrawer) { if (globalDrawer.position > 0.5) { globalDrawer.open(); } else { globalDrawer.close(); } } } } MouseArea { id: edgeMouseArea z:99 anchors { left: parent.left right: parent.right bottom: parent.bottom } drag { target: button //filterChildren: true axis: Drag.XAxis minimumX: contextDrawer && contextDrawer.enabled && contextDrawer.modal ? 0 : root.width/2 - button.width/2 maximumX: globalDrawer && globalDrawer.enabled && globalDrawer.modal ? root.width : root.width/2 - button.width/2 } height: Units.smallSpacing * 3 onPressed: mouseArea.onPressed(mouse) onPositionChanged: mouseArea.positionChanged(mouse) onReleased: mouseArea.released(mouse) } } diff --git a/src/controls/private/CornerShadow.qml b/src/controls/private/CornerShadow.qml index 44ccc2a5..cd5185c8 100644 --- a/src/controls/private/CornerShadow.qml +++ b/src/controls/private/CornerShadow.qml @@ -1,72 +1,72 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtGraphicalEffects 1.0 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 RadialGradient { id: shadow /** * corner: enumeration * This property holds the corner of the shadow that will determine * the direction of the gradient. * The acceptable values are: * Qt.TopLeftCorner, TopRightCorner, BottomLeftCorner, BottomRightCorner */ property int corner: Qt.TopRightCorner width: Units.gridUnit/2 height: Units.gridUnit/2 horizontalOffset: { switch (corner) { case Qt.TopLeftCorner: case Qt.BottomLeftCorner: return -width/2; default: return width/2; } } verticalOffset: { switch (corner) { case Qt.TopLeftCorner: case Qt.TopRightCorner: return -width/2; default: return width/2; } } gradient: Gradient { GradientStop { position: 0.0 color: Qt.rgba(0, 0, 0, 0.2) } GradientStop { position: 0.3 color: Qt.rgba(0, 0, 0, 0.1) } GradientStop { position: 1.0 color: "transparent" } } } diff --git a/src/controls/private/DefaultListItemBackground.qml b/src/controls/private/DefaultListItemBackground.qml index 865460c3..a9c48794 100644 --- a/src/controls/private/DefaultListItemBackground.qml +++ b/src/controls/private/DefaultListItemBackground.qml @@ -1,59 +1,59 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 Rectangle { id: background color: listItem.checked || (listItem.pressed && !listItem.checked && !listItem.sectionDelegate) ? (internal.indicateActiveFocus ? listItem.activeBackgroundColor : Qt.tint(listItem.backgroundColor, Qt.rgba(listItem.activeBackgroundColor.r, listItem.activeBackgroundColor.g, listItem.activeBackgroundColor.b, 0.3))) : listItem.backgroundColor visible: listItem.ListView.view ? listItem.ListView.view.highlight === null : true Rectangle { id: internal - property bool indicateActiveFocus: Settings.isMobile || listItem.activeFocus || (listItem.ListView.view ? listItem.ListView.view.activeFocus : false) + property bool indicateActiveFocus: listItem.pressed || Settings.isMobile || listItem.activeFocus || (listItem.ListView.view ? listItem.ListView.view.activeFocus : false) anchors.fill: parent visible: !Settings.isMobile color: listItem.activeBackgroundColor opacity: (listItem.hovered || (listItem.highlighted && indicateActiveFocus)) && !listItem.pressed ? 0.2 : 0 Behavior on opacity { NumberAnimation { duration: Units.longDuration } } } Behavior on color { ColorAnimation { duration: Units.longDuration } } readonly property bool _firstElement: typeof(index) !== "undefined" && index == 0 on_FirstElementChanged: { if (_firstElement) { - var newObject = Qt.createQmlObject('import QtQuick 2.0; import org.kde.kirigami 2.0; Separator {anchors {left: parent.left; right: parent.right; bottom: parent.top} visible: listItem.separatorVisible}', + var newObject = Qt.createQmlObject('import QtQuick 2.0; import org.kde.kirigami 2.2; Separator {anchors {left: parent.left; right: parent.right; bottom: parent.top} visible: listItem.separatorVisible}', background); } } Separator { anchors { left: parent.left right: parent.right bottom: parent.bottom } visible: listItem.separatorVisible } } diff --git a/src/controls/private/EdgeShadow.qml b/src/controls/private/EdgeShadow.qml index 1c3e4329..0a4f0e07 100644 --- a/src/controls/private/EdgeShadow.qml +++ b/src/controls/private/EdgeShadow.qml @@ -1,58 +1,58 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtGraphicalEffects 1.0 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 LinearGradient { id: shadow /** * edge: enumeration * This property holds the edge of the shadow that will determine * the direction of the gradient. * The acceptable values are: * Qt.TopEdge: The top edge of the content item. * Qt.LeftEdge: The left edge of the content item (default). * Qt.RightEdge: The right edge of the content item. * Qt.BottomEdge: The bottom edge of the content item. */ property int edge: Qt.LeftEdge width: Units.gridUnit/2 height: Units.gridUnit/2 start: Qt.point((edge != Qt.RightEdge ? 0 : width), (edge != Qt.BottomEdge ? 0 : height)) end: Qt.point((edge != Qt.LeftEdge ? 0 : width), (edge != Qt.TopEdge ? 0 : height)) gradient: Gradient { GradientStop { position: 0.0 color: Qt.rgba(0, 0, 0, 0.2) } GradientStop { position: 0.3 color: Qt.rgba(0, 0, 0, 0.1) } GradientStop { position: 1.0 color: "transparent" } } } diff --git a/src/controls/private/PrivateActionToolButton.qml b/src/controls/private/PrivateActionToolButton.qml index 98494b84..60bee4e7 100644 --- a/src/controls/private/PrivateActionToolButton.qml +++ b/src/controls/private/PrivateActionToolButton.qml @@ -1,74 +1,74 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.6 import QtQuick.Layouts 1.2 import QtQuick.Controls 2.0 as Controls -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 Controls.ToolButton { id: control implicitWidth: Math.max(background.implicitWidth, layout.implicitWidth + 16) implicitHeight: background.implicitHeight hoverEnabled: true property Action action property bool showText: true //we need our own text delegate text: "" checkable: action && action.checkable checked: action && action.checked enabled: action && action.enabled opacity: enabled ? 1 : 0.4 visible: action && action.visible onClicked: { if (action) { action.trigger(); } } flat: true contentItem: MouseArea { hoverEnabled: true onPressed: mouse.accepted = false RowLayout { id: layout anchors.centerIn: parent Icon { Layout.minimumWidth: 22 Layout.minimumHeight: 22 source: control.action ? control.action.iconName : "" visible: control.action && control.action.iconName != "" } Label { text: action ? action.text : "" visible: control.showText } } } Controls.ToolTip { visible: control.hovered text: action ? (action.tooltip.length ? action.tooltip : action.text) : "" delay: 1000 timeout: 5000 y: control.height } } diff --git a/src/controls/private/RefreshableScrollView.qml b/src/controls/private/RefreshableScrollView.qml index bd535122..9c8cd198 100644 --- a/src/controls/private/RefreshableScrollView.qml +++ b/src/controls/private/RefreshableScrollView.qml @@ -1,284 +1,284 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import QtQuick.Controls 2.0 as QQC2 import QtGraphicalEffects 1.0 import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import "../templates/private" as P /** * RefreshableScrollView is a scroll view for any Flickable that supports the * "scroll down to refresh" behavior, and also allows the contents of the * flickable to have more top margins in order to make possible to scroll down the list * to reach it with the thumb while using the phone with a single hand. * * Example usage: * * @code - * import org.kde.kirigami 2.0 as Kirigami + * import org.kde.kirigami 2.2 as Kirigami * [...] * * Kirigami.RefreshableScrollView { * id: view * supportsRefreshing: true * onRefreshingChanged: { * if (refreshing) { * myModel.refresh(); * } * } * ListView { * //NOTE: MyModel doesn't come from the components, * //it's purely an example on how it can be used together * //some application logic that can update the list model * //and signals when it's done. * model: MyModel { * onRefreshDone: view.refreshing = false; * } * delegate: BasicListItem {} * } * } * [...] * * @endcode * */ P.ScrollView { id: root /** * type: bool * If true the list is asking for refresh and will show a loading spinner. * it will automatically be set to true when the user pulls down enough the list. * This signals the application logic to start its refresh procedure. * The application itself will have to set back this property to false when done. */ property bool refreshing: false /** * type: bool * If true the list supports the "pull down to refresh" behavior. */ property bool supportsRefreshing: false /** * leftPadding: int * default contents padding at left */ property int leftPadding: Units.gridUnit /** * topPadding: int * default contents padding at top */ property int topPadding: Units.gridUnit /** * rightPadding: int * default contents padding at right */ property int rightPadding: Units.gridUnit /** * bottomPadding: int * default contents padding at bottom */ property int bottomPadding: Units.gridUnit property Item _swipeFilter children: [ Item { id: busyIndicatorFrame z: 99 y: root.flickableItem.verticalLayoutDirection === ListView.BottomToTop ? -root.flickableItem.contentY+height : -root.flickableItem.contentY-height width: root.flickableItem.width height: busyIndicator.height + Units.gridUnit * 2 QQC2.BusyIndicator { id: busyIndicator anchors.centerIn: parent running: root.refreshing visible: root.refreshing //Android busywidget QQC seems to be broken at custom sizes } property int headerItemHeight: (root.flickableItem.headerItem ? (root.flickableItem.headerItem.maximumHeight ? root.flickableItem.headerItem.maximumHeight : root.flickableItem.headerItem.height) : 0) Rectangle { id: spinnerProgress anchors { fill: busyIndicator margins: Math.ceil(Units.smallSpacing/2) } radius: width visible: supportsRefreshing && !refreshing && progress > 0 color: "transparent" opacity: 0.8 - border.color: Theme.viewBackgroundColor + border.color: Theme.backgroundColor border.width: Math.ceil(Units.smallSpacing/4) //also take into account the listview header height if present property real progress: supportsRefreshing && !refreshing ? ((parent.y - busyIndicatorFrame.headerItemHeight)/busyIndicatorFrame.height) : 0 } ConicalGradient { source: spinnerProgress visible: spinnerProgress.visible anchors.fill: spinnerProgress gradient: Gradient { GradientStop { position: 0.00; color: Theme.highlightColor } GradientStop { position: spinnerProgress.progress; color: Theme.highlightColor } GradientStop { position: spinnerProgress.progress + 0.01; color: "transparent" } GradientStop { position: 1.00; color: "transparent" } } } onYChanged: { //it's overshooting enough and not reachable: start countdown for reachability if (y - busyIndicatorFrame.headerItemHeight > root.topPadding + Units.gridUnit && !applicationWindow().reachableMode) { overshootResetTimer.running = true; //not reachable and not overshooting enough, stop reachability countdown } else if (!applicationWindow().reachableMode) { //it's important it doesn't restart overshootResetTimer.running = false; } if (!supportsRefreshing) { return; } //also take into account the listview header height if present if (!root.refreshing && y - busyIndicatorFrame.headerItemHeight > busyIndicatorFrame.height/2 + topPadding) { refreshTriggerTimer.running = true; } else { refreshTriggerTimer.running = false; } } Timer { id: refreshTriggerTimer interval: 500 onTriggered: { //also take into account the listview header height if present if (!root.refreshing && parent.y - busyIndicatorFrame.headerItemHeight > busyIndicatorFrame.height/2 + topPadding) { root.refreshing = true; } } } Connections { target: applicationWindow() onReachableModeChanged: { overshootResetTimer.running = applicationWindow().reachableMode; } } Timer { id: overshootResetTimer interval: applicationWindow().reachableMode ? 8000 : 2000 onTriggered: { //put it there because widescreen may have changed since timer start if (!Settings.isMobile || applicationWindow().wideScreen || root.flickableItem.verticalLayoutDirection === ListView.BottomToTop) { return; } applicationWindow().reachableMode = !applicationWindow().reachableMode; } } Binding { target: root.flickableItem property: "topMargin" value: !Settings.isMobile || applicationWindow().wideScreen ? (root.refreshing ? busyIndicatorFrame.height : 0) : Math.max(Math.max(root.topPadding - busyIndicatorFrame.headerItemHeight, 0) + (root.refreshing ? busyIndicatorFrame.height : 0), (applicationWindow().header ? applicationWindow().header.height : 0)) } Binding { target: root.flickableItem property: "flickableDirection" value: Flickable.VerticalFlick } Binding { target: root.flickableItem property: "bottomMargin" value: Units.gridUnit * 5 } Binding { target: root.contentItem property: "width" value: root.flickableItem.width } } ] onHeightChanged: { if (!applicationWindow() || !applicationWindow().activeFocusItem) { return; } //NOTE: there is no function to know if an item is descended from another, //so we have to walk the parent hyerarchy by hand var isDescendent = false; var candidate = applicationWindow().activeFocusItem.parent; while (candidate) { if (candidate == root) { isDescendent = true; break; } candidate = candidate.parent; } if (!isDescendent) { return; } var cursorY = 0; if (applicationWindow().activeFocusItem.cursorPosition !== undefined) { cursorY = applicationWindow().activeFocusItem.positionToRectangle(applicationWindow().activeFocusItem.cursorPosition).y; } var pos = applicationWindow().activeFocusItem.mapToItem(root.contentItem, 0, cursorY); //focused item alreqady visible? add some margin for the space of the action buttons if (pos.y >= root.flickableItem.contentY && pos.y <= root.flickableItem.contentY + root.flickableItem.height - Units.gridUnit * 8) { return; } root.flickableItem.contentY = pos.y; } onLeftPaddingChanged: { //for gridviews do apply margins if (root.contentItem == root.flickableItem) { if (typeof root.flickableItem.cellWidth != "undefined") { flickableItem.anchors.leftMargin = leftPadding; flickableItem.anchors.rightMargin = rightPadding; } else { flickableItem.anchors.leftMargin = 0; flickableItem.anchors.rightMargin = 0; } flickableItem.anchors.rightMargin = 0; flickableItem.anchors.bottomMargin = 0; } else { flickableItem.anchors.leftMargin = leftPadding; flickableItem.anchors.topMargin = topPadding; flickableItem.anchors.rightMargin = rightPadding; flickableItem.anchors.bottomMargin = bottomPadding; } } } diff --git a/src/controls/private/SwipeItemEventFilter.qml b/src/controls/private/SwipeItemEventFilter.qml index 89734303..6685d109 100644 --- a/src/controls/private/SwipeItemEventFilter.qml +++ b/src/controls/private/SwipeItemEventFilter.qml @@ -1,42 +1,42 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 MouseArea { id: swipeFilter anchors { right: parent.right top: parent.top bottom: parent.bottom } z: 99999 property Item currentItem property real peek width: Units.gridUnit onPositionChanged: { var mapped = mapToItem(parent.flickableItem.contentItem, mouse.x, mouse.y); currentItem = parent.flickableItem.itemAt(mapped.x, mapped.y) peek = 1 - mapped.x / parent.flickableItem.contentItem.width } } diff --git a/src/controls/templates/AbstractApplicationHeader.qml b/src/controls/templates/AbstractApplicationHeader.qml index 6a825600..63fb071f 100644 --- a/src/controls/templates/AbstractApplicationHeader.qml +++ b/src/controls/templates/AbstractApplicationHeader.qml @@ -1,192 +1,192 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import QtQuick.Layouts 1.2 import "private" -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 /** * An item that can be used as a title for the application. * Scrolling the main page will make it taller or shorter (trough the point of going away) * It's a behavior similar to the typical mobile web browser adressbar * the minimum, preferred and maximum heights of the item can be controlled with * * minimumHeight: default is 0, i.e. hidden * * preferredHeight: default is Units.gridUnit * 1.6 * * preferredHeight: default is Units.gridUnit * 3 * * To achieve a titlebar that stays completely fixed just set the 3 sizes as the same * @inherit QtQuick.Item */ Item { id: root z: 90 property int minimumHeight: 0 property int preferredHeight: Units.gridUnit * 2 property int maximumHeight: Units.gridUnit * 3 default property alias contentItem: mainItem.data readonly property int paintedHeight: headerItem.y + headerItem.height - 1 LayoutMirroring.enabled: Qt.application.layoutDirection == Qt.RightToLeft LayoutMirroring.childrenInherit: true //FIXME: remove property QtObject __appWindow: applicationWindow(); anchors { left: parent.left right: parent.right } height: { if (!__appWindow.controlsVisible) { return 1; } else if (__appWindow.wideScreen || !Settings.isMobile) { return preferredHeight; } else { return 1; } } /** * background: Item * This property holds the background item. * Note: the background will be automatically sized as the whole control */ property Item background onBackgroundChanged: { background.z = -1; background.parent = headerItem; background.anchors.fill = headerItem; } opacity: height > 0 && -translateTransform.y <= height ? 1 : 0 Behavior on opacity { OpacityAnimator { duration: Units.longDuration easing.type: Easing.InOutQuad } } transform: Translate { id: translateTransform y: { if (__appWindow === undefined) { return 0; } if (!__appWindow.controlsVisible) { return -headerItem.height - Units.smallSpacing; } else { return 0; } } Behavior on y { NumberAnimation { duration: Units.longDuration easing.type: translateTransform.y < 0 ? Easing.OutQuad : Easing.InQuad } } } Item { id: headerItem anchors { left: parent.left right: parent.right } height: __appWindow.reachableMode && __appWindow.reachableModeEnabled ? root.maximumHeight : root.preferredHeight function updatePageHeader() { if (!__appWindow || !__appWindow.pageStack || !__appWindow.pageStack.currentItem || !__appWindow.pageStack.currentItem.header || !__appWindow.pageStack.currentItem.flickable) { return; } if (__appWindow.wideScreen || !Settings.isMobile) { __appWindow.pageStack.currentItem.header.y = 0; } else { __appWindow.pageStack.currentItem.header.y = headerItem.height + headerItem.y -1; } } onYChanged: updatePageHeader() onHeightChanged: updatePageHeader() Connections { id: headerSlideConnection target: __appWindow.pageStack.currentItem ? __appWindow.pageStack.currentItem.flickable : null property int oldContentY onContentYChanged: { if (!__appWindow.pageStack.currentItem) { return; } if (__appWindow.pageStack.currentItem.flickable.atYBeginning || __appWindow.pageStack.currentItem.flickable.atYEnd) { return; } if (__appWindow.wideScreen || !Settings.isMobile) { headerItem.y = 0; } else { headerItem.y = Math.max(root.minimumHeight - root.preferredHeight, Math.min(0, headerItem.y + oldContentY - __appWindow.pageStack.currentItem.flickable.contentY)); oldContentY = __appWindow.pageStack.currentItem.flickable.contentY; } } onMovementEnded: { if (headerItem.y > root.preferredHeight) { //if don't change the position if more then preferredSize is shown } else if (headerItem.y < -(root.preferredHeight - root.minimumHeight)/2 ) { headerItem.y = root.minimumHeight - root.preferredHeight; } else { headerItem.y = 0; } } } Connections { target: __appWindow.pageStack onCurrentItemChanged: { if (!__appWindow.pageStack.currentItem) { return; } if (__appWindow.pageStack.currentItem.flickable) { headerSlideConnection.oldContentY = __appWindow.pageStack.currentItem.flickable.contentY; } else { headerSlideConnection.oldContentY = 0; } headerItem.y = 0; headerItem.updatePageHeader() } } Item { id: mainItem anchors { fill: parent } } Behavior on y { enabled: __appWindow.pageStack.currentItem && __appWindow.pageStack.currentItem.flickable && !__appWindow.pageStack.currentItem.flickable.moving NumberAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } } } diff --git a/src/controls/templates/AbstractListItem.qml b/src/controls/templates/AbstractListItem.qml index 49dc4d2d..2ec04454 100644 --- a/src/controls/templates/AbstractListItem.qml +++ b/src/controls/templates/AbstractListItem.qml @@ -1,120 +1,121 @@ /* * Copyright 2010 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.0 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import QtQuick.Templates 2.0 as T2 /** * An item delegate for the primitive ListView component. * * It's intended to make all listviews look coherent. * * @inherit QtQuick.Templates.ItemDelegate */ T2.ItemDelegate { id: listItem /** * supportsMouseEvents: bool * Holds if the item emits signals related to mouse interaction. *TODO: remove * The default value is false. */ property bool supportsMouseEvents: hoverEnabled /** * containsMouse: bool * True when the user hover the mouse over the list item * NOTE: on mobile touch devices this will be true only when pressed is also true * TODO: remove? */ property alias containsMouse: listItem.hovered /** * sectionDelegate: bool * If true the item will be a delegate for a section, so will look like a * "title" for the items under it. */ property bool sectionDelegate: false /** * separatorVisible: bool * True if the separator between items is visible * default: true */ property bool separatorVisible: true /** * textColor: color * Color for the text in the item - * It is advised to leave the default value (Theme.viewTextColor) + * It is advised to leave the default value (Theme.textColor) * * Note: if custom text elements are inserted in an AbstractListItem, * their color proprty will ahve to be manually binded with this property */ - property color textColor: Theme.viewTextColor + property color textColor: Theme.textColor /** * backgroundColor: color * Color for the background of the item * It is advised to leave the default value (Theme.viewBackgroundColor) */ - property color backgroundColor: Theme.viewBackgroundColor + property color backgroundColor: Theme.backgroundColor /** * activeTextColor: color * Color for the text in the item when pressed or selected * It is advised to leave the default value (Theme.highlightedTextColor) * * Note: if custom text elements are inserted in an AbstractListItem, * their color proprty will ahve to be manually binded with this property */ property color activeTextColor: Theme.highlightedTextColor /** * activeBackgroundColor: color * Color for the background of the item when pressed or selected * It is advised to leave the default value (Theme.highlightColor) */ property color activeBackgroundColor: Theme.highlightColor default property alias _default: listItem.contentItem + Theme.colorSet: Theme.View leftPadding: Units.smallSpacing * 2 topPadding: Units.smallSpacing * 2 rightPadding: Units.smallSpacing * 2 bottomPadding: Units.smallSpacing * 2 implicitWidth: contentItem ? contentItem.implicitWidth : Units.gridUnit * 12 implicitHeight: contentItem.implicitHeight + Units.smallSpacing * 5 width: parent ? parent.width : implicitWidth Layout.fillWidth: true opacity: enabled ? 1 : 0.6 height: visible ? implicitHeight : 0 hoverEnabled: true - Accessible.role: Accessible.MenuItem + Accessible.role: Accessible.ListItem } diff --git a/src/controls/templates/ApplicationHeader.qml b/src/controls/templates/ApplicationHeader.qml index f327dc4f..33635323 100644 --- a/src/controls/templates/ApplicationHeader.qml +++ b/src/controls/templates/ApplicationHeader.qml @@ -1,282 +1,282 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import QtQuick.Controls 2.0 as QQC2 import QtQuick.Layouts 1.2 import "private" -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 /** * An item that can be used as a title for the application. * Scrolling the main page will make it taller or shorter (trough the point of going away) * It's a behavior similar to the typical mobile web browser adressbar * the minimum, preferred and maximum heights of the item can be controlled with * * minimumHeight: default is 0, i.e. hidden * * preferredHeight: default is Units.gridUnit * 1.6 * * maximumHeight: default is Units.gridUnit * 3 * * To achieve a titlebar that stays completely fixed just set the 3 sizes as the same */ AbstractApplicationHeader { id: header /** * headerStyle: string * The way the separator between pages should be drawn in the header. * Allowed values are: * * Breadcrumb: the pages are hyerarchical and the separator will look like a > * * TabBar: the pages are intended to behave like tabbar pages * and the separator will look limke a dot. * * When the heaer is in wide screen mode, no separator will be drawn. */ property int headerStyle: ApplicationHeaderStyle.Auto /** * backButtonEnabled: bool * if true, there will be a back button present that will make the pagerow scroll back when clicked */ property bool backButtonEnabled: (!titleList.isTabBar && (!Settings.isMobile || Qt.platform.os == "ios")) onBackButtonEnabledChanged: { if (backButtonEnabled && !titleList.backButton) { var component = Qt.createComponent(Qt.resolvedUrl("private/BackButton.qml")); titleList.backButton = component.createObject(header); } else if (titleList.backButton) { titleList.backButton.destroy(); } } property Component pageDelegate: Component { Row { height: parent.height spacing: Units.smallSpacing x: Units.smallSpacing Icon { //in tabbar mode this is just a spacer visible: !titleList.wideMode && ((typeof(modelData) != "undefined" && modelData > 0) || titleList.internalHeaderStyle == ApplicationHeaderStyle.TabBar) anchors.verticalCenter: parent.verticalCenter height: Units.iconSizes.small width: height selected: header.background && header.background.color && header.background.color == Theme.highlightColor source: titleList.isTabBar ? "" : (LayoutMirroring.enabled ? "go-next-symbolic-rtl" : "go-next-symbolic") } Heading { id: title width: Math.min(parent.width, Math.min(titleList.width, implicitWidth)) + Units.smallSpacing anchors.verticalCenter: parent.verticalCenter opacity: current ? 1 : 0.4 //Scaling animate NativeRendering is too slow renderType: Text.QtRendering color: header.background && header.background.color && header.background.color == Theme.highlightColor ? Theme.highlightedTextColor : Theme.textColor elide: Text.ElideRight text: page ? page.title : "" font.pointSize: Math.max(1, titleList.height / (1.6 * Units.devicePixelRatio)) verticalAlignment: Text.AlignVCenter wrapMode: Text.NoWrap Rectangle { anchors { bottom: parent.bottom left: parent.left right: parent.right } height: Units.smallSpacing color: title.color opacity: 0.6 visible: titleList.isTabBar && current } } } } Rectangle { anchors { right: titleList.left verticalCenter: parent.verticalCenter } visible: titleList.x > 0 && !titleList.atXBeginning height: parent.height * 0.7 color: Theme.highlightedTextColor width: Math.ceil(Units.smallSpacing / 6) opacity: 0.4 } QQC2.StackView { id: stack anchors { fill: parent leftMargin: titleList.scrollingLocked && titleList.wideMode && depth < 2 ? 0 : titleList.backButton.width } initialItem: titleList } Repeater { model: __appWindow.pageStack.layers.depth -1 delegate: Loader { sourceComponent: header.pageDelegate readonly property Page page: __appWindow.pageStack.layers.get(modelData+1) readonly property bool current: true; Component.onCompleted: stack.push(this) Component.onDestruction: stack.pop() } } ListView { id: titleList readonly property bool wideMode: typeof __appWindow.pageStack.wideMode !== "undefined" ? __appWindow.pageStack.wideMode : titleList.wideMode property int internalHeaderStyle: header.headerStyle == ApplicationHeaderStyle.Auto ? (titleList.wideMode ? ApplicationHeaderStyle.Titles : ApplicationHeaderStyle.Breadcrumb) : header.headerStyle //if scrolling the titlebar should scroll also the pages and vice versa property bool scrollingLocked: (header.headerStyle == ApplicationHeaderStyle.Titles || titleList.wideMode) //uses this to have less strings comparisons property bool scrollMutex property bool isTabBar: header.headerStyle == ApplicationHeaderStyle.TabBar property Item backButton clip: true cacheBuffer: width ? Math.max(0, width * count) : 0 displayMarginBeginning: __appWindow.pageStack.width * count orientation: ListView.Horizontal boundsBehavior: Flickable.StopAtBounds model: __appWindow.pageStack.depth spacing: 0 currentIndex: __appWindow.pageStack && __appWindow.pageStack.currentIndex !== undefined ? __appWindow.pageStack.currentIndex : 0 function gotoIndex(idx) { //don't actually scroll in widescreen mode if (titleList.wideMode) { return; } listScrollAnim.running = false var pos = titleList.contentX; var destPos; titleList.positionViewAtIndex(idx, ListView.Center); destPos = titleList.contentX; listScrollAnim.from = pos; listScrollAnim.to = destPos; listScrollAnim.running = true; } NumberAnimation { id: listScrollAnim target: titleList property: "contentX" duration: Units.longDuration easing.type: Easing.InOutQuad } Timer { id: contentXSyncTimer interval: 0 onTriggered: { titleList.contentX = __appWindow.pageStack.contentItem.contentX - __appWindow.pageStack.contentItem.originX + titleList.originX; } } onCountChanged: contentXSyncTimer.restart(); onCurrentIndexChanged: gotoIndex(currentIndex); onModelChanged: gotoIndex(currentIndex); onContentWidthChanged: gotoIndex(currentIndex); onContentXChanged: { if (moving && !titleList.scrollMutex && titleList.scrollingLocked && !__appWindow.pageStack.contentItem.moving) { titleList.scrollMutex = true; __appWindow.pageStack.contentItem.contentX = titleList.contentX - titleList.originX + __appWindow.pageStack.contentItem.originX; titleList.scrollMutex = false; } } onHeightChanged: { titleList.returnToBounds() } onMovementEnded: { if (titleList.scrollingLocked) { //this will trigger snap as well __appWindow.pageStack.contentItem.flick(0,0); } } onFlickEnded: movementEnded(); NumberAnimation { id: scrollTopAnimation target: __appWindow.pageStack.currentItem && __appWindow.pageStack.currentItem.flickable ? __appWindow.pageStack.currentItem.flickable : null property: "contentY" to: 0 duration: Units.longDuration easing.type: Easing.InOutQuad } delegate: MouseArea { id: delegate readonly property int currentIndex: index readonly property var currentModelData: modelData clip: true width: { //more columns shown? if (titleList.scrollingLocked && delegateLoader.page) { return delegateLoader.page.width; } else { return Math.min(titleList.width, delegateLoader.implicitWidth + Units.smallSpacing); } } height: titleList.height onClicked: { if (__appWindow.pageStack.currentIndex == modelData) { //scroll up if current otherwise make current if (!__appWindow.pageStack.currentItem.flickable) { return; } if (__appWindow.pageStack.currentItem.flickable.contentY > -__appWindow.header.height) { scrollTopAnimation.to = -__appWindow.pageStack.currentItem.flickable.topMargin; scrollTopAnimation.running = true; } } else { __appWindow.pageStack.currentIndex = modelData; } } Loader { id: delegateLoader height: parent.height x: titleList.wideMode ? (Math.min(delegate.width - implicitWidth, Math.max(0, titleList.contentX - delegate.x + (titleList.backButton ? titleList.backButton.width : 0)))) : 0 width: index == titleList.count-1 ? parent.width : parent.width - x sourceComponent: header.pageDelegate readonly property Page page: __appWindow.pageStack.get(modelData) //NOTE: why not use ListViewCurrentIndex? because listview itself resets //currentIndex in some situations (since here we are using an int as a model, //even more often) so the property binding gets broken readonly property bool current: __appWindow.pageStack.currentIndex == index readonly property int index: parent.currentIndex readonly property var modelData: parent.currentModelData } } Connections { target: titleList.scrollingLocked ? __appWindow.pageStack.contentItem : null onContentXChanged: { if (!titleList.contentItem.moving && !titleList.scrollMutex) { titleList.contentX = __appWindow.pageStack.contentItem.contentX - __appWindow.pageStack.contentItem.originX + titleList.originX; } } } } } diff --git a/src/controls/templates/OverlayDrawer.qml b/src/controls/templates/OverlayDrawer.qml index 0b390089..905d2a57 100644 --- a/src/controls/templates/OverlayDrawer.qml +++ b/src/controls/templates/OverlayDrawer.qml @@ -1,317 +1,324 @@ /* * Copyright 2012 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Templates 2.0 as T2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import "private" /** * Overlay Drawers are used to expose additional UI elements needed for * small secondary tasks for which the main UI elements are not needed. * For example in Okular Active, an Overlay Drawer is used to display * thumbnails of all pages within a document along with a search field. * This is used for the distinct task of navigating to another page. * @inherits: QtQuick.Templates.Drawer */ T2.Drawer { id: root z: modal ? (Math.round((position * 100) / 10) ): 0 //BEGIN Properties /** * drawerOpen: bool * true when the drawer is open and visible */ property bool drawerOpen: false /** * enabled: bool * This property holds whether the item receives mouse and keyboard events. By default this is true. */ property bool enabled: true /** * peeking: true * When true the drawer is in a state between open and closed. the drawer is visible but not completely open. * This is usually the case when the user is dragging the drawer from a screen * edge, so the user is "peeking" what's in the drawer */ property bool peeking: false /** * animating: Bool * True during an animation of a drawer either opening or closing */ readonly property bool animating : enterAnimation.animating || exitAnimation.animating || positionResetAnim.running /** * handleVisible: bool * If true, a little handle will be visible to make opening the drawer easier * Currently supported only on left and right drawers */ property bool handleVisible: typeof(applicationWindow)===typeof(Function) && applicationWindow() ? applicationWindow().controlsVisible : true /** * handle: Item * Readonly property that points to the item that will act as a physical * handle for the Drawer **/ readonly property Item handle: MouseArea { id: drawerHandle z: root.modal ? applicationWindow().overlay.z + (root.position > 0 ? +1 : -1) : root.background.parent.z + 1 preventStealing: true parent: applicationWindow().overlay.parent property int startX property int mappedStartX onPressed: { root.peeking = true; startX = mouse.x; mappedStartX = mapToItem(parent, startX, 0).x } onPositionChanged: { var pos = mapToItem(parent, mouse.x - startX, mouse.y); switch(root.edge) { case Qt.LeftEdge: root.position = pos.x/root.contentItem.width; break; case Qt.RightEdge: root.position = (root.parent.width - pos.x - width)/root.contentItem.width; break; default: } } onReleased: { root.peeking = false; if (Math.abs(mapToItem(parent, mouse.x, 0).x - mappedStartX) < Qt.styleHints.startDragDistance) { if (!root.drawerOpen) { root.close(); } root.drawerOpen = !root.drawerOpen; } } onCanceled: { root.peeking = false } x: { switch(root.edge) { case Qt.LeftEdge: return root.background.width * root.position; case Qt.RightEdge: return drawerHandle.parent.width - (root.background.width * root.position) - width; default: return 0; } } anchors { bottom: parent.bottom bottomMargin: { if (!applicationWindow()) { return; } if (!applicationWindow() || !applicationWindow().pageStack || !applicationWindow().pageStack.contentItem || !applicationWindow().pageStack.contentItem.itemAt) { return 0; } var item; if (applicationWindow().pageStack.layers.depth > 1) { item = applicationWindow().pageStack.layers.currentItem; } else { item = applicationWindow().pageStack.contentItem.itemAt(applicationWindow().pageStack.contentItem.contentX + drawerHandle.x, 0); } //try to take the last item if (!item) { item = applicationWindow().pageStack.get(applicationWindow().pageStack.depth-1); } var footer = item && item.page ? item.page.footer : (item ? item.footer : undefined); if (footer) { return footer.height } else { return 0; } } Behavior on bottomMargin { NumberAnimation { duration: Units.shortDuration easing.type: Easing.InOutQuad } } } visible: root.enabled && (root.edge == Qt.LeftEdge || root.edge == Qt.RightEdge) width: Units.iconSizes.medium + Units.smallSpacing*2 height: width opacity: root.handleVisible ? 1 : 0 Behavior on opacity { NumberAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } transform: Translate { id: translateTransform x: root.handleVisible ? 0 : (root.edge == Qt.LeftEdge ? -drawerHandle.width : drawerHandle.width) Behavior on x { NumberAnimation { duration: Units.longDuration easing.type: !root.handleVisible ? Easing.OutQuad : Easing.InQuad } } } } + Theme.colorSet: Theme.View + Theme.onColorSetChanged: { + contentItem.Theme.colorSet = Theme.colorSet + background.Theme.colorSet = Theme.colorSet + } //END Properties //BEGIN reassign properties //default paddings leftPadding: Units.smallSpacing topPadding: Units.smallSpacing rightPadding: Units.smallSpacing bottomPadding: Units.smallSpacing parent: modal ? T2.ApplicationWindow.overlay : T2.ApplicationWindow.contentItem height: edge == Qt.LeftEdge || edge == Qt.RightEdge ? applicationWindow().height : Math.min(contentItem.implicitHeight, Math.round(applicationWindow().height*0.8)) width: edge == Qt.TopEdge || edge == Qt.BottomEdge ? applicationWindow().width : Math.min(contentItem.implicitWidth, Math.round(applicationWindow().width*0.8)) edge: Qt.LeftEdge modal: true dragMargin: enabled && (edge == Qt.LeftEdge || edge == Qt.RightEdge) ? Qt.styleHints.startDragDistance : 0 implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) enter: Transition { SequentialAnimation { id: enterAnimation /*NOTE: why this? the running status of the enter transition is not relaible and * the SmoothedAnimation is always marked as non running, * so the only way to get to a reliable animating status is with this */ property bool animating ScriptAction { script: { enterAnimation.animating = true //on non modal dialog we don't want drawers in the overlay if (!root.modal) { root.background.parent.parent = applicationWindow().overlay.parent } } } SmoothedAnimation { velocity: 5 } ScriptAction { script: enterAnimation.animating = false } } } exit: Transition { SequentialAnimation { id: exitAnimation property bool animating ScriptAction { script: exitAnimation.animating = true } SmoothedAnimation { velocity: 5 } ScriptAction { script: exitAnimation.animating = false } } } //END reassign properties //BEGIN signal handlers onPositionChanged: { if (peeking) { visible = true } } onVisibleChanged: { if (peeking) { visible = true } else { drawerOpen = visible; } } onPeekingChanged: { if (peeking) { root.enter.enabled = false; root.exit.enabled = false; } else { positionResetAnim.to = position > 0.5 ? 1 : 0; positionResetAnim.running = true root.enter.enabled = true; root.exit.enabled = true; } } onDrawerOpenChanged: { //sync this property only when the component is properly loaded if (!__internal.completed) { return; } positionResetAnim.running = false; if (drawerOpen) { open(); } else { close(); } } Component.onCompleted: { //if defined as drawerOpen by default in QML, don't animate if (root.drawerOpen) { root.enter.enabled = false; root.visible = true; root.position = 1; root.enter.enabled = true; } __internal.completed = true; + contentItem.Theme.colorSet = Theme.colorSet; + background.Theme.colorSet = Theme.colorSet; } //END signal handlers //this is as hidden as it can get here property QtObject __internal: QtObject { //here in order to not be accessible from outside property bool completed: false property NumberAnimation positionResetAnim: NumberAnimation { id: positionResetAnim target: root to: 0 property: "position" duration: (root.position)*Units.longDuration } } } diff --git a/src/controls/templates/OverlaySheet.qml b/src/controls/templates/OverlaySheet.qml index fb745cae..1947bd50 100644 --- a/src/controls/templates/OverlaySheet.qml +++ b/src/controls/templates/OverlaySheet.qml @@ -1,347 +1,352 @@ /* * Copyright (C) 2016 by Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.5 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import QtGraphicalEffects 1.0 import QtQuick.Templates 2.0 as T2 import "private" /** * An overlay sheet that covers the current Page content. * Its contents can be scrolled up or down, scrolling all the way up or * all the way down, dismisses it. * Use this for big, modal dialogs or information display, that can't be * logically done as a new separate Page, even if potentially * are taller than the screen space. * @inherits: QtQuick.QtObject */ QtObject { id: root + Theme.colorSet: Theme.View + Theme.inherit: false + /** * contentItem: Item * This property holds the visual content item. * * Note: The content item is automatically resized inside the * padding of the control. */ default property Item contentItem /** * sheetOpen: bool * If true the sheet is open showing the contents of the OverlaySheet * component. */ property bool sheetOpen /** * leftPadding: int * default contents padding at left */ property int leftPadding: Units.gridUnit /** * topPadding: int * default contents padding at top */ property int topPadding: Units.gridUnit /** * rightPadding: int * default contents padding at right */ property int rightPadding: Units.gridUnit /** * bottomPadding: int * default contents padding at bottom */ property int bottomPadding: Units.gridUnit /** * background: Item * This property holds the background item. * * Note: If the background item has no explicit size specified, * it automatically follows the control's size. * In most cases, there is no need to specify width or * height for a background item. */ property Item background property Item parent function open() { mainItem.visible = true; openAnimation.from = -mainItem.height; openAnimation.to = openAnimation.topOpenPosition; openAnimation.running = true; root.sheetOpen = true; } function close() { if (scrollView.flickableItem.contentY < 0) { closeAnimation.to = -height; } else { closeAnimation.to = scrollView.flickableItem.contentHeight; } closeAnimation.running = true; } onBackgroundChanged: { background.parent = flickableContents; background.z = -1; } onContentItemChanged: { if (contentItem.hasOwnProperty("contentY") && // Check if flickable contentItem.hasOwnProperty("contentHeight")) { contentItem.parent = scrollView; scrollView.contentItem = contentItem; } else { contentItem.parent = contentItemParent; scrollView.contentItem = flickableContents; contentItem.anchors.left = contentItemParent.left; contentItem.anchors.right = contentItemParent.right; } scrollView.flickableItem.flickableDirection = Flickable.VerticalFlick; } onSheetOpenChanged: { if (sheetOpen) { open(); } else { close(); Qt.inputMethod.hide(); } } Component.onCompleted: { scrollView.flickableItem.interactive = true; if (!root.parent) { root.parent = applicationWindow().overlay } } readonly property Item rootItem: MouseArea { id: mainItem + Theme.colorSet: root.Theme.colorSet + Theme.inherit: root.Theme.inherit //we want to be over any possible OverlayDrawers, including handles parent: root.parent == applicationWindow().overlay ? root.parent.parent : root.parent anchors.fill: parent z: 2000000 visible: false drag.filterChildren: true hoverEnabled: true onClicked: { var pos = mapToItem(flickableContents, mouse.x, mouse.y); if (!flickableContents.contains(pos)) { root.close(); } } onWidthChanged: { if (!contentItem.contentItem) return var width = Math.max(mainItem.width/2, Math.min(mainItem.width, root.contentItem.implicitWidth)); contentItem.contentItem.x = (mainItem.width - width)/2 contentItem.contentItem.width = width; } onHeightChanged: { var focusItem; if (typeof applicationWindow !== "undefined") { focusItem = applicationWindow().activeFocusItem; //fallback: hope activeFocusItem is in context } else { focusItem = activeFocusItem; } if (!activeFocusItem) { return; } //NOTE: there is no function to know if an item is descended from another, //so we have to walk the parent hyerarchy by hand var isDescendent = false; var candidate = focusItem.parent; while (candidate) { if (candidate == root) { isDescendent = true; break; } candidate = candidate.parent; } if (!isDescendent) { return; } var cursorY = 0; if (focusItem.cursorPosition !== undefined) { cursorY = focusItem.positionToRectangle(focusItem.cursorPosition).y; } var pos = focusItem.mapToItem(flickableContents, 0, cursorY - Units.gridUnit*3); //focused item alreqady visible? add some margin for the space of the action buttons if (pos.y >= scrollView.flickableItem.contentY && pos.y <= scrollView.flickableItem.contentY + scrollView.flickableItem.height - Units.gridUnit * 8) { return; } scrollView.flickableItem.contentY = pos.y; } NumberAnimation { id: openAnimation property int topOpenPosition: Math.min(-mainItem.height*0.15, scrollView.flickableItem.contentHeight - mainItem.height + Units.gridUnit * 5) property int bottomOpenPosition: (scrollView.flickableItem.contentHeight - mainItem.height) + (Units.gridUnit * 5) target: scrollView.flickableItem properties: "contentY" from: -mainItem.height to: topOpenPosition duration: Units.longDuration easing.type: Easing.OutQuad onRunningChanged: { if (!running && contentItem.contentItem) { var width = Math.max(mainItem.width/2, Math.min(mainItem.width, root.contentItem.implicitWidth)); contentItem.contentItem.x = (mainItem.width - width)/2 contentItem.contentItem.width = width; } } } SequentialAnimation { id: closeAnimation property int to: -mainItem.height NumberAnimation { target: scrollView.flickableItem properties: "contentY" to: closeAnimation.to duration: Units.longDuration easing.type: Easing.InQuad } ScriptAction { script: { scrollView.flickableItem.contentY = -mainItem.height; mainItem.visible = root.sheetOpen = false; } } } Rectangle { anchors.fill: parent color: Theme.textColor opacity: 0.6 * Math.min( (Math.min(scrollView.flickableItem.contentY + scrollView.flickableItem.height, scrollView.flickableItem.height) / scrollView.flickableItem.height), (2 + (scrollView.flickableItem.contentHeight - scrollView.flickableItem.contentY - scrollView.flickableItem.topMargin - scrollView.flickableItem.bottomMargin)/scrollView.flickableItem.height)) } Item { id: flickableContents //anchors.horizontalCenter: parent.horizontalCenter x: (mainItem.width - width) / 2 readonly property real headerHeight: scrollView.flickableItem && root.contentItem.headerItem ? root.contentItem.headerItem.height : 0 y: scrollView.flickableItem && root.contentItem.hasOwnProperty("contentY") ? -scrollView.flickableItem.contentY - headerHeight : 0 width: root.contentItem.implicitWidth <= 0 ? mainItem.width : Math.max(mainItem.width/2, Math.min(mainItem.width, root.contentItem.implicitWidth)) height: scrollView.flickableItem && root.contentItem.hasOwnProperty("contentY") ? scrollView.flickableItem.contentHeight + headerHeight : (root.contentItem.height + topPadding + bottomPadding + Units.iconSizes.medium + Units.gridUnit) Item { id: contentItemParent anchors { fill: parent leftMargin: leftPadding topMargin: topPadding rightMargin: rightPadding bottomMargin: bottomPadding } } } Binding { when: scrollView.flickableItem != null target: scrollView.flickableItem property: "topMargin" value: scrollView.height } Binding { when: scrollView.flickableItem != null target: scrollView.flickableItem property: "bottomMargin" value: scrollView.height } Connections { target: scrollView.flickableItem function movementEnded() { //close if ((mainItem.height + scrollView.flickableItem.contentY) < mainItem.height/2) { closeAnimation.to = -mainItem.height; closeAnimation.running = true; } else if ((mainItem.height*0.6 + scrollView.flickableItem.contentY) > scrollView.flickableItem.contentHeight) { closeAnimation.to = scrollView.flickableItem.contentHeight closeAnimation.running = true; //reset to the default sheetOpen position } else if (scrollView.flickableItem.contentY < openAnimation.topOpenPosition) { openAnimation.from = scrollView.flickableItem.contentY; openAnimation.to = openAnimation.topOpenPosition; openAnimation.running = true; //reset to the default "bottom" sheetOpen position } else if (scrollView.flickableItem.contentY > openAnimation.bottomOpenPosition) { openAnimation.from = scrollView.flickableItem.contentY; openAnimation.to = openAnimation.bottomOpenPosition; openAnimation.running = true; } } onMovementEnded: movementEnded(); onFlickEnded: movementEnded(); onContentHeightChanged: { if (openAnimation.running) { openAnimation.running = false; open(); } } } //add an extra background for the scrollbar Rectangle { z: -1 parent: scrollView.verticalScrollBar.background anchors.fill:parent - color: Theme.viewBackgroundColor + color: Theme.backgroundColor } Binding { target: scrollView.verticalScrollBar property: "visible" value: scrollView.flickableItem.contentHeight > mainItem.height*0.8 } Connections { target: scrollView.verticalScrollBar onActiveChanged: { if (!scrollView.verticalScrollBar.active) { scrollView.flickableItem.movementEnded(); } } } ScrollView { id: scrollView anchors.fill: parent horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff } } } diff --git a/src/controls/templates/SwipeListItem.qml b/src/controls/templates/SwipeListItem.qml index c69a5147..698373a6 100644 --- a/src/controls/templates/SwipeListItem.qml +++ b/src/controls/templates/SwipeListItem.qml @@ -1,324 +1,324 @@ /* * Copyright 2010 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.7 import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import "../private" import QtQuick.Templates 2.0 as T2 /** * An item delegate Intended to support extra actions obtainable * by uncovering them by dragging away the item with the handle * This acts as a container for normal list items. * Any subclass of AbstractListItem can be assigned as the contentItem property. * @code * ListView { * model: myModel * delegate: SwipeListItem { * Label { * text: model.text * } * actions: [ * Action { * iconName: "document-decrypt" * onTriggered: print("Action 1 clicked") * }, * Action { * iconName: model.action2Icon * onTriggered: //do something * } * ] * } * * } * @endcode * * @inherit QtQuick.Templates.ItemDelegate */ T2.ItemDelegate { id: listItem //BEGIN properties /** * supportsMouseEvents: bool * Holds if the item emits signals related to mouse interaction. *TODO: remove * The default value is false. */ property alias supportsMouseEvents: listItem.hoverEnabled /** * containsMouse: bool * True when the user hover the mouse over the list item * NOTE: on mobile touch devices this will be true only when pressed is also true */ property alias containsMouse: listItem.hovered /** * sectionDelegate: bool * If true the item will be a delegate for a section, so will look like a * "title" for the items under it. */ property bool sectionDelegate: false /** * separatorVisible: bool * True if the separator between items is visible * default: true */ property bool separatorVisible: true /** * actions: list * Defines the actions for the list item: at most 4 buttons will * contain the actions for the item, that can be revealed by * sliding away the list item. */ property list actions /** * textColor: color * Color for the text in the item * * Note: if custom text elements are inserted in an AbstractListItem, * their color proprty will ahve to be manually binded with this property */ - property color textColor: Theme.viewTextColor + property color textColor: Theme.textColor /** * backgroundColor: color * Color for the background of the item */ - property color backgroundColor: Theme.viewBackgroundColor + property color backgroundColor: Theme.backgroundColor /** * activeTextColor: color * Color for the text in the item when pressed or selected * It is advised to leave the default value (Theme.highlightedTextColor) * * Note: if custom text elements are inserted in an AbstractListItem, * their color proprty will ahve to be manually binded with this property */ property color activeTextColor: Theme.highlightedTextColor /** * activeBackgroundColor: color * Color for the background of the item when pressed or selected * It is advised to leave the default value (Theme.highlightColor) */ property color activeBackgroundColor: Theme.highlightColor default property alias _default: listItem.contentItem implicitWidth: contentItem ? contentItem.implicitWidth : Units.gridUnit * 12 width: parent ? parent.width : implicitWidth implicitHeight: contentItem.implicitHeight + Units.smallSpacing * 5 leftPadding: Units.smallSpacing * 2 topPadding: Units.smallSpacing * 2 rightPadding: Units.smallSpacing * 2 bottomPadding: Units.smallSpacing * 2 //END properties Item { id: behindItem parent: listItem z: -1 anchors { fill: parent } Rectangle { id: shadowHolder color: Theme.backgroundColor anchors.fill: parent } EdgeShadow { edge: Qt.TopEdge anchors { right: parent.right left: parent.left top: parent.top } } EdgeShadow { edge: Qt.LeftEdge x: listItem.background.x + listItem.background.width anchors { top: parent.top bottom: parent.bottom } } MouseArea { anchors.fill: parent preventStealing: true enabled: background.x != 0 onClicked: { positionAnimation.from = background.x; positionAnimation.to = 0; positionAnimation.running = true; } } Row { id: actionsLayout z: 1 anchors { right: parent.right verticalCenter: parent.verticalCenter rightMargin: listItem.rightPadding } height: Math.min( parent.height / 1.5, Units.iconSizes.medium) width: childrenRect.width property bool exclusive: false property Item checkedButton spacing: Units.largeSpacing Repeater { model: { if (listItem.actions.length == 0) { return null; } else { return listItem.actions[0].text !== undefined && listItem.actions[0].trigger !== undefined ? listItem.actions : listItem.actions[0]; } } delegate: Icon { height: actionsLayout.height width: height source: modelData.iconName enabled: (modelData && modelData.enabled !== undefined) ? modelData.enabled : true; visible: (modelData && modelData.visible !== undefined) ? modelData.visible : true; MouseArea { anchors { fill: parent; margins: -Units.smallSpacing; } enabled: (modelData && modelData.enabled !== undefined) ? modelData.enabled : true; onClicked: { if (modelData && modelData.trigger !== undefined) { modelData.trigger(); } positionAnimation.from = background.x; positionAnimation.to = 0; positionAnimation.running = true; } } } } } } MouseArea { id: handleMouse parent: listItem.background z: 99 anchors { right: parent.right top: parent.top bottom: parent.bottom rightMargin: listItem.rightPadding } preventStealing: true width: height property var downTimestamp; property int startX property int startMouseX onClicked: { positionAnimation.from = background.x; if (listItem.background.x > -listItem.background.width/2) { positionAnimation.to = -listItem.width + height; } else { positionAnimation.to = 0; } positionAnimation.running = true; } onPressed: { downTimestamp = (new Date()).getTime(); startX = listItem.background.x; startMouseX = mouse.x; } onPositionChanged: { listItem.background.x = Math.min(0, Math.max(-listItem.width + height, listItem.background.x - (startMouseX - mouse.x))); } onReleased: { var speed = ((startX - listItem.background.x) / ((new Date()).getTime() - downTimestamp) * 1000); if (Math.abs(speed) < Units.gridUnit) { return; } if (speed > listItem.width/2) { positionAnimation.to = -listItem.width + height; } else { positionAnimation.to = 0; } positionAnimation.from = background.x; positionAnimation.running = true; } Icon { id: handleIcon anchors.verticalCenter: parent.verticalCenter selected: listItem.checked || (listItem.pressed && !listItem.checked && !listItem.sectionDelegate) width: Units.iconSizes.smallMedium height: width x: y source: listItem.background.x < -listItem.background.width/2 ? "handle-right" : "handle-left" } } NumberAnimation { id: positionAnimation property: "x" target: background duration: Units.longDuration easing.type: Easing.InOutQuad } //BEGIN signal handlers onContentItemChanged: { contentItem.parent = background; contentItem.z = 0; } Component.onCompleted: { //this will happen only once if (Settings.isMobile && !swipeFilterConnection.swipeFilterItem) { var component = Qt.createComponent(Qt.resolvedUrl("../private/SwipeItemEventFilter.qml")); listItem.ListView.view.parent.parent._swipeFilter = component.createObject(listItem.ListView.view.parent.parent); } } Connections { id: swipeFilterConnection readonly property QtObject swipeFilterItem: (listItem.ListView && listItem.ListView.view && listItem.ListView.view.parent && listItem.ListView.view.parent.parent) ? listItem.ListView.view.parent.parent._swipeFilter : null readonly property bool enabled: swipeFilterItem ? swipeFilterItem.currentItem === listItem : false target: enabled ? swipeFilterItem : null onPeekChanged: listItem.background.x = -(listItem.background.width - listItem.background.height) * swipeFilterItem.peek onCurrentItemChanged: { if (!enabled) { positionAnimation.to = 0; positionAnimation.from = background.x; positionAnimation.running = true; } } } //END signal handlers Accessible.role: Accessible.ListItem } diff --git a/src/controls/templates/private/BackButton.qml b/src/controls/templates/private/BackButton.qml index 8eaa3922..d3be6dee 100644 --- a/src/controls/templates/private/BackButton.qml +++ b/src/controls/templates/private/BackButton.qml @@ -1,50 +1,50 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Controls 2.0 as Controls -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 Controls.ToolButton { anchors { left: parent.left top: parent.top bottom: parent.bottom } width: visible ? height : 0 z: 99 enabled: !Settings.isMobile && (__appWindow.pageStack.currentIndex > 0 || applicationWindow().pageStack.contentItem.contentX > 0) implicitWidth: height visible: applicationWindow().pageStack.contentItem.contentWidth > applicationWindow().pageStack.width onClicked: { if (applicationWindow().pageStack.layers && applicationWindow().pageStack.layers.depth > 1) { applicationWindow().pageStack.layers.pop(); } else { applicationWindow().pageStack.goBack(); } } Icon { anchors.fill: parent opacity: parent.enabled ? 1 : 0.6 selected: header.background && header.background.color && header.background.color == Theme.highlightColor source: (LayoutMirroring.enabled ? "go-previous-symbolic-rtl" : "go-previous-symbolic") } } diff --git a/src/controls/templates/private/ContextIcon.qml b/src/controls/templates/private/ContextIcon.qml index b7d5eb3e..c9e21be8 100644 --- a/src/controls/templates/private/ContextIcon.qml +++ b/src/controls/templates/private/ContextIcon.qml @@ -1,78 +1,78 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.2 import QtGraphicalEffects 1.0 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 Item { id: canvas width: height height: Units.iconSizes.smallMedium property real morph: 0 property color color: Theme.textColor opacity: 0.8 layer.enabled: true Item { id: iconRoot anchors { fill: parent margins: Units.smallSpacing } property int thickness: Math.round(Units.smallSpacing / 2) Rectangle { anchors { horizontalCenter: parent.horizontalCenter top: parent.top leftMargin: canvas.width/4 * morph } antialiasing: true transformOrigin: Item.Left width: (1 - morph) * height + morph * ((parent.width / Math.sqrt(2)) - height/2) height: iconRoot.thickness + iconRoot.thickness*0.5 * (1-morph) color: canvas.color rotation: 45 * morph } Rectangle { anchors.centerIn: parent width: height * (1 - morph) height: iconRoot.thickness + iconRoot.thickness*0.5 * (1-morph) color: canvas.color } Rectangle { anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom leftMargin: canvas.width/4 * morph } antialiasing: true transformOrigin: Item.Left width: (1 - morph) * height + morph * ((parent.width / Math.sqrt(2)) - height/2) height: iconRoot.thickness + iconRoot.thickness*0.5 * (1-morph) color: canvas.color rotation: -45 * morph } } } diff --git a/src/controls/templates/private/MenuIcon.qml b/src/controls/templates/private/MenuIcon.qml index 74faf51a..8e2d2070 100644 --- a/src/controls/templates/private/MenuIcon.qml +++ b/src/controls/templates/private/MenuIcon.qml @@ -1,77 +1,77 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.2 import QtGraphicalEffects 1.0 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 Item { id: canvas width: height height: Units.iconSizes.smallMedium property real morph: 0 property color color: Theme.textColor opacity: 0.8 layer.enabled: true Item { id: iconRoot anchors { fill: parent margins: Units.smallSpacing } property int thickness: Math.round(Units.smallSpacing / 2) Rectangle { anchors { right: parent.right top: parent.top rightMargin: canvas.width/4 * morph } antialiasing: true transformOrigin: Item.Right width: (1 - morph) * parent.width + morph * ((parent.width / Math.sqrt(2)) - height/2) height: iconRoot.thickness color: canvas.color rotation: -45 * morph } Rectangle { anchors.centerIn: parent width: parent.width - parent.width * morph height: iconRoot.thickness color: canvas.color } Rectangle { anchors { right: parent.right bottom: parent.bottom rightMargin: canvas.width/4 * morph } antialiasing: true transformOrigin: Item.Right width: (1 - morph) * parent.width + morph * ((parent.width / Math.sqrt(2)) - height/2) height: iconRoot.thickness color: canvas.color rotation: 45 * morph } } } diff --git a/src/controls/templates/private/PassiveNotification.qml b/src/controls/templates/private/PassiveNotification.qml index 4e3d67e3..8c6982ee 100644 --- a/src/controls/templates/private/PassiveNotification.qml +++ b/src/controls/templates/private/PassiveNotification.qml @@ -1,153 +1,153 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import QtQuick.Controls 2.0 as QQC2 import QtQuick.Layouts 1.2 import QtGraphicalEffects 1.0 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 MouseArea { id: root z: 9999999 width: background.width height: background.height opacity: 0 enabled: appearAnimation.appear anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom bottomMargin: Units.gridUnit * 4 } function showNotification(message, timeout, actionText, callBack) { if (!message) { return; } appearAnimation.running = false; appearAnimation.appear = true; appearAnimation.running = true; if (timeout == "short") { timer.interval = 1000; } else if (timeout == "long") { timer.interval = 4500; } else if (timeout > 0) { timer.interval = timeout; } else { timer.interval = 4500; } messageLabel.text = message ? message : ""; actionButton.text = actionText ? actionText : ""; actionButton.callBack = callBack ? callBack : ""; timer.restart(); } function hideNotification() { appearAnimation.running = false; appearAnimation.appear = false; appearAnimation.running = true; } onClicked: { appearAnimation.appear = false; appearAnimation.running = true; } transform: Translate { id: transform y: root.height } Timer { id: timer interval: 4000 onTriggered: { appearAnimation.appear = false; appearAnimation.running = true; } } ParallelAnimation { id: appearAnimation property bool appear: true NumberAnimation { target: root properties: "opacity" to: appearAnimation.appear ? 1 : 0 duration: Units.longDuration easing.type: Easing.InOutQuad } NumberAnimation { target: transform properties: "y" to: appearAnimation.appear ? 0 : background.height duration: Units.longDuration easing.type: appearAnimation.appear ? Easing.OutQuad : Easing.InQuad } } Item { id: background width: backgroundRect.width + Units.gridUnit height: backgroundRect.height + Units.gridUnit Rectangle { id: backgroundRect anchors.centerIn: parent radius: Units.smallSpacing color: Theme.textColor opacity: 0.6 width: mainLayout.width + Math.round((height - mainLayout.height)) height: Math.max(mainLayout.height + Units.smallSpacing*2, Units.gridUnit*2) } RowLayout { id: mainLayout anchors.centerIn: parent Label { id: messageLabel Layout.maximumWidth: Math.min(root.parent.width - Units.largeSpacing*2, implicitWidth) elide: Text.ElideRight wrapMode: Text.WordWrap maximumLineCount: 4 color: Theme.backgroundColor } QQC2.Button { id: actionButton property var callBack visible: text != "" onClicked: { appearAnimation.appear = false; appearAnimation.running = true; if (callBack) { callBack(); } } } } layer.enabled: true layer.effect: DropShadow { horizontalOffset: 0 verticalOffset: 0 radius: Units.gridUnit samples: 32 color: Qt.rgba(0, 0, 0, 0.5) } } } diff --git a/src/controls/templates/private/ScrollView.qml b/src/controls/templates/private/ScrollView.qml index e03853a3..53a82631 100644 --- a/src/controls/templates/private/ScrollView.qml +++ b/src/controls/templates/private/ScrollView.qml @@ -1,108 +1,108 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import QtQuick.Controls 2.0 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 MouseArea { id: root default property Item contentItem property Flickable flickableItem //TODO: horizontalScrollBarPolicy is completely noop just for compatibility right now property int horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff property int verticalScrollBarPolicy: Qt.ScrollBarAsNeeded readonly property Item verticalScrollBar: flickableItem.ScrollBar.vertical ? flickableItem.ScrollBar.vertical : null onVerticalScrollBarPolicyChanged: { flickableItem.ScrollBar.vertical.visible = verticalScrollBarPolicy == Qt.ScrollBarAlwaysOff } drag.filterChildren: !Settings.isMobile onWheel: { if (Settings.isMobile || flickableItem.contentHeight * Copyright 2014 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "desktopicon.h" +#include "platformtheme.h" #include #include #include #include #include #include #include #include #include #include #include #include #include +#include class ManagedTextureNode : public QSGSimpleTextureNode { Q_DISABLE_COPY(ManagedTextureNode) public: ManagedTextureNode(); void setTexture(QSharedPointer texture); private: QSharedPointer m_texture; }; ManagedTextureNode::ManagedTextureNode() {} void ManagedTextureNode::setTexture(QSharedPointer texture) { m_texture = texture; QSGSimpleTextureNode::setTexture(texture.data()); } typedef QHash > > TexturesCache; struct ImageTexturesCachePrivate { TexturesCache cache; }; class ImageTexturesCache { public: ImageTexturesCache(); ~ImageTexturesCache(); /** * @returns the texture for a given @p window and @p image. * * If an @p image id is the same as one already provided before, we won't create * a new texture and return a shared pointer to the existing texture. */ QSharedPointer loadTexture(QQuickWindow *window, const QImage &image, QQuickWindow::CreateTextureOptions options); QSharedPointer loadTexture(QQuickWindow *window, const QImage &image); private: QScopedPointer d; }; ImageTexturesCache::ImageTexturesCache() : d(new ImageTexturesCachePrivate) { } ImageTexturesCache::~ImageTexturesCache() { } QSharedPointer ImageTexturesCache::loadTexture(QQuickWindow *window, const QImage &image, QQuickWindow::CreateTextureOptions options) { qint64 id = image.cacheKey(); QSharedPointer texture = d->cache.value(id).value(window).toStrongRef(); if (!texture) { auto cleanAndDelete = [this, window, id](QSGTexture* texture) { QHash >& textures = (d->cache)[id]; textures.remove(window); if (textures.isEmpty()) d->cache.remove(id); delete texture; }; texture = QSharedPointer(window->createTextureFromImage(image, options), cleanAndDelete); (d->cache)[id][window] = texture.toWeakRef(); } //if we have a cache in an atlas but our request cannot use an atlassed texture //create a new texture and use that //don't use removedFromAtlas() as that requires keeping a reference to the non atlased version if (!(options & QQuickWindow::TextureCanUseAtlas) && texture->isAtlasTexture()) { texture = QSharedPointer(window->createTextureFromImage(image, options)); } return texture; } QSharedPointer ImageTexturesCache::loadTexture(QQuickWindow *window, const QImage &image) { return loadTexture(window, image, 0); } Q_GLOBAL_STATIC(ImageTexturesCache, s_iconImageCache) DesktopIcon::DesktopIcon(QQuickItem *parent) : QQuickItem(parent), m_smooth(false), m_changed(false), m_active(false), - m_selected(false) + m_selected(false), + m_isMask(false) { setFlag(ItemHasContents, true); + //FIXME: not necessary anymore connect(qApp, &QGuiApplication::paletteChanged, this, [this]() { m_changed = true; update(); }); } DesktopIcon::~DesktopIcon() { } void DesktopIcon::setSource(const QVariant &icon) { if (m_source == icon) { return; } m_source = icon; m_changed = true; + + if (!m_theme) { + m_theme = static_cast(qmlAttachedPropertiesObject(this, true)); + Q_ASSERT(m_theme); + + connect(m_theme, &Kirigami::PlatformTheme::colorsChanged, this, [this]() { + m_changed = true; + update(); + }); + } + update(); emit sourceChanged(); } QVariant DesktopIcon::source() const { return m_source; } void DesktopIcon::setEnabled(const bool enabled) { if (enabled == QQuickItem::isEnabled()) { return; } QQuickItem::setEnabled(enabled); m_changed = true; update(); emit enabledChanged(); } void DesktopIcon::setActive(const bool active) { if (active == m_active) { return; } m_active = active; m_changed = true; update(); emit activeChanged(); } bool DesktopIcon::active() const { return m_active; } bool DesktopIcon::valid() const { return !m_source.isNull(); } void DesktopIcon::setSelected(const bool selected) { if (selected == m_selected) { return; } m_selected = selected; m_changed = true; update(); emit selectedChanged(); } bool DesktopIcon::selected() const { return m_selected; } +void DesktopIcon::setIsMask(bool mask) +{ + if (m_isMask == mask) { + return; + } + + m_isMask = mask; + emit isMaskChanged(); +} + +bool DesktopIcon::isMask() const +{ + return m_isMask; +} + +void DesktopIcon::setColor(const QColor &color) +{ + if (m_color == color) { + return; + } + + m_color = color; + emit colorChanged(); +} + +QColor DesktopIcon::color() const +{ + return m_color; +} + + int DesktopIcon::implicitWidth() const { return 32; } int DesktopIcon::implicitHeight() const { return 32; } void DesktopIcon::setSmooth(const bool smooth) { if (smooth == m_smooth) { return; } m_smooth = smooth; m_changed = true; update(); emit smoothChanged(); } bool DesktopIcon::smooth() const { return m_smooth; } QSGNode* DesktopIcon::updatePaintNode(QSGNode* node, QQuickItem::UpdatePaintNodeData* /*data*/) { if (m_source.isNull()) { delete node; return Q_NULLPTR; } if (m_changed || node == 0) { QImage img; const QSize itemSize(width(), height()); if (itemSize.width() != 0 && itemSize.height() != 0) { const QSize size = itemSize * (window() ? window()->devicePixelRatio() : qApp->devicePixelRatio()); switch(m_source.type()){ case QVariant::Pixmap: img = m_source.value().toImage(); break; case QVariant::Image: img = m_source.value(); break; case QVariant::Bitmap: img = m_source.value().toImage(); break; case QVariant::Icon: img = m_source.value().pixmap(size, iconMode(), QIcon::On).toImage(); break; case QVariant::Url: case QVariant::String: img = findIcon(size); break; case QVariant::Brush: + //todo: fill here too? case QVariant::Color: - //perhaps fill image instead? + img = QImage(size, QImage::Format_Alpha8); + img.fill(m_source.value()); + break; default: break; } if (img.isNull()){ img = QImage(size, QImage::Format_Alpha8); img.fill(Qt::transparent); } if (img.size() != size){ img = img.scaled(size, Qt::KeepAspectRatioByExpanding, m_smooth ? Qt::SmoothTransformation : Qt::FastTransformation ); } } m_changed = false; ManagedTextureNode* mNode = dynamic_cast(node); if (!mNode) { delete node; mNode = new ManagedTextureNode; } mNode->setTexture(s_iconImageCache->loadTexture(window(), img)); mNode->setRect(QRect(QPoint(0,0), itemSize)); node = mNode; } return node; } void DesktopIcon::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { if (newGeometry.size() != oldGeometry.size()) { m_changed = true; update(); } QQuickItem::geometryChanged(newGeometry, oldGeometry); } void DesktopIcon::handleFinished(QNetworkAccessManager* qnam, QNetworkReply* reply) { if (reply->error() == QNetworkReply::NoError) { const QUrl possibleRedirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); if (!possibleRedirectUrl.isEmpty()) { const QUrl redirectUrl = reply->url().resolved(possibleRedirectUrl); if (redirectUrl == reply->url()) { // no infinite redirections thank you very much reply->deleteLater(); return; } reply->deleteLater(); QNetworkRequest request(possibleRedirectUrl); request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); QNetworkReply* newReply = qnam->get(request); connect(newReply, &QNetworkReply::readyRead, this, [this, newReply](){ handleReadyRead(newReply); }); connect(newReply, &QNetworkReply::finished, this, [this, qnam, newReply](){ handleFinished(qnam, newReply); }); return; } } } void DesktopIcon::handleReadyRead(QNetworkReply* reply) { if (reply->attribute(QNetworkRequest::RedirectionTargetAttribute).isNull()) { // We're handing the event loop back while doing network work, and it turns out // this fairly regularly results in things being deleted under us. So, just // handle that and crash less :) QPointer me(this); QByteArray data; do { data.append(reply->read(32768)); // Because we are in the main thread, this could be potentially very expensive, so let's not block qApp->processEvents(); if(!me) { return; } } while(!reply->atEnd()); m_loadedImage = QImage::fromData(data); if (m_loadedImage.isNull()) { // broken image from data, inform the user of this with some useful broken-image thing... const QSize size = QSize(width(), height()) * (window() ? window()->devicePixelRatio() : qApp->devicePixelRatio()); m_loadedImage = QIcon::fromTheme("unknown").pixmap(size, iconMode(), QIcon::On).toImage(); } m_changed = true; update(); } } QImage DesktopIcon::findIcon(const QSize &size) { QImage img; QString iconSource = m_source.toString(); if (iconSource.startsWith("image://")){ QUrl iconUrl(iconSource); QString iconProviderId = iconUrl.host(); QString iconId = iconUrl.path(); QSize actualSize; QQuickImageProvider* imageProvider = dynamic_cast( qmlEngine(this)->imageProvider(iconProviderId)); if (!imageProvider) return img; switch(imageProvider->imageType()){ case QQmlImageProviderBase::Image: img = imageProvider->requestImage(iconId, &actualSize, size); break; case QQmlImageProviderBase::Pixmap: img = imageProvider->requestPixmap(iconId, &actualSize, size).toImage(); break; case QQmlImageProviderBase::Texture: case QQmlImageProviderBase::Invalid: case QQmlImageProviderBase::ImageResponse: //will have to investigate this more break; } } else if(iconSource.startsWith("http://") || iconSource.startsWith("https://")) { if(!m_loadedImage.isNull()) { return m_loadedImage.scaled(size, Qt::KeepAspectRatio, m_smooth ? Qt::SmoothTransformation : Qt::FastTransformation ); } QQmlEngine* engine = qmlEngine(this); QNetworkAccessManager* qnam; if (engine && (qnam = qmlEngine(this)->networkAccessManager())) { QNetworkRequest request(m_source.toUrl()); request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); QNetworkReply* reply = qnam->get(request); connect(reply, &QNetworkReply::readyRead, this, [this, reply](){ handleReadyRead(reply); }); connect(reply, &QNetworkReply::finished, this, [this, qnam, reply](){ handleFinished(qnam, reply); }); } // Temporary icon while we wait for the real image to load... img = QIcon::fromTheme("image-x-icon").pixmap(size, iconMode(), QIcon::On).toImage(); } else { if (iconSource.startsWith("qrc:/")){ iconSource = iconSource.mid(3); } QIcon icon(iconSource); if (icon.availableSizes().isEmpty()) { - icon = QIcon::fromTheme(iconSource); + icon = m_theme->iconFromTheme(iconSource, m_color); } if (!icon.availableSizes().isEmpty()){ img = icon.pixmap(size, iconMode(), QIcon::On).toImage(); + if (m_isMask || icon.isMask()) { + QPainter p(&img); + p.setCompositionMode(QPainter::CompositionMode_SourceIn); + p.fillRect(img.rect(), m_theme->textColor()); + p.end(); + } } } return img; } QIcon::Mode DesktopIcon::iconMode() const { if (!isEnabled()) { return QIcon::Disabled; } else if (m_selected) { return QIcon::Selected; } else if (m_active) { return QIcon::Active; } return QIcon::Normal; } diff --git a/src/desktopicon.h b/src/desktopicon.h index 7e009eec..72e63612 100644 --- a/src/desktopicon.h +++ b/src/desktopicon.h @@ -1,91 +1,110 @@ /* * Copyright 2011 Marco Martin * Copyright 2014 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef QICONITEM_H #define QICONITEM_H #include #include #include class QNetworkAccessManager; class QNetworkReply; + +namespace Kirigami { + class PlatformTheme; +} + class DesktopIcon : public QQuickItem { Q_OBJECT Q_PROPERTY(QVariant source READ source WRITE setSource NOTIFY sourceChanged) Q_PROPERTY(bool smooth READ smooth WRITE setSmooth NOTIFY smoothChanged) Q_PROPERTY(int implicitWidth READ implicitWidth CONSTANT) Q_PROPERTY(int implicitHeight READ implicitHeight CONSTANT) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) Q_PROPERTY(bool valid READ valid NOTIFY validChanged) Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectedChanged) + Q_PROPERTY(bool isMask READ isMask WRITE setIsMask NOTIFY isMaskChanged) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) public: DesktopIcon(QQuickItem *parent=0); ~DesktopIcon(); void setSource(const QVariant &source); QVariant source() const; int implicitWidth() const; int implicitHeight() const; void setSmooth(const bool smooth); bool smooth() const; void setEnabled(bool enabled = true); void setActive(bool active = true); bool active() const; bool valid() const; void setSelected(bool selected = true); bool selected() const; + void setIsMask(bool mask); + bool isMask() const; + + void setColor(const QColor &color); + QColor color() const; + QSGNode* updatePaintNode(QSGNode* node, UpdatePaintNodeData* data) Q_DECL_OVERRIDE; Q_SIGNALS: void sourceChanged(); void smoothChanged(); void enabledChanged(); void activeChanged(); void validChanged(); void selectedChanged(); + void isMaskChanged(); + void colorChanged(); protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; QImage findIcon(const QSize& size); void handleFinished(QNetworkAccessManager* qnam, QNetworkReply* reply); void handleReadyRead(QNetworkReply* reply); QIcon::Mode iconMode() const; + private: + Kirigami::PlatformTheme *m_theme = nullptr; QVariant m_source; bool m_smooth; bool m_changed; bool m_active; bool m_selected; + bool m_isMask; QImage m_loadedImage; + QColor m_color = Qt::transparent; }; #endif diff --git a/src/kirigamiplugin.cpp b/src/kirigamiplugin.cpp index 476acf80..df64416e 100644 --- a/src/kirigamiplugin.cpp +++ b/src/kirigamiplugin.cpp @@ -1,128 +1,140 @@ /* * Copyright 2009 by Alan Alpert * Copyright 2010 by Ménard Alexis * Copyright 2010 by Marco Martin * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kirigamiplugin.h" #include "enums.h" #include "desktopicon.h" #include "settings.h" #include #include #include +#ifdef KIRIGAMI_BUILD_TYPE_STATIC +#include "libkirigami/platformtheme.h" +#else +#include +#endif + static QString s_selectedStyle; QUrl KirigamiPlugin::componentUrl(const QString &fileName) const { foreach (const QString &style, m_stylesFallbackChain) { const QString candidate = QStringLiteral("styles/") + style + QLatin1Char('/') + fileName; if (QFile::exists(resolveFilePath(candidate))) { return QUrl(resolveFileUrl(candidate)); } } return QUrl(resolveFileUrl(fileName)); } void KirigamiPlugin::registerTypes(const char *uri) { Q_ASSERT(uri == QLatin1String("org.kde.kirigami")); const QString style = QString::fromLatin1(qgetenv("QT_QUICK_CONTROLS_STYLE")); //org.kde.desktop.plasma is a couple of files that fall back to desktop by purpose if ((style.isEmpty() || style == QStringLiteral("org.kde.desktop.plasma")) && QFile::exists(resolveFilePath(QStringLiteral("/styles/org.kde.desktop")))) { #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) m_stylesFallbackChain.prepend(QStringLiteral("org.kde.desktop")); #elif defined(Q_OS_ANDROID) - m_stylesFallbackChain.prepend(QStringLiteral("material")); + m_stylesFallbackChain.prepend(QStringLiteral("Material")); #else // do we have an iOS specific style? - m_stylesFallbackChain.prepend(QStringLiteral("material")); + m_stylesFallbackChain.prepend(QStringLiteral("Material")); #endif } if (!style.isEmpty() && QFile::exists(resolveFilePath(QStringLiteral("/styles/") + style))) { m_stylesFallbackChain.prepend(style); //if we have plasma deps installed, use them for extra integration if (style == QStringLiteral("org.kde.desktop") && QFile::exists(resolveFilePath(QStringLiteral("/styles/org.kde.desktop.plasma")))) { m_stylesFallbackChain.prepend("org.kde.desktop.plasma"); } } //At this point the fallback chain will be selected->org.kde.desktop->Fallback + Kirigami::PlatformTheme::setFallbackThemeQmlPath(componentUrl(QStringLiteral("Theme.qml"))); - //TODO: in this plugin it will end up something similar to - //PlasmaCore's ColorScope? s_selectedStyle = m_stylesFallbackChain.first(); qmlRegisterSingletonType(uri, 2, 0, "Settings", [](QQmlEngine*, QJSEngine*) -> QObject* { Settings *settings = new Settings; settings->setStyle(s_selectedStyle); return settings; } ); qmlRegisterUncreatableType(uri, 2, 0, "ApplicationHeaderStyle", "Cannot create objects of type ApplicationHeaderStyle"); qmlRegisterSingletonType(componentUrl(QStringLiteral("Theme.qml")), uri, 2, 0, "Theme"); + //Theme changed from a singleton to an attached property + qmlRegisterUncreatableType(uri, 2, 2, "Theme", "Cannot create objects of type Theme, use it as an attached poperty"); qmlRegisterSingletonType(componentUrl(QStringLiteral("Units.qml")), uri, 2, 0, "Units"); qmlRegisterType(componentUrl(QStringLiteral("Action.qml")), uri, 2, 0, "Action"); qmlRegisterType(componentUrl(QStringLiteral("AbstractApplicationHeader.qml")), uri, 2, 0, "AbstractApplicationHeader"); qmlRegisterType(componentUrl(QStringLiteral("AbstractApplicationWindow.qml")), uri, 2, 0, "AbstractApplicationWindow"); qmlRegisterType(componentUrl(QStringLiteral("AbstractListItem.qml")), uri, 2, 0, "AbstractListItem"); qmlRegisterType(componentUrl(QStringLiteral("ApplicationHeader.qml")), uri, 2, 0, "ApplicationHeader"); qmlRegisterType(componentUrl(QStringLiteral("ToolBarApplicationHeader.qml")), uri, 2, 0, "ToolBarApplicationHeader"); qmlRegisterType(componentUrl(QStringLiteral("ApplicationWindow.qml")), uri, 2, 0, "ApplicationWindow"); qmlRegisterType(componentUrl(QStringLiteral("BasicListItem.qml")), uri, 2, 0, "BasicListItem"); qmlRegisterType(componentUrl(QStringLiteral("OverlayDrawer.qml")), uri, 2, 0, "OverlayDrawer"); qmlRegisterType(componentUrl(QStringLiteral("ContextDrawer.qml")), uri, 2, 0, "ContextDrawer"); qmlRegisterType(componentUrl(QStringLiteral("GlobalDrawer.qml")), uri, 2, 0, "GlobalDrawer"); qmlRegisterType(componentUrl(QStringLiteral("Heading.qml")), uri, 2, 0, "Heading"); qmlRegisterType(componentUrl(QStringLiteral("Separator.qml")), uri, 2, 0, "Separator"); qmlRegisterType(componentUrl(QStringLiteral("PageRow.qml")), uri, 2, 0, "PageRow"); //The icon is "special: we have to use a wrapper class to QIcon on org.kde.desktops #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) - qmlRegisterType(uri, 2, 0, "Icon"); + //we know that we want a different implementation with Material and Plasma styles + if (s_selectedStyle == QStringLiteral("Material") || s_selectedStyle == QStringLiteral("Plasma")) { + qmlRegisterType(componentUrl(QStringLiteral("Icon.qml")), uri, 2, 0, "Icon"); + } else { + qmlRegisterType(uri, 2, 0, "Icon"); + } #else qmlRegisterType(componentUrl(QStringLiteral("Icon.qml")), uri, 2, 0, "Icon"); #endif qmlRegisterType(componentUrl(QStringLiteral("Label.qml")), uri, 2, 0, "Label"); //TODO: uncomment for 2.3 release //qmlRegisterTypeNotAvailable(uri, 2, 3, "Label", "Label type not supported anymore, use QtQuick.Controls.Label 2.0 instead"); qmlRegisterType(componentUrl(QStringLiteral("OverlaySheet.qml")), uri, 2, 0, "OverlaySheet"); qmlRegisterType(componentUrl(QStringLiteral("Page.qml")), uri, 2, 0, "Page"); qmlRegisterType(componentUrl(QStringLiteral("ScrollablePage.qml")), uri, 2, 0, "ScrollablePage"); qmlRegisterType(componentUrl(QStringLiteral("SplitDrawer.qml")), uri, 2, 0, "SplitDrawer"); qmlRegisterType(componentUrl(QStringLiteral("SwipeListItem.qml")), uri, 2, 0, "SwipeListItem"); //2.1 qmlRegisterType(componentUrl(QStringLiteral("AbstractItemViewHeader.qml")), uri, 2, 1, "AbstractItemViewHeader"); qmlRegisterType(componentUrl(QStringLiteral("ItemViewHeader.qml")), uri, 2, 1, "ItemViewHeader"); qmlRegisterType(componentUrl(QStringLiteral("AbstractApplicationItem.qml")), uri, 2, 1, "AbstractApplicationItem"); qmlRegisterType(componentUrl(QStringLiteral("ApplicationItem.qml")), uri, 2, 1, "ApplicationItem"); qmlProtectModule(uri, 2); } #include "moc_kirigamiplugin.cpp" diff --git a/src/libkirigami/CMakeLists.txt b/src/libkirigami/CMakeLists.txt new file mode 100644 index 00000000..698d0adf --- /dev/null +++ b/src/libkirigami/CMakeLists.txt @@ -0,0 +1,85 @@ + + +set(libkirigami_SRCS + platformtheme.cpp + basictheme.cpp + kirigamipluginfactory.cpp +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +ecm_qt_declare_logging_category(libkirigami_SRCS + HEADER loggingcategory.h + IDENTIFIER KirigamiLog + CATEGORY_NAME kf5.kirigami + DEFAULT_SEVERITY Warning +) + +add_library(KF5Kirigami2 ${libkirigami_SRCS}) +generate_export_header(KF5Kirigami2 BASE_NAME Kirigami2) +add_library(KF5::Kirigami2 ALIAS KF5Kirigami2) + +target_include_directories(KF5Kirigami2 + INTERFACE "$" +) + +target_link_libraries(KF5Kirigami2 + PUBLIC + Qt5::Core + PRIVATE + Qt5::Qml + Qt5::Quick + Qt5::QuickControls2 +) + +set_target_properties(KF5Kirigami2 PROPERTIES + VERSION ${KIRIGAMI_VERSION_STRING} + SOVERSION ${KIRIGAMI_SOVERSION} + EXPORT_NAME "Kirigami2" +) + +ecm_generate_headers(Kirigami2_HEADERS + HEADER_NAMES + PlatformTheme + KirigamiPluginFactory + + REQUIRED_HEADERS Kirigami2_HEADERS +) + +install(TARGETS KF5Kirigami2 + EXPORT KF5Kirigami2Targets + ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) + + +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/kirigami2_export.h + ${Kirigami2_HEADERS} + DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/Kirigami2 + COMPONENT Devel) + +if(BUILD_QCH) + ecm_add_qch( + KF5Kirigami2_QCH + NAME Kirigami2 + BASE_NAME KF5Kirigami2 + VERSION ${KF5_VERSION} + ORG_DOMAIN org.kde + SOURCES # using only public headers, to cover only public API + ${Kirigami2_HEADERS} + MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md" + LINK_QCHS + Qt5Core_QCH + BLANK_MACROS + KIRIGAMI_EXPORT + KIRIGAMI_DEPRECATED + TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} + QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} + COMPONENT Devel + ) +endif() + +include(ECMGeneratePriFile) +ecm_generate_pri_file(BASE_NAME Kirigami2 LIB_NAME KF5Kirigami2 DEPS "core" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/Kirigami2) +install(FILES ${PRI_FILENAME} + DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) + diff --git a/src/libkirigami/basictheme.cpp b/src/libkirigami/basictheme.cpp new file mode 100644 index 00000000..59b7bcf1 --- /dev/null +++ b/src/libkirigami/basictheme.cpp @@ -0,0 +1,295 @@ +/* +* Copyright (C) 2017 by Marco Martin +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Library General Public License for more details +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "basictheme_p.h" +#include +#include +#include +#include +#include +#include +#include + +namespace Kirigami { + +class BasicThemeDeclarativeSingleton +{ +public: + BasicThemeDeclarativeSingleton() + {} + + BasicThemeDeclarative self; +}; + +Q_GLOBAL_STATIC(BasicThemeDeclarativeSingleton, privateBasicThemeDeclarativeSelf) + +BasicThemeDeclarative::BasicThemeDeclarative() +{ + m_colorSyncTimer = new QTimer; + m_colorSyncTimer->setInterval(0); + m_colorSyncTimer->setSingleShot(true); +} + +BasicThemeDeclarative::~BasicThemeDeclarative() +{ + delete m_colorSyncTimer; +} + +void BasicThemeDeclarative::setQmlPath(const QUrl &path) +{ + m_qmlPath = path; +} + +QUrl BasicThemeDeclarative::qmlPath() const +{ + return m_qmlPath; +} + +QObject *BasicThemeDeclarative::instance(const BasicTheme *theme) +{ + if (m_declarativeBasicTheme) { + return m_declarativeBasicTheme; + } + + QQmlEngine *engine = qmlEngine(theme->parent()); + Q_ASSERT(engine); + + QQmlComponent c(engine); + c.loadUrl(m_qmlPath); + + m_declarativeBasicTheme = c.create(); + + return m_declarativeBasicTheme; +} + + + +BasicTheme::BasicTheme(QObject *parent) + : PlatformTheme(parent) +{ + //TODO: correct? + connect(qApp, &QGuiApplication::fontDatabaseChanged, this, [this]() {setDefaultFont(qApp->font());}); + + //connect all the declarative object signals to the timer start to compress, use the old syntax as they are all signals defined in QML + connect(basicThemeDeclarative()->instance(this), SIGNAL(textColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(disabledTextColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(highlightColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(highlightedTextColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(backgroundColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(linkColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(visitedLinkColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + + connect(basicThemeDeclarative()->instance(this), SIGNAL(buttonTextColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(buttonBackgroundColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(buttonHoverColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(buttonFocusColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + + connect(basicThemeDeclarative()->instance(this), SIGNAL(viewTextColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(viewBackgroundColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(viewHoverColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(viewFocusColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + + connect(basicThemeDeclarative()->instance(this), SIGNAL(complementaryTextColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(complementaryBackgroundColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(complementaryHoverColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + connect(basicThemeDeclarative()->instance(this), SIGNAL(complementaryFocusColorChanged()), + basicThemeDeclarative()->m_colorSyncTimer, SLOT(start())); + + //finally connect the timer to the sync + connect(basicThemeDeclarative()->m_colorSyncTimer, &QTimer::timeout, + this, &BasicTheme::syncColors); + connect(this, &BasicTheme::colorSetChanged, + this, [this]() { + syncColors(); + if (basicThemeDeclarative()->instance(this)) { + QMetaObject::invokeMethod(basicThemeDeclarative()->instance(this), "__propagateColorSet", Q_ARG(QVariant, QVariant::fromValue(this->parent())), Q_ARG(QVariant, colorSet())); + } + }); + syncColors(); +} + +BasicTheme::~BasicTheme() +{ +} + +QStringList BasicTheme::keys() const +{ + QStringList props; + for (int i = metaObject()->propertyOffset(); i < metaObject()->propertyCount(); ++i) { + const QString prop = metaObject()->property(i).name(); + if (prop != "keys") { + props << prop; + } + } + return props; +} + +//TODO: tint for which we need to chain to m_parentBasicTheme's color +#define RESOLVECOLOR(colorName, upperCaseColor) \ + QColor color;\ + switch (colorSet()) {\ + case BasicTheme::Button:\ + color = basicThemeDeclarative()->instance(this)->property("button"#upperCaseColor).value();\ + break;\ + case BasicTheme::View:\ + color = basicThemeDeclarative()->instance(this)->property("view"#upperCaseColor).value();\ + break;\ + case BasicTheme::Selection:\ + color = basicThemeDeclarative()->instance(this)->property("selection"#upperCaseColor).value();\ + break;\ + case BasicTheme::Tooltip:\ + color = basicThemeDeclarative()->instance(this)->property("tooltip"#upperCaseColor).value();\ + break;\ + case BasicTheme::Complementary:\ + color = basicThemeDeclarative()->instance(this)->property("complementary"#upperCaseColor).value();\ + break;\ + case BasicTheme::Window:\ + default:\ + color = basicThemeDeclarative()->instance(this)->property(#colorName).value();\ + }\ + + +#define PROXYCOLOR(colorName, upperCaseColor) \ + basicThemeDeclarative()->instance(this)->property(#colorName).value() + + +void BasicTheme::syncColors() +{ + { + RESOLVECOLOR(textColor, TextColor); + setTextColor(color); + }{ + setDisabledTextColor(PROXYCOLOR(disabledTextColor, DisabledTextColor)); + }{ + RESOLVECOLOR(backgroundColor, BackgroundColor) + setBackgroundColor(color); + }{ + setHighlightColor(PROXYCOLOR(highlightColor, HighlightColor)); + }{ + setHighlightedTextColor(PROXYCOLOR(highlightedTextColor, HighlightedTextColor)); + }{ + setActiveTextColor(PROXYCOLOR(activeTextColor, ActiveTextColor)); + }{ + setLinkColor(PROXYCOLOR(linkColor, LinkColor)); + }{ + setVisitedLinkColor(PROXYCOLOR(visitedLinkColor, VisitedLinkColor)); + }{ + setNegativeTextColor(PROXYCOLOR(negativeTextColor, NegativeTextColor)); + }{ + setNeutralTextColor(PROXYCOLOR(neutralTextColor, NeutralTextColor)); + }{ + setPositiveTextColor(PROXYCOLOR(positiveTextColor, PositiveTextColor)); + }{ + RESOLVECOLOR(hoverColor, HoverColor); + setHoverColor(color); + }{ + RESOLVECOLOR(focusColor, FocusColor); + setFocusColor(color); + } + + //legacy + { + m_buttonTextColor = PROXYCOLOR(buttonTextColor, ButtonTextColor); + m_buttonBackgroundColor = PROXYCOLOR(buttonBackgroundColor, ButtonBackgroundColor); + m_buttonHoverColor = PROXYCOLOR(buttonHoverColor, ButtonHoverColor); + m_buttonFocusColor = PROXYCOLOR(buttonFocusColor, ButtonFocusColor); + m_viewTextColor = PROXYCOLOR(viewTextColor, ViewTextColor); + m_viewBackgroundColor = PROXYCOLOR(viewBackgroundColor, ViewBackgroundColor); + m_viewHoverColor = PROXYCOLOR(viewHoverColor, ViewHoverColor); + m_viewFocusColor = PROXYCOLOR(viewFocusColor, ViewFocusColor); + } + //TODO: build the qpalette + emit colorsChanged(); +} + +QColor BasicTheme::buttonTextColor() const +{ + qWarning()<<"WARNING: buttonTextColor is deprecated, use textColor with colorSet: Theme.Button instead"; + return m_buttonTextColor; +} + +QColor BasicTheme::buttonBackgroundColor() const +{ + qWarning()<<"WARNING: buttonBackgroundColor is deprecated, use backgroundColor with colorSet: Theme.Button instead"; + return m_buttonBackgroundColor; +} + +QColor BasicTheme::buttonHoverColor() const +{ + qWarning()<<"WARNING: buttonHoverColor is deprecated, use backgroundColor with colorSet: Theme.Button instead"; + return m_buttonHoverColor; +} + +QColor BasicTheme::buttonFocusColor() const +{ + qWarning()<<"WARNING: buttonFocusColor is deprecated, use backgroundColor with colorSet: Theme.Button instead"; + return m_buttonFocusColor; +} + + +QColor BasicTheme::viewTextColor() const +{ + qWarning()<<"WARNING: viewTextColor is deprecated, use backgroundColor with colorSet: Theme.View instead"; + return m_viewTextColor; +} + +QColor BasicTheme::viewBackgroundColor() const +{ + qWarning()<<"WARNING: viewBackgroundColor is deprecated, use backgroundColor with colorSet: Theme.View instead"; + return m_viewBackgroundColor; +} + +QColor BasicTheme::viewHoverColor() const +{ + qWarning()<<"WARNING: viewHoverColor is deprecated, use backgroundColor with colorSet: Theme.View instead"; + return m_viewHoverColor; +} + +QColor BasicTheme::viewFocusColor() const +{ + qWarning()<<"WARNING: viewFocusColor is deprecated, use backgroundColor with colorSet: Theme.View instead"; + return m_viewFocusColor; +} + +BasicThemeDeclarative *BasicTheme::basicThemeDeclarative() +{ + return &privateBasicThemeDeclarativeSelf->self; +} + +} + +#include "moc_basictheme_p.cpp" diff --git a/src/libkirigami/basictheme_p.h b/src/libkirigami/basictheme_p.h new file mode 100644 index 00000000..d38bbd25 --- /dev/null +++ b/src/libkirigami/basictheme_p.h @@ -0,0 +1,105 @@ +/* +* Copyright (C) 2017 by Marco Martin +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Library General Public License for more details +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef BASICTHEME_H +#define BASICTHEME_H + +#include "platformtheme.h" +#include +#include +#include +#include + +namespace Kirigami { + +class BasicTheme; + +class BasicThemeDeclarative +{ +public: + BasicThemeDeclarative(); + virtual ~BasicThemeDeclarative(); + + void setQmlPath(const QUrl &path); + QUrl qmlPath() const; + QObject *instance(const BasicTheme *theme); + + QTimer *m_colorSyncTimer; + +private: + QUrl m_qmlPath; + QObject *m_declarativeBasicTheme = nullptr; +}; + +class BasicTheme : public PlatformTheme +{ + Q_OBJECT + + // colors + Q_PROPERTY(QColor buttonTextColor READ buttonTextColor NOTIFY colorsChanged) + Q_PROPERTY(QColor buttonBackgroundColor READ buttonBackgroundColor NOTIFY colorsChanged) + Q_PROPERTY(QColor buttonHoverColor READ buttonHoverColor NOTIFY colorsChanged) + Q_PROPERTY(QColor buttonFocusColor READ buttonFocusColor NOTIFY colorsChanged) + + Q_PROPERTY(QColor viewTextColor READ viewTextColor NOTIFY colorsChanged) + Q_PROPERTY(QColor viewBackgroundColor READ viewBackgroundColor NOTIFY colorsChanged) + Q_PROPERTY(QColor viewHoverColor READ viewHoverColor NOTIFY colorsChanged) + Q_PROPERTY(QColor viewFocusColor READ viewFocusColor NOTIFY colorsChanged) + + //FIXME: this is due https://bugreports.qt.io/browse/QTBUG-63089 + Q_PROPERTY(QStringList keys READ keys CONSTANT) + +public: + explicit BasicTheme(QObject *parent = 0); + ~BasicTheme(); + + void syncColors(); + + QColor buttonTextColor() const; + QColor buttonBackgroundColor() const; + QColor buttonHoverColor() const; + QColor buttonFocusColor() const; + + QColor viewTextColor() const; + QColor viewBackgroundColor() const; + QColor viewHoverColor() const; + QColor viewFocusColor() const; + + QStringList keys() const; + + static BasicThemeDeclarative *basicThemeDeclarative(); + +Q_SIGNALS: + void colorsChanged(); + +private: + //legacy colors + QColor m_buttonTextColor; + QColor m_buttonBackgroundColor; + QColor m_buttonHoverColor; + QColor m_buttonFocusColor; + QColor m_viewTextColor; + QColor m_viewBackgroundColor; + QColor m_viewHoverColor; + QColor m_viewFocusColor; +}; + +} + +#endif // BASICTHEME_H diff --git a/src/libkirigami/kirigamipluginfactory.cpp b/src/libkirigami/kirigamipluginfactory.cpp new file mode 100644 index 00000000..ae492760 --- /dev/null +++ b/src/libkirigami/kirigamipluginfactory.cpp @@ -0,0 +1,39 @@ +/* +* Copyright (C) 2017 by Marco Martin +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Library General Public License for more details +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "kirigamipluginfactory.h" +#include "platformtheme.h" + +#include + + +namespace Kirigami { + +KirigamiPluginFactory::KirigamiPluginFactory(QObject *parent) + : QObject(parent) +{ +} + +KirigamiPluginFactory::~KirigamiPluginFactory() +{ +} + +} + +#include "moc_kirigamipluginfactory.cpp" diff --git a/src/libkirigami/kirigamipluginfactory.h b/src/libkirigami/kirigamipluginfactory.h new file mode 100644 index 00000000..93754800 --- /dev/null +++ b/src/libkirigami/kirigamipluginfactory.h @@ -0,0 +1,65 @@ +/* +* Copyright (C) 2017 by Marco Martin +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Library General Public License for more details +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef KIRIGAMIPLUGINFACTORY_H +#define KIRIGAMIPLUGINFACTORY_H + +#include "platformtheme.h" +#include + +#ifndef KIRIGAMI_BUILD_TYPE_STATIC +#include +#endif + +namespace Kirigami { + +/** + * @class KirigamiPluginFactory kirigamipluginfactory.h KirigamiPluginFactory + * + * This class is reimpleented by plugins to provide different implementations + * of PlatformTheme + */ +#ifdef KIRIGAMI_BUILD_TYPE_STATIC +class KirigamiPluginFactory : public QObject +#else +class KIRIGAMI2_EXPORT KirigamiPluginFactory : public QObject +#endif +{ + Q_OBJECT + +public: + explicit KirigamiPluginFactory(QObject *parent = nullptr); + ~KirigamiPluginFactory(); + + /** + * Creates an instance of PlatformTheme which can come out from + * an implementation provided by a plugin + * @param parent the parent object of the created PlatformTheme + */ + virtual PlatformTheme *createPlatformTheme(QObject *parent) = 0; +}; + +} + +QT_BEGIN_NAMESPACE +#define KirigamiPluginFactory_iid "org.kde.kirigami.KirigamiPluginFactory" +Q_DECLARE_INTERFACE(Kirigami::KirigamiPluginFactory, KirigamiPluginFactory_iid) +QT_END_NAMESPACE + +#endif //KIRIGAMIPLUGINFACTORY_H diff --git a/src/libkirigami/platformtheme.cpp b/src/libkirigami/platformtheme.cpp new file mode 100644 index 00000000..b1747a00 --- /dev/null +++ b/src/libkirigami/platformtheme.cpp @@ -0,0 +1,455 @@ +/* +* Copyright (C) 2017 by Marco Martin +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Library General Public License for more details +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "platformtheme.h" +#include "kirigamipluginfactory.h" +#include "basictheme_p.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Kirigami { + +class PlatformThemePrivate { +public: + PlatformThemePrivate(PlatformTheme *q); + ~PlatformThemePrivate(); + + void findParentStyle(); + static QColor tint(const QColor &c1, const QColor &c2, qreal ratio); + + + PlatformTheme *q; + QTimer *setColorCompressTimer; + PlatformTheme::ColorSet m_colorSet = PlatformTheme::Window; + QSet m_childThemes; + QPointer m_parentTheme; + + QColor textColor; + QColor disabledTextColor; + QColor highlightedTextColor; + QColor activeTextColor; + QColor linkColor; + QColor visitedLinkColor; + QColor negativeTextColor; + QColor neutralTextColor; + QColor positiveTextColor; + + QColor backgroundColor; + QColor highlightColor; + + QColor focusColor; + QColor hoverColor; + + QFont font; + QPalette palette; + bool m_inherit = true; +}; + +PlatformThemePrivate::PlatformThemePrivate(PlatformTheme *q) + : q(q) +{ + setColorCompressTimer = new QTimer(q); + setColorCompressTimer->setSingleShot(true); + setColorCompressTimer->setInterval(0); +} + +PlatformThemePrivate::~PlatformThemePrivate() +{} + +void PlatformThemePrivate::findParentStyle() +{ + if (m_parentTheme) { + m_parentTheme->d->m_childThemes.remove(q); + } + QQuickItem *candidate = qobject_cast(q->parent()); + while (candidate) { + candidate = candidate->parentItem(); + PlatformTheme *t = static_cast(qmlAttachedPropertiesObject(candidate, false)); + if (t) { + t->d->m_childThemes.insert(q); + m_parentTheme = t; + if (m_inherit) { + q->setColorSet(t->colorSet()); + } + break; + } + + } +} + +QColor PlatformThemePrivate::tint(const QColor &c1, const QColor &c2, qreal ratio) +{ + qreal r = c1.redF() + (c2.redF() - c1.redF()) * ratio; + qreal g = c1.greenF() + (c2.greenF() - c1.greenF()) * ratio; + qreal b = c1.blueF() + (c2.blueF() - c1.blueF()) * ratio; + + return QColor::fromRgbF(r, g, b, 1); +} + + + + +PlatformTheme::PlatformTheme(QObject *parent) + : QObject(parent), + d(new PlatformThemePrivate(this)) +{ + connect(d->setColorCompressTimer, &QTimer::timeout, + this, &PlatformTheme::colorsChanged); + d->findParentStyle(); + + if (QQuickItem *item = qobject_cast(parent)) { + connect(item, &QQuickItem::windowChanged, this, [this]() { + d->findParentStyle(); + }); + connect(item, &QQuickItem::parentChanged, this, [this]() { + d->findParentStyle(); + }); + } + //TODO: needs https://codereview.qt-project.org/#/c/206889/ for font changes +} + +PlatformTheme::~PlatformTheme() +{ + if (d->m_parentTheme) { + d->m_parentTheme->d->m_childThemes.remove(this); + } +} + +void PlatformTheme::setColorSet(PlatformTheme::ColorSet colorSet) +{ + if (d->m_colorSet == colorSet) { + return; + } + + d->m_colorSet = colorSet; + + for (PlatformTheme *t : d->m_childThemes) { + if (t->inherit()) { + t->setColorSet(colorSet); + } + } + + emit colorSetChanged(colorSet); + d->setColorCompressTimer->start(); +} + +PlatformTheme::ColorSet PlatformTheme::colorSet() const +{ + return d->m_colorSet; +} + +bool PlatformTheme::inherit() const +{ + return d->m_inherit; +} + +void PlatformTheme::setInherit(bool inherit) +{ + if (d->m_inherit == inherit) { + return; + } + + d->m_inherit = inherit; + if (inherit && d->m_parentTheme) { + setColorSet(d->m_parentTheme->colorSet()); + } + emit inheritChanged(inherit); +} + + +QColor PlatformTheme::textColor() const +{ + return d->textColor; +} + +QColor PlatformTheme::disabledTextColor() const +{ + return d->disabledTextColor; +} + +QColor PlatformTheme::highlightColor() const +{ + return d->highlightColor; +} + +QColor PlatformTheme::highlightedTextColor() const +{ + return d->highlightedTextColor; +} + +QColor PlatformTheme::backgroundColor() const +{ + return d->backgroundColor; +} + +QColor PlatformTheme::activeTextColor() const +{ + return d->activeTextColor; +} + +QColor PlatformTheme::linkColor() const +{ + return d->linkColor; +} + +QColor PlatformTheme::visitedLinkColor() const +{ + return d->visitedLinkColor; +} + +QColor PlatformTheme::negativeTextColor() const +{ + return d->negativeTextColor; +} + +QColor PlatformTheme::neutralTextColor() const +{ + return d->neutralTextColor; +} + +QColor PlatformTheme::positiveTextColor() const +{ + return d->positiveTextColor; +} + +QColor PlatformTheme::focusColor() const +{ + return d->focusColor; +} + +QColor PlatformTheme::hoverColor() const +{ + return d->hoverColor; +} + + +void PlatformTheme::setTextColor(const QColor &color) +{ + if (d->textColor == color) { + return; + } + + d->textColor = color; + d->setColorCompressTimer->start(); +} + +void PlatformTheme::setDisabledTextColor(const QColor &color) +{ + if (d->disabledTextColor == color) { + return; + } + + d->disabledTextColor = color; + d->setColorCompressTimer->start(); +} + +void PlatformTheme::setBackgroundColor(const QColor &color) +{ + if (d->backgroundColor == color) { + return; + } + + d->backgroundColor = color; + d->setColorCompressTimer->start(); +} + +void PlatformTheme::setHighlightColor(const QColor &color) +{ + if (d->highlightColor == color) { + return; + } + + d->highlightColor = color; + d->setColorCompressTimer->start(); +} + +void PlatformTheme::setHighlightedTextColor(const QColor &color) +{ + if (d->highlightedTextColor == color) { + return; + } + + d->highlightedTextColor = color; + d->setColorCompressTimer->start(); +} + +void PlatformTheme::setActiveTextColor(const QColor &color) +{ + if (d->activeTextColor == color) { + return; + } + + d->activeTextColor = color; + d->setColorCompressTimer->start(); +} + +void PlatformTheme::setLinkColor(const QColor &color) +{ + if (d->linkColor == color) { + return; + } + + d->linkColor = color; + d->setColorCompressTimer->start(); +} + +void PlatformTheme::setVisitedLinkColor(const QColor &color) +{ + if (d->visitedLinkColor == color) { + return; + } + + d->visitedLinkColor = color; + d->setColorCompressTimer->start(); +} + +void PlatformTheme::setNegativeTextColor(const QColor &color) +{ + if (d->negativeTextColor == color) { + return; + } + + d->negativeTextColor = color; + d->setColorCompressTimer->start(); +} + +void PlatformTheme::setNeutralTextColor(const QColor &color) +{ + if (d->neutralTextColor == color) { + return; + } + + d->neutralTextColor = color; + d->setColorCompressTimer->start(); +} + +void PlatformTheme::setPositiveTextColor(const QColor &color) +{ + if (d->positiveTextColor == color) { + return; + } + + d->positiveTextColor = color; + d->setColorCompressTimer->start(); +} + +void PlatformTheme::setHoverColor(const QColor &color) +{ + if (d->hoverColor == color) { + return; + } + + d->hoverColor = color; + d->setColorCompressTimer->start(); +} + +void PlatformTheme::setFocusColor(const QColor &color) +{ + if (d->focusColor == color) { + return; + } + + d->focusColor = color; + d->setColorCompressTimer->start(); +} + +QFont PlatformTheme::defaultFont() const +{ + return d->font; +} + +void PlatformTheme::setDefaultFont(const QFont &font) +{ + if (d->font == font) { + return; + } + + d->font = font; + emit defaultFontChanged(font); +} + +QPalette PlatformTheme::palette() const +{ + return d->palette; +} + +void PlatformTheme::setPalette(const QPalette &palette) +{ + if (d->palette == palette) { + return; + } + + d->palette = palette; + emit paletteChanged(palette); +} + +QIcon PlatformTheme::iconFromTheme(const QString &name, const QColor &customColor) +{ + QIcon icon = QIcon::fromTheme(name); + if (name.endsWith("-symbolic") || customColor != Qt::transparent) { + icon.setIsMask(true); + } + return icon; +} + + + +PlatformTheme *PlatformTheme::qmlAttachedProperties(QObject *object) +{ + for (const QString &path : QCoreApplication::libraryPaths()) { + QDir dir(path + "/kf5/kirigami"); + for (const QString &fileName : dir.entryList(QDir::Files)) { + //TODO: env variable? + if (fileName.startsWith(QQuickStyle::name())) { + QPluginLoader loader(dir.absoluteFilePath(fileName)); + QObject *plugin = loader.instance(); + //TODO: load actually a factory as plugin + + KirigamiPluginFactory *factory = qobject_cast(plugin); + if (factory) { + return factory->createPlatformTheme(object); + } + } + } + } + + return new BasicTheme(object); +} + +void PlatformTheme::setFallbackThemeQmlPath(const QUrl &path) +{ + BasicTheme::basicThemeDeclarative()->setQmlPath(path); +} + +QUrl PlatformTheme::fallbackThemeQmlPath() +{ + return BasicTheme::basicThemeDeclarative()->qmlPath(); +} + +} + +#include "moc_platformtheme.cpp" diff --git a/src/libkirigami/platformtheme.h b/src/libkirigami/platformtheme.h new file mode 100644 index 00000000..623e0365 --- /dev/null +++ b/src/libkirigami/platformtheme.h @@ -0,0 +1,239 @@ +/* +* Copyright (C) 2017 by Marco Martin +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Library General Public License for more details +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef PLATFORMTHEME_H +#define PLATFORMTHEME_H + +#include +#include +#include +#include + +#ifndef KIRIGAMI_BUILD_TYPE_STATIC +#include +#endif + +namespace Kirigami { + +class PlatformThemePrivate; + +/** + * @class PlatformTheme platformtheme.h PlatformTheme + * + * This class is the base for color management in Kirigami, + * different platforms can reimplement this class to integrate with + * system platform colors of a given platform + */ +#ifdef KIRIGAMI_BUILD_TYPE_STATIC +class PlatformTheme : public QObject +#else +class KIRIGAMI2_EXPORT PlatformTheme : public QObject +#endif +{ + Q_OBJECT + + /** + * This enumeration describes the color set for which a color is being selected. + * + * Color sets define a color "environment", suitable for drawing all parts of a + * given region. Colors from different sets should not be combined. + */ + Q_PROPERTY(ColorSet colorSet READ colorSet WRITE setColorSet NOTIFY colorSetChanged) + + /** + * If true, the colorSet will be inherited from the colorset of a theme of one + * of the ancestor items + * default: true + */ + Q_PROPERTY(bool inherit READ inherit WRITE setInherit NOTIFY inheritChanged) + + // foreground colors + /** + * Color for normal foregrounds, usually text, but not limited to it, + * anything that should be painted with a clear contrast should use this color + */ + Q_PROPERTY(QColor textColor READ textColor NOTIFY colorsChanged) + + /** + * Foreground color for disabled areas, usually a mid-gray + */ + Q_PROPERTY(QColor disabledTextColor READ disabledTextColor NOTIFY colorsChanged) + + /** + * Color for text that has been highlighted, often is a light color while normal text is dark + */ + Q_PROPERTY(QColor highlightedTextColor READ highlightedTextColor NOTIFY colorsChanged) + + /** + * Foreground for areas that are active or requesting attention + */ + Q_PROPERTY(QColor activeTextColor READ activeTextColor NOTIFY colorsChanged) + + /** + * Color for links + */ + Q_PROPERTY(QColor linkColor READ linkColor NOTIFY colorsChanged) + + /** + * Color for visited links, usually a bit darker than linkColor + */ + Q_PROPERTY(QColor visitedLinkColor READ visitedLinkColor NOTIFY colorsChanged) + + /** + * Foreground color for negative areas, such as critical error text + */ + Q_PROPERTY(QColor negativeTextColor READ negativeTextColor NOTIFY colorsChanged) + + /** + * Foreground color for neutral areas, such as warning texts (but not critical) + */ + Q_PROPERTY(QColor neutralTextColor READ neutralTextColor NOTIFY colorsChanged) + + /** + * Success messages, trusted content + */ + Q_PROPERTY(QColor positiveTextColor READ positiveTextColor NOTIFY colorsChanged) + + //background colors + /** + * The generic background color + */ + Q_PROPERTY(QColor backgroundColor READ backgroundColor NOTIFY colorsChanged) + + /** + * The background color for selected areas + */ + Q_PROPERTY(QColor highlightColor READ highlightColor NOTIFY colorsChanged) + + //decoration colors + /** + * A decoration color that indicates active focus + */ + Q_PROPERTY(QColor focusColor READ focusColor NOTIFY colorsChanged) + + /** + * A decoration color that indicates mouse hovering + */ + Q_PROPERTY(QColor hoverColor READ hoverColor NOTIFY colorsChanged) + + // font and palette + Q_PROPERTY(QFont defaultFont READ defaultFont NOTIFY defaultFontChanged) + Q_PROPERTY(QPalette palette READ palette NOTIFY paletteChanged) + + Q_ENUMS(ColorSet) + +public: + + enum ColorSet { + View = 0, /** Color set for item views, usually the lightest of all */ + Window, /** Default Color set for windows and "chrome" areas */ + Button, /** Color set used by buttons */ + Selection, /** Color set used by selectged areas */ + Tooltip, /** Color set used by tooltips */ + Complementary /** Color set meant to be complementary to Window: usually is a dark theme for light themes */ + }; + + explicit PlatformTheme(QObject *parent = 0); + ~PlatformTheme(); + + void setColorSet(PlatformTheme::ColorSet); + PlatformTheme::ColorSet colorSet() const; + + bool inherit() const; + void setInherit(bool inherit); + + //foreground colors + QColor textColor() const; + QColor disabledTextColor() const; + QColor highlightedTextColor() const; + QColor activeTextColor() const; + QColor linkColor() const; + QColor visitedLinkColor() const; + QColor negativeTextColor() const; + QColor neutralTextColor() const; + QColor positiveTextColor() const; + + //background colors + QColor backgroundColor() const; + QColor highlightColor() const; + //TODO: add active/positive/neutral/negative backgrounds? + + //decoration colors + QColor focusColor() const; + QColor hoverColor() const; + + //Setters, not accessible from QML but from implementations + + //foreground colors + void setTextColor(const QColor &color); + void setDisabledTextColor(const QColor &color); + void setHighlightedTextColor(const QColor &color); + void setActiveTextColor(const QColor &color); + void setLinkColor(const QColor &color); + void setVisitedLinkColor(const QColor &color); + void setNegativeTextColor(const QColor &color); + void setNeutralTextColor(const QColor &color); + void setPositiveTextColor(const QColor &color); + + //background colors + void setBackgroundColor(const QColor &color); + void setHighlightColor(const QColor &color); + + //decoration colors + void setFocusColor(const QColor &color); + void setHoverColor(const QColor &color); + + + QFont defaultFont() const; + void setDefaultFont(const QFont &defaultFont); + + QPalette palette() const; + void setPalette(const QPalette &palette); + + //this will be used by desktopicon to fetch icons with KIconLoader + virtual Q_INVOKABLE QIcon iconFromTheme(const QString &name, const QColor &customColor = Qt::transparent); + //this may be used somehow by the desktop QQC2 to set the styleoption palettes + + //QML attached property + static PlatformTheme *qmlAttachedProperties(QObject *object); + + /** + * @internal + */ + static void setFallbackThemeQmlPath(const QUrl &path); + static QUrl fallbackThemeQmlPath(); + +Q_SIGNALS: + //TODO: parameters to signals as this is also a c++ api + void colorsChanged(); + void defaultFontChanged(const QFont &font); + void colorSetChanged(Kirigami::PlatformTheme::ColorSet colorSet); + void paletteChanged(const QPalette &pal); + void inheritChanged(bool inherit); + +private: + PlatformThemePrivate *d; + friend class PlatformThemePrivate; +}; + +} + +QML_DECLARE_TYPEINFO(Kirigami::PlatformTheme, QML_HAS_ATTACHED_PROPERTIES) + +#endif // PLATFORMTHEME_H diff --git a/src/styles/Material/AbstractListItem.qml b/src/styles/Material/AbstractListItem.qml index 2b6ffd8b..729cd98a 100644 --- a/src/styles/Material/AbstractListItem.qml +++ b/src/styles/Material/AbstractListItem.qml @@ -1,63 +1,42 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.7 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 +import QtQuick.Controls.Material 2.1 as Mat +import QtQuick.Controls.Material.impl 2.1 as MatImp import "../../private" import "../../templates" as T T.AbstractListItem { id: listItem - onPressedChanged: { - if (pressed) { - clickAnim.running = true - } - } background: DefaultListItemBackground { - clip: true - //TODO: this will have to reuse QQC2.1 Ripple - Rectangle { - id: ripple - anchors.centerIn: parent - width: parent.width - height: parent.width - radius: width - color: Qt.rgba(1,1,1,0.3) - scale: 0 - opacity: 1 - ParallelAnimation { - id: clickAnim - ScaleAnimator { - target: ripple - from: 0 - to: 1 - duration: Units.longDuration - } - OpacityAnimator { - target: ripple - from: 0 - to: 1 - duration: Units.longDuration - } - } + + MatImp.Ripple { + anchors.fill: parent + clip: visible + pressed: listItem.pressed + anchor: listItem + active: listItem.down || listItem.visualFocus + color: Qt.rgba(0,0,0,0.2) } } implicitHeight: contentItem.implicitHeight + Units.smallSpacing * 6 } diff --git a/src/styles/Material/Label.qml b/src/styles/Material/Label.qml index dca7117c..7c7435d2 100644 --- a/src/styles/Material/Label.qml +++ b/src/styles/Material/Label.qml @@ -1,59 +1,59 @@ /* * Copyright (C) 2011 by Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.1 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import QtQuick.Templates 2.0 as T2 /** * This is a label which uses the plasma Theme. * * The characteristics of the text will be automatically set according to the * plasma Theme. If you need a more customized text item use the Text component * from QtQuick. * * You can use all elements of the QML Text component, in particular the "text" * property to define the label text. * * @inherit QtQuick.Text */ T2.Label { id: root height: Math.round(Math.max(paintedHeight, Units.gridUnit * 1.6)) verticalAlignment: lineCount > 1 ? Text.AlignTop : Text.AlignVCenter activeFocusOnTab: false font.capitalization: Theme.defaultFont.capitalization font.family: Theme.defaultFont.family font.italic: Theme.defaultFont.italic font.letterSpacing: Theme.defaultFont.letterSpacing font.pointSize: Theme.defaultFont.pointSize font.strikeout: Theme.defaultFont.strikeout font.underline: Theme.defaultFont.underline font.weight: Theme.defaultFont.weight font.wordSpacing: Theme.defaultFont.wordSpacing color: Theme.textColor opacity: enabled? 1 : 0.6 Accessible.role: Accessible.StaticText Accessible.name: text } diff --git a/src/styles/Material/SwipeListItem.qml b/src/styles/Material/SwipeListItem.qml index 6e6dd390..5e64dc9f 100644 --- a/src/styles/Material/SwipeListItem.qml +++ b/src/styles/Material/SwipeListItem.qml @@ -1,92 +1,92 @@ /* * Copyright 2010 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.5 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import "../../private" import "../../templates" as T /** * An item delegate Intended to support extra actions obtainable * by uncovering them by dragging away the item with the handle * This acts as a container for normal list items. * Any subclass of AbstractListItem can be assigned as the contentItem property. * @code * ListView { * model: myModel * delegate: SwipeListItem { * Label { * text: model.text * } * actions: [ * Action { * iconName: "document-decrypt" * onTriggered: print("Action 1 clicked") * }, * Action { * iconName: model.action2Icon * onTriggered: //do something * } * ] * } * * } * @endcode * * @inherit QtQuick.Item */ T.SwipeListItem { id: root onPressedChanged: { if (pressed) { clickAnim.running = true } } background: DefaultListItemBackground { clip: true //TODO: this will have to reuse QQC2.1 Ripple Rectangle { id: ripple anchors.centerIn: parent width: parent.width height: parent.width radius: width color: Qt.rgba(1,1,1,0.3) scale: 0 opacity: 1 ParallelAnimation { id: clickAnim ScaleAnimator { target: ripple from: 0 to: 1 duration: Units.longDuration } OpacityAnimator { target: ripple from: 0 to: 1 duration: Units.longDuration } } } } implicitHeight: contentItem.implicitHeight + Units.smallSpacing * 6 } diff --git a/src/styles/Material/Theme.qml b/src/styles/Material/Theme.qml index d0b0404c..3420f72b 100644 --- a/src/styles/Material/Theme.qml +++ b/src/styles/Material/Theme.qml @@ -1,60 +1,93 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.7 import QtQuick.Controls.Material 2.0 +import org.kde.kirigami 2.2 as Kirigami pragma Singleton QtObject { id: theme //NOTE: this is useless per se, but it forces the Material attached property to be created Material.elevation:2 property color textColor: theme.Material.foreground onTextColorChanged: theme.Material.foreground = textColor property color disabledTextColor: "#9931363b" property color highlightColor: theme.Material.accent onHighlightColorChanged: theme.Material.accent = highlightColor //FIXME: something better? property color highlightedTextColor: theme.Material.background property color backgroundColor: theme.Material.background - property color linkColor: "#2196F3" - property color visitedLinkColor: "#2196F3" + property color activeTextColor: theme.Material.primary + property color linkColor: "#2980B9" + property color visitedLinkColor: "#7F8C8D" + property color hoverColor: theme.Material.highlightedButtonColor + property color focusColor: theme.Material.highlightedButtonColor + property color negativeTextColor: "#DA4453" + property color neutralTextColor: "#F67400" + property color positiveTextColor: "#27AE60" property color buttonTextColor: theme.Material.foreground property color buttonBackgroundColor: theme.Material.buttonColor property color buttonHoverColor: theme.Material.highlightedButtonColor property color buttonFocusColor: theme.Material.highlightedButtonColor property color viewTextColor: theme.Material.foreground property color viewBackgroundColor: theme.Material.dialogColor property color viewHoverColor: theme.Material.listHighlightColor property color viewFocusColor: theme.Material.listHighlightColor + property color selectionTextColor: theme.Material.primaryHighlightedTextColor + property color selectionBackgroundColor: theme.Material.textSelectionColor + property color selectionHoverColor: theme.Material.highlightedButtonColor + property color selectionFocusColor: theme.Material.highlightedButtonColor + + property color tooltipTextColor: fontMetrics.Material.foreground + property color tooltipBackgroundColor: fontMetrics.Material.tooltipColor + property color tooltipHoverColor: fontMetrics.Material.highlightedButtonColor + property color tooltipFocusColor: fontMetrics.Material.highlightedButtonColor + + property color complementaryTextColor: fontMetrics.Material.foreground + property color complementaryBackgroundColor: fontMetrics.Material.background + property color complementaryHoverColor: theme.Material.highlightedButtonColor + property color complementaryFocusColor: theme.Material.highlightedButtonColor + property font defaultFont: fontMetrics.font property list children: [ TextMetrics { id: fontMetrics + //this is to get a source of dark colors + Material.theme: Material.Dark } ] + //for internal use + function __propagateColorSet(object, context) { + //TODO: actually check if it's a dark or light color + if (context == Kirigami.Theme.Complementary) { + object.Material.theme = Material.Dark; + } else { + object.Material.theme = Material.Light; + } + } } diff --git a/src/styles/Plasma/Icon.qml b/src/styles/Plasma/Icon.qml index d988d1f8..04878d39 100644 --- a/src/styles/Plasma/Icon.qml +++ b/src/styles/Plasma/Icon.qml @@ -1,34 +1,38 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import org.kde.plasma.core 2.0 as PlasmaCore PlasmaCore.IconItem { property bool selected: false + property bool isMask: false + //TODO: implement in libplasma + property color color: "transparent" usesPlasmaTheme: false + colorGroup: PlasmaCore.ColorScope.colorGroup onSelectedChanged: { if (selected) { status = PlasmaCore.Svg.Selected; } else { status = PlasmaCore.Svg.Normal; } } } diff --git a/src/styles/Plasma/Theme.qml b/src/styles/Plasma/Theme.qml index 542c44f4..b00500b6 100644 --- a/src/styles/Plasma/Theme.qml +++ b/src/styles/Plasma/Theme.qml @@ -1,46 +1,91 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ pragma Singleton import QtQuick 2.4 import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.kirigami 2.2 as Kirigami QtObject { property color textColor: theme.textColor property color disabledTextColor: Qt.rgba(theme.textColor.r, theme.textColor.g, theme.textColor.b, 0.6) property color highlightColor: theme.highlightColor property color highlightedTextColor: theme.highlightedTextColor property color backgroundColor: theme.backgroundColor + //TODO: don't make this invisible + property color activeTextColor: theme.highlightColor property color linkColor: theme.linkColor property color visitedLinkColor: theme.visitedLinkColor + property color negativeTextColor: theme.negativeTextColor + property color neutralTextColor: theme.neutralTextColor + property color positiveTextColor: theme.positiveTextColor property color buttonTextColor: theme.buttonTextColor property color buttonBackgroundColor: theme.buttonBackgroundColor property color buttonHoverColor: theme.buttonHoverColor property color buttonFocusColor: theme.buttonFocusColor property color viewTextColor: theme.viewTextColor property color viewBackgroundColor: theme.viewBackgroundColor property color viewHoverColor: theme.viewHoverColor property color viewFocusColor: theme.viewFocusColor + property color selectionTextColor: theme.highlightedTextColor + property color selectionBackgroundColor: theme.highlightColor + property color selectionHoverColor: theme.buttonHoverColor + property color selectionFocusColor: theme.buttonFocusColor + + property color tooltipTextColor: theme.complementaryTextColor + property color tooltipBackgroundColor: theme.complementaryBackgroundColor + property color tooltipHoverColor: theme.complementaryHoverColor + property color tooltipFocusColor: theme.complementaryFocusColor + + property color complementaryTextColor: theme.complementaryTextColor + property color complementaryBackgroundColor: theme.complementaryBackgroundColor + property color complementaryHoverColor: theme.complementaryHoverColor + property color complementaryFocusColor: theme.complementaryFocusColor + property variant defaultFont: theme.defaultFont + + function __propagateColorSet(object, context) { + object.PlasmaCore.ColorScope.inherit = false; + switch(context) { + case Kirigami.Theme.Window: + object.PlasmaCore.ColorScope.colorGroup = PlasmaCore.Theme.NormalColorGroup; + break; + case Kirigami.Theme.Button: + object.PlasmaCore.ColorScope.colorGroup = PlasmaCore.Theme.ButtonColorGroup; + break; + case Kirigami.Theme.View: + object.PlasmaCore.ColorScope.colorGroup = PlasmaCore.Theme.ViewColorGroup; + break; + case Kirigami.Theme.Selection: + object.PlasmaCore.ColorScope.colorGroup = PlasmaCore.Theme.NormalColorGroup; + break; + case Kirigami.Theme.Tooltip: + object.PlasmaCore.ColorScope.colorGroup = PlasmaCore.Theme.ComplementaryColorGroup; + break; + case Kirigami.Theme.Complementary: + object.PlasmaCore.ColorScope.colorGroup = PlasmaCore.Theme.ComplementaryColorGroup; + break; + } + } } diff --git a/src/styles/org.kde.desktop/AbstractApplicationHeader.qml b/src/styles/org.kde.desktop/AbstractApplicationHeader.qml index bafdfbbb..2263718f 100644 --- a/src/styles/org.kde.desktop/AbstractApplicationHeader.qml +++ b/src/styles/org.kde.desktop/AbstractApplicationHeader.qml @@ -1,52 +1,52 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 -import org.kde.kirigami 2.1 +import org.kde.kirigami 2.2 import "../../templates" as T /** * An item that can be used as a title for the application. * Scrolling the main page will make it taller or shorter (trough the point of going away) * It's a behavior similar to the typical mobile web browser adressbar * the minimum, preferred and maximum heights of the item can be controlled with * * minimumHeight: default is 0, i.e. hidden * * preferredHeight: default is Units.gridUnit * 1.6 * * maximumHeight: default is Units.gridUnit * 3 * * To achieve a titlebar that stays completely fixed just set the 3 sizes as the same */ T.AbstractApplicationHeader { id: root background: Rectangle { color: Theme.backgroundColor Separator { anchors { left: parent.left right: parent.right bottom: root.y <= 0 ? parent.bottom : undefined top: root.y <= 0 ? undefined : parent.top } } } } diff --git a/src/styles/org.kde.desktop/AbstractListItem.qml b/src/styles/org.kde.desktop/AbstractListItem.qml index c2b9f7ce..195b63c8 100644 --- a/src/styles/org.kde.desktop/AbstractListItem.qml +++ b/src/styles/org.kde.desktop/AbstractListItem.qml @@ -1,30 +1,30 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.1 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import "../../private" import "../../templates" as T T.AbstractListItem { id: listItem background: DefaultListItemBackground {} implicitHeight: contentItem.implicitHeight + Units.smallSpacing * 4 } diff --git a/src/styles/org.kde.desktop/ApplicationWindow.qml b/src/styles/org.kde.desktop/ApplicationWindow.qml index 78b29e8d..bc771781 100644 --- a/src/styles/org.kde.desktop/ApplicationWindow.qml +++ b/src/styles/org.kde.desktop/ApplicationWindow.qml @@ -1,30 +1,30 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import "../../" as Base Base.ApplicationWindow { id: root width: Units.gridUnit * 55 height: Units.gridUnit * 40 wideScreen: true } diff --git a/src/styles/org.kde.desktop/OverlayDrawer.qml b/src/styles/org.kde.desktop/OverlayDrawer.qml index 4702968b..7921b631 100644 --- a/src/styles/org.kde.desktop/OverlayDrawer.qml +++ b/src/styles/org.kde.desktop/OverlayDrawer.qml @@ -1,108 +1,108 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtGraphicalEffects 1.0 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import QtQuick.Templates 2.0 import "../../templates" as T /** * Overlay Drawers are used to expose additional UI elements needed for * small secondary tasks for which the main UI elements are not needed. * For example in Okular Active, an Overlay Drawer is used to display * thumbnails of all pages within a document along with a search field. * This is used for the distinct task of navigating to another page. * */ T.OverlayDrawer { id: root //BEGIN Properties background: Rectangle { - color: Theme.viewBackgroundColor + color: Theme.backgroundColor Item { parent: root.handle anchors.fill: parent DropShadow { anchors.fill: handleGraphics horizontalOffset: 0 verticalOffset: Units.devicePixelRatio radius: Units.gridUnit /2 samples: 16 color: Qt.rgba(0, 0, 0, root.handle.pressed ? 0.6 : 0.4) source: handleGraphics } Rectangle { id: handleGraphics anchors.centerIn: parent - color: root.handle.pressed ? Theme.highlightColor : Theme.buttonBackgroundColor + color: root.handle.pressed ? Theme.highlightColor : Theme.backgroundColor width: Units.iconSizes.smallMedium + Units.smallSpacing * 2 height: width radius: Units.devicePixelRatio*2 Loader { anchors.centerIn: parent width: height height: Units.iconSizes.small source: root.edge == Qt.LeftEdge ? Qt.resolvedUrl("../../templates/private/MenuIcon.qml") : (root.edge == Qt.RightEdge ? Qt.resolvedUrl("../../templates/private/ContextIcon.qml") : "") onItemChanged: { if(item) { item.morph = Qt.binding(function(){return root.position}) - item.color = Qt.binding(function(){return root.handle.pressed ? Theme.highlightedTextColor : Theme.buttonTextColor}) + item.color = Qt.binding(function(){return root.handle.pressed ? Theme.highlightedTextColor : Theme.textColor}) } } } Behavior on color { ColorAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } } } Rectangle { z: -2 anchors { right: root.edge == Qt.RightEdge ? parent.left : (root.edge == Qt.LeftEdge ? undefined : parent.right) left: root.edge == Qt.LeftEdge ? parent.right : (root.edge == Qt.RightEdge ? undefined : parent.left) top: root.edge == Qt.TopEdge ? parent.bottom : (root.edge == Qt.BottomEdge ? undefined : parent.top) bottom: root.edge == Qt.BottomEdge ? parent.top : (root.edge == Qt.TopEdge ? undefined : parent.bottom) } color: Theme.textColor opacity: root.position == 0 ? 0 : 0.3 width: Units.devicePixelRatio } } focus: false //default to a sidebar in desktop mode modal: (applicationWindow() && applicationWindow().width < width*2) || edge == Qt.TopEdge || edge == Qt.BottomEdge drawerOpen: true closePolicy: modal ? Popup.CloseOnEscape | Popup.CloseOnPressOutside : Popup.NoAutoClose handleVisible: modal || !drawerOpen onPositionChanged: { if (!modal && !root.peeking && !root.animating) { position = 1; } } } diff --git a/src/styles/org.kde.desktop/SwipeListItem.qml b/src/styles/org.kde.desktop/SwipeListItem.qml index 297219e8..bfc5b8e6 100644 --- a/src/styles/org.kde.desktop/SwipeListItem.qml +++ b/src/styles/org.kde.desktop/SwipeListItem.qml @@ -1,31 +1,31 @@ /* * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ import QtQuick 2.5 -import org.kde.kirigami 2.0 +import org.kde.kirigami 2.2 import "../../private" import "../../templates" as T T.SwipeListItem { id: listItem rightPadding: Units.gridUnit background: DefaultListItemBackground {} implicitHeight: contentItem.implicitHeight + Units.smallSpacing * 4 } diff --git a/src/styles/org.kde.desktop/Theme.qml b/src/styles/org.kde.desktop/Theme.qml index 8a848a87..c935354a 100644 --- a/src/styles/org.kde.desktop/Theme.qml +++ b/src/styles/org.kde.desktop/Theme.qml @@ -1,62 +1,85 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.4 pragma Singleton QtObject { id: theme property color textColor: palette.windowText property color disabledTextColor: disabledPalette.windowText property color highlightColor: palette.highlight property color highlightedTextColor: palette.highlightedText property color backgroundColor: palette.window - property color linkColor: "#2196F3" - property color visitedLinkColor: "#2196F3" + property color activeTextColor: palette.highlight + property color linkColor: "#2980B9" + property color visitedLinkColor: "#7F8C8D" + property color hoverColor: palette.highlight + property color focusColor: palette.highlight + property color negativeTextColor: "#DA4453" + property color neutralTextColor: "#F67400" + property color positiveTextColor: "#27AE60" property color buttonTextColor: palette.buttonText property color buttonBackgroundColor: palette.button property color buttonHoverColor: palette.highlight property color buttonFocusColor: palette.highlight property color viewTextColor: palette.text property color viewBackgroundColor: palette.base property color viewHoverColor: palette.highlight property color viewFocusColor: palette.highlight + property color selectionTextColor: palette.highlightedText + property color selectionBackgroundColor: palette.highlight + property color selectionHoverColor: palette.highlight + property color selectionFocusColor: palette.highlight + + property color tooltipTextColor: palette.base + property color tooltipBackgroundColor: palette.text + property color tooltipHoverColor: palette.highlight + property color tooltipFocusColor: palette.highlight + + property color complementaryTextColor: palette.base + property color complementaryBackgroundColor: palette.text + property color complementaryHoverColor: palette.highlight + property color complementaryFocusColor: palette.highlight + property font defaultFont: fontMetrics.font property list children: [ TextMetrics { id: fontMetrics }, SystemPalette { id: palette colorGroup: SystemPalette.Active }, SystemPalette { id: disabledPalette colorGroup: SystemPalette.Disabled } ] + + function __propagateColorSet(object, context) {} } diff --git a/tests/KeyboardListTest.qml b/tests/KeyboardListTest.qml index 8433cfc3..0fbf67d7 100644 --- a/tests/KeyboardListTest.qml +++ b/tests/KeyboardListTest.qml @@ -1,45 +1,45 @@ /* * Copyright 2016 Aleix Pol Gonzalez * Copyright 2016 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.7 import QtQuick.Controls 2.0 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ApplicationWindow { id: main Component { id: keyPage Kirigami.ScrollablePage { ListView { model: 10 delegate: Rectangle { width: 100 height: 30 color: ListView.isCurrentItem ? "red" : "white" } } } } Component.onCompleted: { main.pageStack.push(keyPage) } } diff --git a/tests/KeyboardTest.qml b/tests/KeyboardTest.qml index 57fd1e27..8ba75700 100644 --- a/tests/KeyboardTest.qml +++ b/tests/KeyboardTest.qml @@ -1,56 +1,56 @@ /* * Copyright 2016 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.7 import QtQuick.Controls 2.0 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 as Kirigami Kirigami.ApplicationWindow { id: main Component { id: keyPage Kirigami.Page { readonly property alias lastKey: see.text Text { id: see anchors.centerIn: parent color: parent.focus ? "black" : "red" } Keys.onPressed: { if (event.text) see.text = event.text else see.text = event.key } Keys.onEnterPressed: main.showPassiveNotification("page!") } } header: Text { text: "focus:" + activeFocusItem + " current: " + main.pageStack.currentIndex } Component.onCompleted: { main.pageStack.push(keyPage) main.pageStack.push(keyPage) } }