add 'ensure-permissions' for android; revisions

This commit is contained in:
pls.153 2022-02-22 16:10:55 +01:00
parent 8929b6f60f
commit 60d4a08a8c
12 changed files with 121 additions and 37 deletions

2
.gitignore vendored
View file

@ -8,6 +8,8 @@ _*
*.o *.o
*.obj *.obj
*.so* *.so*
*.dylib
*.dll
*.qm *.qm
*.stash *.stash
*.ts *.ts

View file

@ -1,5 +1,5 @@
#include "lib.h" #include "lib.h"
#include "../../src/cpp/ecl_fun_plugin.h" #include "../../src/cpp/ecl_fun_plugin.h" // for ecl_fun(); independent from LQML
#include <QApplication> #include <QApplication>
#include <QMessageBox> #include <QMessageBox>
#include <QtDebug> #include <QtDebug>

View file

@ -18,6 +18,15 @@
(my-qt-function *c++* x y) ; call from Lisp (my-qt-function *c++* x y) ; call from Lisp
<b>ensure-permissions (permission/permissions)</b>
Android only; requests the passed permission, or a list of them.
Returns the permission if it was granted, or a list of the granted
permissions.
(ensure-permissions "android.permission.ACCESS_FINE_LOCATION")
<b>find-quick-item (object-name)</b> <b>find-quick-item (object-name)</b>
Finds the first QQuickItem matching OBJECT-NAME. Locally set *ROOT-ITEM* if Finds the first QQuickItem matching OBJECT-NAME. Locally set *ROOT-ITEM* if

View file

@ -74,4 +74,3 @@
:info #.(read-file "txt/neptune.txt")))) :info #.(read-file "txt/neptune.txt"))))
(populate-item-model) (populate-item-model)

View file

