diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,19 +13,16 @@ include(CPack) include(FeatureSummary) -find_package(Qt5 ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE COMPONENTS Core Quick QuickControls2) - set(CMAKE_AUTOMOC ON) -set(AUTOMOC_MOC_OPTIONS -Muri=org.kde.kirigami) set(CMAKE_INCLUDE_CURRENT_DIR ON) ################# set KDE specific information ################# find_package(ECM 5.56.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}) +set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) include(GenerateExportHeader) include(ECMSetupVersion) @@ -51,30 +48,37 @@ PATH_VARS KF5_INCLUDE_INSTALL_DIR CMAKE_INSTALL_PREFIX ) -# install(FILES -# "${CMAKE_CURRENT_BINARY_DIR}/KF5KirigamiAddonsConfig.cmake" -# "${CMAKE_CURRENT_BINARY_DIR}/KF5KirigamiAddonsConfigVersion.cmake" -# "${CMAKE_CURRENT_SOURCE_DIR}/KF5KirigamiAddonsMacros.cmake" -# DESTINATION "${CMAKECONFIG_INSTALL_DIR}" -# COMPONENT Devel -# ) - -# install(EXPORT KF5KirigamiAddonsTargets -# DESTINATION "${CMAKECONFIG_INSTALL_DIR}" -# FILE KF5KirigamiAddonsTargets.cmake -# NAMESPACE KF5:: -# ) - +find_package(Qt5 ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE COMPONENTS Core Quick QuickControls2) find_package(KF5I18n ${KF5_DEP_VERSION} REQUIRED) -# ecm_setup_version(${KF5_VERSION} -# VARIABLE_PREFIX KIRIGAMIADDONS -# VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kirigamiaddons_version.h" -# PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5KirigamiAddonsConfigVersion.cmake" -# SOVERSION 5 -# ) +if(ANDROID) + find_package(Qt5 ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE COMPONENTS AndroidExtras) + find_package(Gradle REQUIRED) +endif() + +ecm_setup_version(${KF5_VERSION} + VARIABLE_PREFIX KIRIGAMIADDONS + VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kirigamiaddons_version.h" + PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5KirigamiAddonsConfigVersion.cmake" + SOVERSION 1 +) add_subdirectory(src) +if(ANDROID) +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/KF5KirigamiAddonsConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/KF5KirigamiAddonsConfigVersion.cmake" + DESTINATION "${CMAKECONFIG_INSTALL_DIR}" + COMPONENT Devel +) + +install(EXPORT KF5KirigamiAddonsTargets + DESTINATION "${CMAKECONFIG_INSTALL_DIR}" + FILE KF5KirigamiAddonsTargets.cmake + NAMESPACE KF5:: +) +endif() + feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/KF5KirigamiAddonsConfig.cmake.in b/KF5KirigamiAddonsConfig.cmake.in --- a/KF5KirigamiAddonsConfig.cmake.in +++ b/KF5KirigamiAddonsConfig.cmake.in @@ -5,11 +5,8 @@ # Any changes in this ".cmake" file will be overwritten by CMake, the source is the ".cmake.in" file. -include("${CMAKE_CURRENT_LIST_DIR}/KF5Kirigami2Targets.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/KF5KirigamiAddonsTargets.cmake") -set(Kirigami2_INSTALL_PREFIX "@PACKAGE_CMAKE_INSTALL_PREFIX@") +set(KirigamiAddons_INSTALL_PREFIX "@PACKAGE_CMAKE_INSTALL_PREFIX@") -#set(Kirigami2_LIBRARIES KF5::Kirigami2) - -include("${CMAKE_CURRENT_LIST_DIR}/KF5Kirigami2Macros.cmake") @PACKAGE_INCLUDE_QCHTARGETS@ diff --git a/cmake/modules/FindGradle.cmake b/cmake/modules/FindGradle.cmake new file mode 100644 --- /dev/null +++ b/cmake/modules/FindGradle.cmake @@ -0,0 +1,110 @@ +#.rst: +# FindGradle +# ---------- +# +# Provides the ability to build Android AAR libraries using Gradle. +# +# This relies on the Qt provided Gradle, so a Qt for Android installation +# is required. +# +# gradle_add_aar( +# BUIDLFILE build.gradle +# NAME ) +# +# This builds an Android AAR library using the given ``build.gradle`` file. +# +# gradle_install_aar( +# DESTINATION ) +# +# Installs a Android AAR library that has been created with ``gradle_add_aar``. + +#============================================================================= +# Copyright (c) 2019 Volker Krause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +include(CMakeParseArguments) +include(FindPackageHandleStandardArgs) + +find_package(Qt5Core REQUIRED) + +if (NOT WIN32) + set(Gradle_EXECUTABLE ${CMAKE_BINARY_DIR}/gradle/gradlew) +else() + set(Gradle_EXECUTABLE ${CMAKE_BINARY_DIR}/gradle/gradlew.bat) +endif() + +get_target_property(_qt_core_location Qt5::Core LOCATION) +get_filename_component(_qt_install_root ${_qt_core_location} DIRECTORY) +get_filename_component(_qt_install_root ${_qt_install_root}/../ ABSOLUTE) + +set(_gradle_template_dir ${CMAKE_CURRENT_LIST_DIR}) + +add_custom_command(OUTPUT ${Gradle_EXECUTABLE} + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/gradle + COMMAND ${CMAKE_COMMAND} -E copy_directory ${_qt_install_root}/src/3rdparty/gradle ${CMAKE_BINARY_DIR}/gradle +) +add_custom_target(gradle DEPENDS ${Gradle_EXECUTABLE}) + +find_package_handle_standard_args(Gradle DEFAULT_MSG Gradle_EXECUTABLE) + +function(gradle_add_aar target) + cmake_parse_arguments(ARG "" "BUILDFILE;NAME" "" ${ARGN}) + + set(_build_root ${CMAKE_CURRENT_BINARY_DIR}/gradle_build/${ARG_NAME}) + configure_file(${_gradle_template_dir}/local.properties.in ${_build_root}/local.properties) + configure_file(${_gradle_template_dir}/settings.gradle.in ${_build_root}/settings.gradle) + configure_file(${ARG_BUILDFILE} ${_build_root}/build.gradle) + + if (CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]") + set(_aar_suffix "-debug") + set(_aar_gradleCmd "assembleDebug") + else() + set(_aar_suffix "-release") + set(_aar_gradleCmd "assembleRelease") + endif() + if (NOT Qt5Core_VERSION VERSION_LESS 5.14.0) # behavior change in Gradle shipped with Qt 5.14 + set(_aar_suffix "") + endif() + + file(GLOB_RECURSE _src_files CONFIGURE_DEPENDS "*") + add_custom_command( + OUTPUT ${_build_root}/build/outputs/aar/${ARG_NAME}${_aar_suffix}.aar + COMMAND ${Gradle_EXECUTABLE} ${_aar_gradleCmd} + DEPENDS ${Gradle_EXECUTABLE} ${_src_files} + DEPENDS gradle + WORKING_DIRECTORY ${_build_root} + ) + add_custom_target(${target} ALL DEPENDS ${_build_root}/build/outputs/aar/${ARG_NAME}${_aar_suffix}.aar) + set_target_properties(${target} PROPERTIES LOCATION ${_build_root}/build/outputs/aar/${ARG_NAME}${_aar_suffix}.aar) + set_target_properties(${target} PROPERTIES OUTPUT_NAME ${ARG_NAME}) +endfunction() + +function(gradle_install_aar target) + cmake_parse_arguments(ARG "" "DESTINATION" "" ${ARGN}) + get_target_property(_loc ${target} LOCATION) + get_target_property(_name ${target} OUTPUT_NAME) + install(FILES ${_loc} DESTINATION ${ARG_DESTINATION} RENAME ${_name}.aar) +endfunction() diff --git a/cmake/modules/local.properties.in b/cmake/modules/local.properties.in new file mode 100644 --- /dev/null +++ b/cmake/modules/local.properties.in @@ -0,0 +1 @@ +sdk.dir=@ANDROID_SDK_ROOT@ diff --git a/cmake/modules/settings.gradle.in b/cmake/modules/settings.gradle.in new file mode 100644 --- /dev/null +++ b/cmake/modules/settings.gradle.in @@ -0,0 +1 @@ +rootProject.name = '@ARG_NAME@' diff --git a/src/dateandtime/CMakeLists.txt b/src/dateandtime/CMakeLists.txt --- a/src/dateandtime/CMakeLists.txt +++ b/src/dateandtime/CMakeLists.txt @@ -16,11 +16,33 @@ KF5::I18n ) +if(ANDROID) + add_subdirectory(android) + + add_library(KF5KirigamiDateAndTimeAndroid lib/androidutils.cpp) + add_library(KF5::KirigamiDateAndTimeAndroid ALIAS KF5KirigamiDateAndTimeAndroid) + + target_link_libraries(KF5KirigamiDateAndTimeAndroid Qt5::AndroidExtras) + + target_link_libraries(dateandtimeplugin KF5KirigamiDateAndTimeAndroid) + + set_target_properties(KF5KirigamiDateAndTimeAndroid PROPERTIES EXPORT_NAME KirigamiDateAndTimeAndroid) + + install(TARGETS KF5KirigamiDateAndTimeAndroid EXPORT KF5KirigamiAddonsTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) + + if (Qt5Core_VERSION VERSION_LESS 5.14.0) + install(FILES KF5KirigamiDateAndTimeAndroid-android-dependencies.xml DESTINATION ${KDE_INSTALL_LIBDIR}) + else() + install(FILES KF5KirigamiDateAndTimeAndroid-android-dependencies.xml DESTINATION ${KDE_INSTALL_LIBDIR} RENAME KF5KirigamiDateAndTimeAndroid_${CMAKE_ANDROID_ARCH_ABI}-android-dependencies.xml) + endif() +endif() + install(TARGETS dateandtimeplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigamiaddons/dateandtime) install(FILES qmldir ClockElement.qml ClockFace.qml + DateDialog.qml DateInput.qml DatePicker.qml DesktopDateInput.qml @@ -30,4 +52,5 @@ TimeLabel.qml TimePicker.qml TimeInput.qml + TimeDialog.qml DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigamiaddons/dateandtime) diff --git a/src/dateandtime/DateDialog.qml b/src/dateandtime/DateDialog.qml new file mode 100644 --- /dev/null +++ b/src/dateandtime/DateDialog.qml @@ -0,0 +1,52 @@ +/* + * SPDX-FileCopyrightText: 2020 Nicolas Fella + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +import QtQuick 2.7 +import QtQuick.Layouts 1.1 +import QtQuick.Controls 2.5 +import org.kde.kirigami 2.4 as Kirigami + +import org.kde.kirigamiaddons.dateandtime 0.1 as KDT + +Item { + signal datePicked(date theDate) + + function open() { + if (Qt.platform.os === "android") { + KDT.AndroidUtils.showDatePicker() + } else { + dialog.open() + } + } + + Connections { + target: Qt.platform.os === "android" ? KDT.AndroidUtils : dummy + onDatePickerFinished: (accepted, newDate) => { + if (accepted) { + datePicked(newDate) + } + } + } + + // Dummy for AndroidUtils object when not on Android + Item { + id: dummy + signal datePickerFinished(bool accepted, date theDate) + } + + Dialog { + id: dialog + anchors.centerIn: Overlay.overlay + height: Kirigami.Units.gridUnit * 6 + contentItem: KDT.DateInput { + id: picker + } + + standardButtons: Dialog.Ok | Dialog.Cancel + + onAccepted: datePicked(picker.selectedDate) + } +} diff --git a/src/dateandtime/KF5KirigamiDateAndTimeAndroid-android-dependencies.xml b/src/dateandtime/KF5KirigamiDateAndTimeAndroid-android-dependencies.xml new file mode 100644 --- /dev/null +++ b/src/dateandtime/KF5KirigamiDateAndTimeAndroid-android-dependencies.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/dateandtime/TimeDialog.qml b/src/dateandtime/TimeDialog.qml new file mode 100644 --- /dev/null +++ b/src/dateandtime/TimeDialog.qml @@ -0,0 +1,59 @@ +/* + * SPDX-FileCopyrightText: 2020 Nicolas Fella + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +import QtQuick 2.7 +import QtQuick.Layouts 1.1 +import QtQuick.Controls 2.5 +import org.kde.kirigami 2.4 as Kirigami + +import org.kde.kirigamiaddons.dateandtime 0.1 as KDT + +Item { + signal timePicked(date theTime) + + function open() { + if (Qt.platform.os === "android") { + KDT.AndroidUtils.showTimePicker() + } else { + dialog.open() + } + } + + Connections { + target: Qt.platform.os === "android" ? KDT.AndroidUtils : dummy + onTimePickerFinished: (accepted, newTime) => { + if (accepted) { + timePicked(newTime) + } + } + } + + // Dummy for AndroidUtils object when not on Android + QtObject { + id: dummy + signal timePickerFinished(bool accepted, date theTime) + } + + Dialog { + id: dialog + anchors.centerIn: Overlay.overlay + contentItem: KDT.TimePicker { + id: picker + implicitWidth: Kirigami.Units.gridUnit * 16 + implicitHeight: implicitWidth + } + + standardButtons: Dialog.Ok | Dialog.Cancel + + onAccepted: { + var time = new Date(); + time.setMinutes(picker.minutes) + time.setHours(picker.hours) + + timePicked(time) + } + } +} diff --git a/src/dateandtime/android/AndroidManifest.xml b/src/dateandtime/android/AndroidManifest.xml new file mode 100644 --- /dev/null +++ b/src/dateandtime/android/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/src/dateandtime/android/CMakeLists.txt b/src/dateandtime/android/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/src/dateandtime/android/CMakeLists.txt @@ -0,0 +1,2 @@ +gradle_add_aar(dateandtimeplugin_aar BUILDFILE ${CMAKE_CURRENT_SOURCE_DIR}/build.gradle NAME KF5KirigamiAddonsDateAndTime) +gradle_install_aar(dateandtimeplugin_aar DESTINATION jar) diff --git a/src/dateandtime/android/build.gradle b/src/dateandtime/android/build.gradle new file mode 100644 --- /dev/null +++ b/src/dateandtime/android/build.gradle @@ -0,0 +1,33 @@ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.2.0' + } +} + +repositories { + google() + jcenter() +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 28 + buildToolsVersion '28.0.2' + + sourceSets { + main { + manifest.srcFile '@CMAKE_CURRENT_SOURCE_DIR@/AndroidManifest.xml' + java.srcDirs = ['@CMAKE_CURRENT_SOURCE_DIR@/org'] + } + } + + lintOptions { + abortOnError false + } +} diff --git a/src/dateandtime/android/org/kde/kirigamiaddons/dateandtime/DatePicker.java b/src/dateandtime/android/org/kde/kirigamiaddons/dateandtime/DatePicker.java new file mode 100644 --- /dev/null +++ b/src/dateandtime/android/org/kde/kirigamiaddons/dateandtime/DatePicker.java @@ -0,0 +1,56 @@ +/* + * SPDX-FileCopyrightText: 2020 Nicolas Fella + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +package org.kde.kirigamiaddons.dateandtime; + +import android.app.DatePickerDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.app.DialogFragment; +import android.app.Activity; + +import java.util.Calendar; + +public class DatePicker extends DialogFragment implements DatePickerDialog.OnDateSetListener { + + private Activity activity; + private long initialDate; + + private native void dateSelected(int day, int month, int year); + private native void cancelled(); + + public DatePicker(Activity activity, long initialDate) { + super(); + this.activity = activity; + this.initialDate = initialDate; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(initialDate); + DatePickerDialog dialog = new DatePickerDialog(activity, this, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)); + android.widget.DatePicker picker = dialog.getDatePicker(); + return dialog; + } + + @Override + public void onCancel(DialogInterface dialog) { + cancelled(); + } + + @Override + public void onDateSet(android.widget.DatePicker view, int year, int month, int day) { + // Android reports month starting with 0 + month++; + dateSelected(day, month, year); + } + + public void doShow() { + show(activity.getFragmentManager(), "datePicker"); + } +} diff --git a/src/dateandtime/android/org/kde/kirigamiaddons/dateandtime/TimePicker.java b/src/dateandtime/android/org/kde/kirigamiaddons/dateandtime/TimePicker.java new file mode 100644 --- /dev/null +++ b/src/dateandtime/android/org/kde/kirigamiaddons/dateandtime/TimePicker.java @@ -0,0 +1,53 @@ +/* + * SPDX-FileCopyrightText: 2020 Nicolas Fella + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +package org.kde.kirigamiaddons.dateandtime; + +import android.app.TimePickerDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.app.DialogFragment; +import android.app.Activity; + +import java.util.Calendar; + +public class TimePicker extends DialogFragment + implements TimePickerDialog.OnTimeSetListener { + + private Activity activity; + private long initialTime; + + private native void timeSelected(int hours, int minutes); + private native void cancelled(); + + public TimePicker(Activity activity, long initialTime) { + super(); + this.activity = activity; + this.initialTime = initialTime; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(initialTime); + TimePickerDialog dialog = new TimePickerDialog(activity, this, cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), true); + return dialog; + } + + public void onTimeSet(android.widget.TimePicker view, int hourOfDay, int minute) { + timeSelected(hourOfDay, minute); + } + + @Override + public void onCancel(DialogInterface dialog) { + cancelled(); + } + + public void doShow() { + show(activity.getFragmentManager(), "timePicker"); + } +} diff --git a/src/dateandtime/lib/androidutils.h b/src/dateandtime/lib/androidutils.h new file mode 100644 --- /dev/null +++ b/src/dateandtime/lib/androidutils.h @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2020 Nicolas Fella + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#pragma once + +#include + +class QTime; +class QDate; + +class Q_DECL_EXPORT AndroidUtils : public QObject +{ + Q_OBJECT +public: + Q_INVOKABLE void showDatePicker(); + Q_INVOKABLE void showTimePicker(); + + void _dateSelected(int days, int months, int years); + void _dateCancelled(); + + void _timeSelected(int hours, int minutes); + void _timeCancelled(); + + static AndroidUtils &instance(); + +Q_SIGNALS: + void datePickerFinished(bool accepted, const QDate &date); + void timePickerFinished(bool accepted, const QTime &time); + +private: + static AndroidUtils *s_instance; +}; + diff --git a/src/dateandtime/lib/androidutils.cpp b/src/dateandtime/lib/androidutils.cpp new file mode 100644 --- /dev/null +++ b/src/dateandtime/lib/androidutils.cpp @@ -0,0 +1,112 @@ +/* + * SPDX-FileCopyrightText: 2020 Nicolas Fella + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include "androidutils.h" +#include +#include +#include +#include + +#define JSTRING(s) QAndroidJniObject::fromString(s).object() + + +AndroidUtils &AndroidUtils::instance() +{ + static AndroidUtils instance; + return instance; +} + +static void dateSelected(JNIEnv *env, jobject that, jint day, jint month, jint year) +{ + Q_UNUSED(that); + Q_UNUSED(env); + AndroidUtils::instance()._dateSelected(day, month, year); +} + +static void dateCancelled(JNIEnv *env, jobject that) +{ + Q_UNUSED(that); + Q_UNUSED(env); + AndroidUtils::instance()._dateCancelled(); +} + +static void timeSelected(JNIEnv *env, jobject that, jint hours, jint minutes) +{ + Q_UNUSED(that); + Q_UNUSED(env); + AndroidUtils::instance()._timeSelected(hours, minutes); +} + +static void timeCancelled(JNIEnv *env, jobject that) +{ + Q_UNUSED(that); + Q_UNUSED(env); + AndroidUtils::instance()._timeCancelled(); +} + +static const JNINativeMethod dateMethods[] = {{"dateSelected", "(III)V", (void *)dateSelected}, {"cancelled", "()V", (void *)dateCancelled}}; + +static const JNINativeMethod timeMethods[] = {{"timeSelected", "(II)V", (void *)timeSelected}, {"cancelled", "()V", (void *)timeCancelled}}; + +Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) +{ + static bool initialized = false; + if (initialized) { + return JNI_VERSION_1_6; + } + initialized = true; + + JNIEnv *env = nullptr; + if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) { + qWarning() << "Failed to get JNI environment."; + return -1; + } + jclass theclass = env->FindClass("org/kde/kirigamiaddons/dateandtime/DatePicker"); + if (env->RegisterNatives(theclass, dateMethods, sizeof(dateMethods) / sizeof(JNINativeMethod)) < 0) { + qWarning() << "Failed to register native functions."; + return -1; + } + + jclass timeclass = env->FindClass("org/kde/kirigamiaddons/dateandtime/TimePicker"); + if (env->RegisterNatives(timeclass, timeMethods, sizeof(timeMethods) / sizeof(JNINativeMethod)) < 0) { + qWarning() << "Failed to register native functions."; + return -1; + } + + return JNI_VERSION_1_4; +} + +void AndroidUtils::showDatePicker() +{ + QAndroidJniObject picker("org/kde/kirigamiaddons/dateandtime/DatePicker", "(Landroid/app/Activity;J)V", QtAndroid::androidActivity().object(), QDateTime::currentMSecsSinceEpoch()); + picker.callMethod("doShow"); +} + +void AndroidUtils::_dateSelected(int days, int months, int years) +{ + Q_EMIT datePickerFinished(true, QDate(years, months, days)); +} + +void AndroidUtils::_dateCancelled() +{ + Q_EMIT datePickerFinished(false, QDate()); +} + +void AndroidUtils::showTimePicker() +{ + QAndroidJniObject picker("org/kde/kirigamiaddons/dateandtime/TimePicker", "(Landroid/app/Activity;J)V", QtAndroid::androidActivity().object(), QDateTime::currentDateTime().toMSecsSinceEpoch()); + picker.callMethod("doShow"); +} + +void AndroidUtils::_timeSelected(int hours, int minutes) +{ + Q_EMIT timePickerFinished(true, QTime(hours, minutes)); +} + +void AndroidUtils::_timeCancelled() +{ + Q_EMIT timePickerFinished(false, QTime()); +} diff --git a/src/dateandtime/lib/plugin.cpp b/src/dateandtime/lib/plugin.cpp --- a/src/dateandtime/lib/plugin.cpp +++ b/src/dateandtime/lib/plugin.cpp @@ -24,6 +24,10 @@ #include "timeinputvalidator.h" #include "monthmodel.h" +#ifdef Q_OS_ANDROID +#include "androidutils.h" +#endif + class KirigamiAddonsDataAndTimePlugin : public QQmlExtensionPlugin { Q_OBJECT @@ -48,6 +52,13 @@ qmlRegisterType(uri, 0, 1, "TimeZoneModel"); qmlRegisterType(uri, 0, 1, "TimeZoneFilterModel"); qmlRegisterType(uri, 0, 1, "TimeInputValidator"); + +#ifdef Q_OS_ANDROID + qmlRegisterSingletonType(uri, 0, 1, "AndroidUtils", [](QQmlEngine *, QJSEngine *) -> QObject * { + QQmlEngine::setObjectOwnership(&AndroidUtils::instance(), QQmlEngine::CppOwnership); + return &AndroidUtils::instance(); + }); +#endif } #include "plugin.moc" diff --git a/src/dateandtime/qmldir b/src/dateandtime/qmldir --- a/src/dateandtime/qmldir +++ b/src/dateandtime/qmldir @@ -10,3 +10,5 @@ ClockElement 0.1 ClockElement.qml TimeInput 0.1 TimeInput.qml TimeLabel 0.1 TimeLabel.qml +DateDialog 0.1 DateDialog.qml +TimeDialog 0.1 TimeDialog.qml