@ -13,6 +13,10 @@
#include <QQmlExpression> #include <QQmlExpression>
#include <QQmlProperty> #include <QQmlProperty>
#ifdef Q_OS_ANDROID
#include <QtAndroid>
#endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
void iniCLFunctions() { void iniCLFunctions() {
@ -21,34 +25,35 @@ void iniCLFunctions() {
cl_make_package(1, qml); cl_make_package(1, qml);
} }
si_select_package(qml); si_select_package(qml);
DEFUN ("%js", js2, 2) DEFUN ("%ensure-permissions", ensure_permissions2, 1)
DEFUN ("pixel-ratio", pixel_ratio, 0) DEFUN ("%js", js2, 2)
DEFUN ("%qapropos", qapropos2, 3) DEFUN ("pixel-ratio", pixel_ratio, 0)
DEFUN ("qchildren", qchildren, 1) DEFUN ("%qapropos", qapropos2, 3)
DEFUN ("qescape", qescape, 1) DEFUN ("qchildren", qchildren, 1)
DEFUN ("%qexec", qexec2, 1) DEFUN ("qescape", qescape, 1)
DEFUN ("qexit", qexit, 0) DEFUN ("%qexec", qexec2, 1)
DEFUN ("qfind-child", qfind_child, 2) DEFUN ("qexit", qexit, 0)
DEFUN ("%qfind-children", qfind_children2, 3) DEFUN ("qfind-child", qfind_child, 2)
DEFUN ("qfrom-utf8", qfrom_utf8, 1) DEFUN ("%qfind-children", qfind_children2, 3)
DEFUN ("%qinvoke-method", qinvoke_method2, 3) DEFUN ("qfrom-utf8", qfrom_utf8, 1)
DEFUN ("%qload-c++", qload_cpp, 2) DEFUN ("%qinvoke-method", qinvoke_method2, 3)
DEFUN ("%qlog", qlog2, 1) DEFUN ("%qload-c++", qload_cpp, 2)
DEFUN ("%qml-get", qml_get2, 2) DEFUN ("%qlog", qlog2, 1)
DEFUN ("%qml-set", qml_set2, 3) DEFUN ("%qml-get", qml_get2, 2)
DEFUN ("qobject-name", qobject_name, 1) DEFUN ("%qml-set", qml_set2, 3)
DEFUN ("qprocess-events", qprocess_events, 0) DEFUN ("qobject-name", qobject_name, 1)
DEFUN ("%qquit", qquit2, 1) DEFUN ("qprocess-events", qprocess_events, 0)
DEFUN ("%qrun-on-ui-thread", qrun_on_ui_thread2, 2) DEFUN ("%qquit", qquit2, 1)
DEFUN ("%qget", qget2, 2) DEFUN ("%qrun-on-ui-thread", qrun_on_ui_thread2, 2)
DEFUN ("%qset", qset2, 2) DEFUN ("%qget", qget2, 2)
DEFUN ("%qsingle-shot", qsingle_shot2, 2) DEFUN ("%qset", qset2, 2)
DEFUN ("qtranslate", qtranslate, 3) DEFUN ("%qsingle-shot", qsingle_shot2, 2)
DEFUN ("qversion", qversion, 0) DEFUN ("qtranslate", qtranslate, 3)
DEFUN ("qt-object-info", qt_object_info, 1) DEFUN ("qversion", qversion, 0)
DEFUN ("%reload", reload2, 0) DEFUN ("qt-object-info", qt_object_info, 1)
DEFUN ("root-item", root_item, 0) DEFUN ("%reload", reload2, 0)
DEFUN ("%set-shutdown-p", set_shutdown_p, 1) DEFUN ("root-item", root_item, 0)
DEFUN ("%set-shutdown-p", set_shutdown_p, 1)
} }
@ -173,7 +178,7 @@ cl_object qfind_children2(cl_object l_obj, cl_object l_name, cl_object l_class)
if (qobject != nullptr) { if (qobject != nullptr) {
QObjectList children = qobject->findChildren<QObject*>(objectName); QObjectList children = qobject->findChildren<QObject*>(objectName);
cl_object l_children = ECL_NIL; cl_object l_children = ECL_NIL;
Q_FOREACH(QObject* child, children) { Q_FOREACH (QObject* child, children) {
QByteArray className2(child->metaObject()->className()); QByteArray className2(child->metaObject()->className());
if (className.isEmpty() || (className == className2)) { if (className.isEmpty() || (className == className2)) {
l_children = CONS(from_qobject_pointer(child), l_children = CONS(from_qobject_pointer(child),
@ -196,7 +201,7 @@ cl_object qchildren(cl_object l_item) {
if (item != nullptr) { if (item != nullptr) {
QList<QQuickItem*> children = item->childItems(); QList<QQuickItem*> children = item->childItems();
cl_object l_children = ECL_NIL; cl_object l_children = ECL_NIL;
Q_FOREACH(QQuickItem* child, children) { Q_FOREACH (QQuickItem* child, children) {
l_children = CONS(from_qobject_pointer(child), l_children = CONS(from_qobject_pointer(child),
l_children); l_children);
} }
@ -547,6 +552,46 @@ cl_object reload2() {
ecl_return1(ecl_process_env(), l_ret); ecl_return1(ecl_process_env(), l_ret);
} }
cl_object ensure_permissions2(cl_object l_permissions) {
/// args: (permission/permissions)
/// Android only; requests the passed permission, or a list of them.
/// Returns the permission if it was granted, or a list of the granted
/// permissions.
/// (ensure-permissions "android.permission.ACCESS_FINE_LOCATION")
cl_object l_ret = ECL_T;
#if (defined Q_OS_ANDROID) && (QT_VERSION > 0x050A00) // 5.10
QStringList permissions(toQStringList(l_permissions));
QStringList denied;
QStringList granted;
Q_FOREACH (QString p, permissions) {
if (QtAndroid::checkPermission(p) == QtAndroid::PermissionResult::Granted) {
granted << p;
} else {
denied << p;
}
}
if (!denied.isEmpty()) {
QEventLoop loop; // custom sync because requestPermissionsSync() may hang
QtAndroid::requestPermissions(denied, [&](const QtAndroid::PermissionResultMap& res) {
Q_FOREACH (QString p, denied) {
if (res[p] == QtAndroid::PermissionResult::Granted) {
granted << p;
}
}
loop.exit();
});
loop.exec(QEventLoop::ExcludeUserInputEvents);
}
if (granted.length() == 1) {
l_ret = from_qstring(granted.first());
}
else {
l_ret = from_qstringlist(granted);
}
#endif
ecl_return1(ecl_process_env(), l_ret);
}
// *** meta info *** // *** meta info ***
@ -633,7 +678,7 @@ static cl_object collectInfo(const QByteArray& type,
std::sort(info.begin(), info.end(), metaInfoLessThan); std::sort(info.begin(), info.end(), metaInfoLessThan);
if (info.size()) { if (info.size()) {
*found = true; *found = true;
Q_FOREACH(QByteArray i, info) { Q_FOREACH (QByteArray i, info) {
l_info = CONS(STRING_COPY(i.constData()), l_info); l_info = CONS(STRING_COPY(i.constData()), l_info);
} }
} }

View file

@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE
#define LIST10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ #define LIST10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
CONS(a1, LIST9(a2, a3, a4, a5, a6, a7, a8, a9, a10)) CONS(a1, LIST9(a2, a3, a4, a5, a6, a7, a8, a9, a10))
cl_object ensure_permissions2 (cl_object);
cl_object js2 (cl_object, cl_object); cl_object js2 (cl_object, cl_object);
cl_object pixel_ratio (); cl_object pixel_ratio ();
cl_object qapropos2 (cl_object, cl_object, cl_object); cl_object qapropos2 (cl_object, cl_object, cl_object);

View file

@ -1,4 +1,4 @@
// all-in-on-header to include in Qt plugin source files which want to call // all-in-one header to include in Qt plugin source files which want to call
// ECL functions through 'ecl_fun()' // ECL functions through 'ecl_fun()'
// //
// does not depend on LQML // does not depend on LQML
@ -312,7 +312,7 @@ cl_object from_qvariant(const QVariant& var) {
case QMetaType::QString: l_obj = from_qstring(var.toString()); break; case QMetaType::QString: l_obj = from_qstring(var.toString()); break;
// special case (can be nested) // special case (can be nested)
case QMetaType::QVariantList: case QMetaType::QVariantList:
Q_FOREACH(QVariant v, var.value<QVariantList>()) { Q_FOREACH (QVariant v, var.value<QVariantList>()) {
l_obj = CONS(from_qvariant(v), l_obj); l_obj = CONS(from_qvariant(v), l_obj);
} }
l_obj = cl_nreverse(l_obj); l_obj = cl_nreverse(l_obj);

View file

@ -124,6 +124,18 @@ QString toQString(cl_object l_str) {
return s; return s;
} }
QStringList toQStringList(cl_object l_list) {
QStringList l;
if (ECL_LISTP(l_list)) {
cl_object l_el = l_list;
while (l_el != ECL_NIL) {
l << toQString(cl_car(l_el));
l_el = cl_cdr(l_el);
}
}
return l;
}
TO_QT_FLOAT_2 (QPointF) TO_QT_FLOAT_2 (QPointF)
TO_QT_FLOAT_2 (QSizeF) TO_QT_FLOAT_2 (QSizeF)
TO_QT_FLOAT_4 (QRectF) TO_QT_FLOAT_4 (QRectF)
@ -246,6 +258,15 @@ cl_object from_qstring(const QString& s) {
return l_s; return l_s;
} }
cl_object from_qstringlist(const QStringList& l) {
cl_object l_list = ECL_NIL;
Q_FOREACH (QString s, l) {
l_list = CONS(from_qstring(s), l_list);
}
l_list = cl_nreverse(l_list);
return l_list;
}
TO_CL_FLOAT_2 (QPointF, qpointf, x, y) TO_CL_FLOAT_2 (QPointF, qpointf, x, y)
TO_CL_FLOAT_2 (QSizeF, qsizef, width, height) TO_CL_FLOAT_2 (QSizeF, qsizef, width, height)
TO_CL_FLOAT_4 (QRectF, qrectf, x, y, width, height) TO_CL_FLOAT_4 (QRectF, qrectf, x, y, width, height)
@ -270,7 +291,7 @@ cl_object from_qvariant(const QVariant& var) {
case QMetaType::QString: l_obj = from_qstring(var.toString()); break; case QMetaType::QString: l_obj = from_qstring(var.toString()); break;
// special case (can be nested) // special case (can be nested)
case QMetaType::QVariantList: case QMetaType::QVariantList:
Q_FOREACH(QVariant v, var.value<QVariantList>()) { Q_FOREACH (QVariant v, var.value<QVariantList>()) {
l_obj = CONS(from_qvariant(v), l_obj); l_obj = CONS(from_qvariant(v), l_obj);
} }
l_obj = cl_nreverse(l_obj); l_obj = cl_nreverse(l_obj);

View file

@ -83,6 +83,7 @@ qreal toReal(cl_object);
QByteArray toCString(cl_object); QByteArray toCString(cl_object);
QByteArray toQByteArray(cl_object); QByteArray toQByteArray(cl_object);
QString toQString(cl_object); QString toQString(cl_object);
QStringList toQStringList(cl_object);
QVariant toQVariant(cl_object, int = -1); QVariant toQVariant(cl_object, int = -1);
QVariantList toQVariantList(cl_object); QVariantList toQVariantList(cl_object);
QVariant toQVariantMap(cl_object); QVariant toQVariantMap(cl_object);
@ -91,6 +92,7 @@ QObject* toQObjectPointer(cl_object);
cl_object from_cstring(const QByteArray&); cl_object from_cstring(const QByteArray&);
cl_object from_qbytearray(const QByteArray&); cl_object from_qbytearray(const QByteArray&);
cl_object from_qstring(const QString&); cl_object from_qstring(const QString&);
cl_object from_qstringlist(const QStringList&);
cl_object from_qvariant(const QVariant&); cl_object from_qvariant(const QVariant&);
cl_object from_qobject_pointer(QObject*); cl_object from_qobject_pointer(QObject*);

View file

@ -212,7 +212,10 @@
(assert (typep exit-status 'fixnum)) (assert (typep exit-status 'fixnum))
(%qquit exit-status)) (%qquit exit-status))
;;; for android logging ;;; android
(defun ensure-permissions (permissions)
(qrun* (%ensure-permissions (x:ensure-list permissions))))
(defun qlog (arg1 &rest args) (defun qlog (arg1 &rest args)
"args: (arg1 &rest args) "args: (arg1 &rest args)

View file

@ -6,6 +6,7 @@
#:*root-item* #:*root-item*
#:*caller* #:*caller*
#:define-qt-wrappers #:define-qt-wrappers
#:ensure-permissions
#:find-quick-item #:find-quick-item
#:pixel-ratio #:pixel-ratio
#:qapropos #:qapropos

View file

@ -17,6 +17,7 @@ macx {
} }
android { android {
QT += androidextras
INCLUDEPATH = $$(ECL_ANDROID)/include INCLUDEPATH = $$(ECL_ANDROID)/include
LIBS = -L$$(ECL_ANDROID)/lib -lecl LIBS = -L$$(ECL_ANDROID)/lib -lecl
DESTDIR = ../../platforms/android/lib DESTDIR = ../../platforms/android/lib