add help generated from doc-strings; some revisions

This commit is contained in:
pls.153 2022-01-22 15:07:55 +01:00
parent d7d4d980f4
commit 4625850752
12 changed files with 420 additions and 95 deletions

View file

@ -4,6 +4,7 @@
#include "single_shot.h"
#include <QTimer>
#include <QLibrary>
#include <QLibraryInfo>
#include <QGuiApplication>
#include <QQuickItem>
#include <QQuickView>
@ -22,7 +23,7 @@ void iniCLFunctions() {
DEFUN ("%js", js2, 2)
DEFUN ("pixel-ratio", pixel_ratio, 0)
DEFUN ("%qapropos", qapropos2, 3)
DEFUN ("qchild-items", qchild_items, 1)
DEFUN ("qchildren", qchildren, 1)
DEFUN ("qescape", qescape, 1)
DEFUN ("%qexec", qexec2, 1)
DEFUN ("qexit", qexit, 0)
@ -31,7 +32,6 @@ void iniCLFunctions() {
DEFUN ("qfrom-utf8", qfrom_utf8, 1)
DEFUN ("%qinvoke-method", qinvoke_method2, 3)
DEFUN ("%qload-c++", qload_cpp, 2)
DEFUN ("qlocal8bit", qlocal8bit, 1)
DEFUN ("%qlog", qlog2, 1)
DEFUN ("%qml-get", qml_get2, 2)
DEFUN ("%qml-set", qml_set2, 3)
@ -43,7 +43,6 @@ void iniCLFunctions() {
DEFUN ("%qset", qset2, 2)
DEFUN ("%qsingle-shot", qsingle_shot2, 2)
DEFUN ("qtranslate", qtranslate, 3)
DEFUN ("qutf8", qutf8, 1)
DEFUN ("qversion", qversion, 0)
DEFUN ("%reload", reload2, 0)
DEFUN ("root-item", root_item, 0)
@ -55,6 +54,7 @@ void iniCLFunctions() {
// *** utils ***
void error_msg(const char* fun, cl_object l_args) {
// for error messages in ECL functions defined in C++
STATIC_SYMBOL_PKG (s_break_on_errors, "*BREAK-ON-ERRORS*", "QML")
if (cl_symbol_value(s_break_on_errors) != ECL_NIL) {
STATIC_SYMBOL_PKG (s_break, "%BREAK", "QML") // see "ini.lisp"
@ -79,11 +79,16 @@ void error_msg(const char* fun, cl_object l_args) {
// *** main functions ***
cl_object set_shutdown_p(cl_object l_obj) {
// for internal use
LQML::cl_shutdown_p = (l_obj != ECL_NIL);
ecl_return1(ecl_process_env(), l_obj);
}
cl_object qget2(cl_object l_obj, cl_object l_name) {
/// args: (object name)
/// Gets a Qt property. Enumerator values are returned as integer values.
/// Returns T as second return value for successful calls.
/// (qget *quick-view* |width|)
QObject* qobject = toQObjectPointer(l_obj);
if (ECL_STRINGP(l_name) && (qobject != nullptr)) {
const QMetaObject* mo = qobject->metaObject();
@ -101,6 +106,10 @@ cl_object qget2(cl_object l_obj, cl_object l_name) {
}
cl_object qset2(cl_object l_obj, cl_object l_args) {
/// args: (object name1 value1 &optional name2 value2...)
/// Sets a Qt property. Enumerators have to be passed as integer values.
/// Returns T as second return value for successful calls.
/// (qset *quick-view* |x| 100 |y| 100)
QObject* qobject = toQObjectPointer(l_obj);
if (qobject != nullptr) {
const QMetaObject* mo = qobject->metaObject();
@ -131,6 +140,8 @@ fail:
}
cl_object qfind_child(cl_object l_obj, cl_object l_name) {
/// args: (qobject name)
/// Calls QObject::findChild<QObject*>().
ecl_process_env()->nvalues = 1;
QString name(toQString(l_name));
if (!name.isEmpty()) {
@ -148,6 +159,7 @@ cl_object qfind_child(cl_object l_obj, cl_object l_name) {
}
cl_object qfind_children2(cl_object l_obj, cl_object l_name, cl_object l_class) {
// for internal use
ecl_process_env()->nvalues = 1;
QString objectName(toQString(l_name));
QByteArray className(toCString(l_class));
@ -169,7 +181,9 @@ cl_object qfind_children2(cl_object l_obj, cl_object l_name, cl_object l_class)
return ECL_NIL;
}
cl_object qchild_items(cl_object l_item) {
cl_object qchildren(cl_object l_item) {
/// args: (item/name)
/// Like QML function children().
ecl_process_env()->nvalues = 1;
QObject* qobject = toQObjectPointer(l_item);
QQuickItem* item = qobject_cast<QQuickItem*>(qobject); // type check
@ -183,11 +197,25 @@ cl_object qchild_items(cl_object l_item) {
l_children = cl_nreverse(l_children);
return l_children;
}
error_msg("QCHILD-ITEMS", LIST1(l_item));
error_msg("QCHILDREN", LIST1(l_item));
return ECL_NIL;
}
cl_object qload_cpp(cl_object l_lib_name, cl_object l_unload) { /// qload-c++
/// args: (library-name &optional unload)
/// Loads a custom Qt/C++ plugin (see 'cpp-lib' in sources). The LIBRARY-NAME
/// has to be passed as path to the plugin, without file ending. This offers
/// a simple way to extend your application with your own Qt/C++ functions.
/// The plugin will be reloaded (if supported by the OS) every time you call
/// this function. If the UNLOAD argument is not NIL, the plugin will be
/// unloaded (if supported by the OS).
/// N.B: This works only for Qt6 functions with the following signature:
/// "QVariant foo(QVariant, ...)" ; max 10 QVariant arguments
/// Since a QVariant can also be of type QVariantList, this is a perfect fit
/// for (nested) Lisp lists.
/// (defparameter *c++* (qload-c++ "my-lib"))
/// (qapropos nil *c++*) ; documentation
/// (define-qt-wrappers *c++*) ; Lisp wrapper functions
static QHash<QString, QLibrary*> libraries;
QString libName = toQString(l_lib_name);
bool unload = (l_unload != ECL_NIL);
@ -235,6 +263,7 @@ cl_object qload_cpp(cl_object l_lib_name, cl_object l_unload) { /// qload-c++
// *** convenience functions ***
cl_object qtranslate(cl_object l_con, cl_object l_src, cl_object l_n) {
// called by QML:TR
QByteArray context(toQString(l_con).toUtf8());
QByteArray source(toQString(l_src).toUtf8());
int n = toInt(l_n);
@ -248,34 +277,32 @@ cl_object qtranslate(cl_object l_con, cl_object l_src, cl_object l_n) {
ecl_return1(ecl_process_env(), l_ret);
}
cl_object qlocal8bit(cl_object l_str) {
// returns 'ecl_simple_base_string', not Unicode
cl_object l_ret = from_cstring(toQString(l_str).toLocal8Bit());
ecl_return1(ecl_process_env(), l_ret);
}
cl_object qutf8(cl_object l_str) {
// returns 'ecl_simple_base_string', not Unicode
cl_object l_ret = from_cstring(toQString(l_str).toUtf8());
ecl_return1(ecl_process_env(), l_ret);
}
cl_object qfrom_utf8(cl_object l_ba) {
/// args: (byte-array)
/// Returns the BYTE-ARRAY (vector of octets) converted using
/// QString::fromUtf8().
cl_object l_ret = from_qstring(QString::fromUtf8(toQByteArray(l_ba)));
ecl_return1(ecl_process_env(), l_ret);
}
cl_object qescape(cl_object l_str) {
/// args: (string)
/// Calls QString::toHtmlEscaped().
cl_object l_ret = from_qstring(toQString(l_str).toHtmlEscaped());
ecl_return1(ecl_process_env(), l_ret);
}
cl_object qprocess_events() {
QGuiApplication::processEvents();
/// args: ()
/// Calls QCoreApplication::processEvents().
QCoreApplication::processEvents();
ecl_return1(ecl_process_env(), ECL_T);
}
cl_object qexec2(cl_object l_milliseconds) {
/// args: (&optional milliseconds)
/// Calls QCoreApplication::exec(). Optionally pass the time in milliseconds
/// after which QEventLoop::exit() will be called. See also QSLEEP.
ecl_process_env()->nvalues = 1;
if (l_milliseconds != ECL_NIL) {
static QTimer* timer = 0;
@ -290,11 +317,15 @@ cl_object qexec2(cl_object l_milliseconds) {
return l_milliseconds;
}
QCoreApplication::exit(); // prevent "the event loop is already running"
QGuiApplication::exec();
QCoreApplication::exec();
return ECL_T;
}
cl_object qexit() {
/// args: ()
/// Calls QEventLoop::exit(), in order to exit event processing after a call
/// QEXEC with a timeout. Returns T if the event loop has effectively been
/// exited.
ecl_process_env()->nvalues = 1;
if (LQML::eventLoop) {
if (LQML::eventLoop->isRunning()) {
@ -306,6 +337,9 @@ cl_object qexit() {
}
cl_object qsingle_shot2(cl_object l_msec, cl_object l_fun) {
/// args: (milliseconds function)
/// A single shot timer similar to QTimer::singleShot().
/// (qsingle-shot 1000 'one-second-later)
ecl_process_env()->nvalues = 1;
if (l_fun != ECL_NIL) {
new SingleShot(toInt(l_msec), l_fun); // see "delete this;" in "single_shot.h"
@ -316,12 +350,16 @@ cl_object qsingle_shot2(cl_object l_msec, cl_object l_fun) {
}
cl_object qversion() {
/// args: ()
/// Returns the LQML version number as 'year.month.counter'. The second
/// return value is the Qt version as returned by QLibraryInfo::version().
cl_object l_ret1 = from_cstring(LQML::version);
cl_object l_ret2 = from_cstring(qVersion());
cl_object l_ret2 = from_qstring(QLibraryInfo::version().toString());
ecl_return2(ecl_process_env(), l_ret1, l_ret2);
}
cl_object qrun_on_ui_thread2(cl_object l_function_or_closure, cl_object l_blocking) {
// for internal use, you should never need to call it explicitely
ecl_process_env()->nvalues = 1;
if (l_function_or_closure != ECL_NIL) {
QObject o;
@ -344,17 +382,18 @@ cl_object qrun_on_ui_thread2(cl_object l_function_or_closure, cl_object l_blocki
}
cl_object qlog2(cl_object l_msg) {
// for android logging only; see 'ini.lisp::qlog' and 'lqml.cpp::logMessageHandler'
// called by QML:QLOG
// for android logging only; see also 'lqml.cpp::logMessageHandler'
qDebug() << toQString(l_msg);
ecl_return1(ecl_process_env(), ECL_NIL);
}
cl_object qinvoke_method2(cl_object l_obj, cl_object l_name, cl_object l_args) {
// max. 10 arguments
// supported argument types: T, NIL, INTEGER, FLOAT, STRING,
// (nested) LIST of mentioned arguments
//
// N.B. does not support default arguments if used to call JS functions
// for internal use: this is used to call user defined JS functions, and to
// call user defined Qt/C++ plugin functions.
// Max. 10 arguments of type T, NIL, INTEGER, FLOAT, STRING, (nested) LIST of
// mentioned arguments. On Qt side, only QVariant arguments are allowed.
// N.B. does not support default arguments, if used to call JS functions
ecl_process_env()->nvalues = 1;
const int MAX = 10;
QVariant arg[MAX];
@ -385,6 +424,7 @@ cl_object qinvoke_method2(cl_object l_obj, cl_object l_name, cl_object l_args) {
}
cl_object js2(cl_object l_item, cl_object l_str) {
// called by function QML:JS
ecl_process_env()->nvalues = 1;
QObject* qobject = toQObjectPointer(l_item);
if (qobject != nullptr) {
@ -397,6 +437,7 @@ cl_object js2(cl_object l_item, cl_object l_str) {
}
cl_object qml_get2(cl_object l_item, cl_object l_name) {
// called by QML:QML-GET
QObject* qobject = toQObjectPointer(l_item);
QByteArray name = toCString(l_name);
if ((qobject != nullptr) && !name.isEmpty()) {
@ -411,6 +452,7 @@ cl_object qml_get2(cl_object l_item, cl_object l_name) {
}
cl_object qml_set2(cl_object l_item, cl_object l_name, cl_object l_value) {
// called by QML:QML-SET
ecl_process_env()->nvalues = 1;
QObject* qobject = toQObjectPointer(l_item);
QByteArray name = toCString(l_name);
@ -427,6 +469,8 @@ cl_object qml_set2(cl_object l_item, cl_object l_name, cl_object l_value) {
}
cl_object qobject_name(cl_object l_obj) {
/// args: (qobject)
/// Returns the QObject::objectName() of passed QOBJECT (FFI pointer).
ecl_process_env()->nvalues = 1;
QObject* qobject = toQObjectPointer(l_obj);
if (qobject != nullptr) {
@ -438,16 +482,19 @@ cl_object qobject_name(cl_object l_obj) {
}
cl_object root_item() {
/// args: ()
/// Returns the root item of the QQuickView.
ecl_process_env()->nvalues = 1;
cl_object l_ret = from_qobject_pointer(LQML::quickView->rootObject());
ecl_return1(ecl_process_env(), l_ret);
}
cl_object qquit2(cl_object l_status) {
// called by QML:QQUIT
int s = toInt(l_status);
qGuiApp->quit();
cl_shutdown();
LQML::cl_shutdown_p = true;
int s = toInt(l_status);
if (s < 0) {
abort();
} else {
@ -457,11 +504,14 @@ cl_object qquit2(cl_object l_status) {
}
cl_object pixel_ratio() {
/// args: ()
/// Returns the effective device pixel ratio.
cl_object l_ret = ecl_make_doublefloat(LQML::quickView->effectiveDevicePixelRatio());
ecl_return1(ecl_process_env(), l_ret);
}
cl_object reload2() {
// called by QML:RELOAD
LQML::quickView->engine()->clearComponentCache();
QUrl source(LQML::quickView->source());
LQML::quickView->setSource(source);
@ -564,6 +614,7 @@ static cl_object collectInfo(const QByteArray& type,
}
cl_object qapropos2(cl_object l_search, cl_object l_obj, cl_object l_no_offset) {
// called by QML:QAPROPOS
ecl_process_env()->nvalues = 1;
QByteArray search;
if (ECL_STRINGP(l_search)) {

View file

@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
cl_object js2 (cl_object, cl_object);
cl_object pixel_ratio ();
cl_object qapropos2 (cl_object, cl_object, cl_object);
cl_object qchild_items (cl_object);
cl_object qchildren (cl_object);
cl_object qescape (cl_object);
cl_object qexec2 (cl_object);
cl_object qexit ();
@ -61,7 +61,6 @@ cl_object qfind_children2 (cl_object, cl_object, cl_object);
cl_object qfrom_utf8 (cl_object);
cl_object qinvoke_method2 (cl_object, cl_object, cl_object);
cl_object qload_cpp (cl_object, cl_object);
cl_object qlocal8bit (cl_object);
cl_object qlog2 (cl_object);
cl_object qml_get2 (cl_object, cl_object);
cl_object qml_set2 (cl_object, cl_object, cl_object);
@ -73,7 +72,6 @@ cl_object qget2 (cl_object, cl_object);
cl_object qset2 (cl_object, cl_object);
cl_object qsingle_shot2 (cl_object, cl_object);
cl_object qtranslate (cl_object, cl_object, cl_object);
cl_object qutf8 (cl_object);
cl_object qversion ();
cl_object reload2 ();
cl_object root_item ();

View file

@ -48,7 +48,8 @@ LQML::LQML(int argc, char* argv[], QQuickView* view) : QObject() {
iniCLFunctions();
ecl_init_module(NULL, ini_LQML);
eval("(in-package :qml-user)");
eval(QString("(setf *quick-view* (make-qobject %1))").arg((quintptr)view));
eval(QString("(setf *quick-view* (make-qobject %1))")
.arg(reinterpret_cast<quintptr>(view)));
}
LQML::~LQML() {

View file

@ -28,6 +28,7 @@ int main(int argc, char* argv[]) {
//app.setOrganizationName("MyProject");
//app.setOrganizationDomain("my.org");
app.setApplicationName(QFileInfo(app.applicationFilePath()).baseName());
QStringList arguments(QCoreApplication::arguments());
QQuickView view;
ADD_MACOS_BUNDLE_IMPORT_PATH
@ -41,7 +42,6 @@ int main(int argc, char* argv[]) {
view.connect(view.engine(), &QQmlEngine::quit, &app, &QCoreApplication::quit);
LQML lqml(argc, argv, &view);
QStringList arguments(QCoreApplication::arguments());
if (arguments.contains("-v") || arguments.contains("--version")) {
lqml.printVersion();
std::cout << std::endl;
@ -49,16 +49,25 @@ int main(int argc, char* argv[]) {
}
new QQmlFileSelector(view.engine(), &view);
QUrl url("qrc:///qml/main.qml");
if (!QFile::exists(url.fileName())) {
url = "qml/main.qml";
QString qml("qml/main.qml");
QUrl url("qrc:///" + qml);
bool set = false;
if (QFile::exists(url.fileName())) {
set = true;
} else {
url = QUrl::fromLocalFile(qml);
if (QFile::exists(QDir::currentPath() + "/" + qml)) {
set = true;
}
}
view.setSource(url);
if (view.status() == QQuickView::Error) {
return -1;
if (set) {
view.setSource(url);
if (view.status() == QQuickView::Error) {
return -1;
}
view.setResizeMode(QQuickView::SizeRootObjectToView);
QTimer::singleShot(0, &view, &QQuickView::show);
}
view.setResizeMode(QQuickView::SizeRootObjectToView);
QTimer::singleShot(0, &view, &QQuickView::show);
// load .eclrc
if (arguments.contains("-norc")) {

View file

@ -246,7 +246,9 @@ cl_object from_qvariant(const QVariant& var) {
cl_object from_qobject_pointer(QObject* qobject) {
STATIC_SYMBOL_PKG (s_make_qobject, "MAKE-QOBJECT", "QML") // see 'ini.lisp'
return cl_funcall(2, s_make_qobject, ecl_make_unsigned_integer((quintptr)qobject));
return cl_funcall(2,
s_make_qobject,
ecl_make_unsigned_integer(reinterpret_cast<quintptr>(qobject)));
}
QT_END_NAMESPACE

View file

@ -20,7 +20,7 @@ QObject* iniQml() {
static QVariant qmlApply(QObject* caller, const QString& function, const QVariantList& arguments) {
QVariant var =
ecl_fun("qml:qml-apply",
QVariant((quintptr)caller),
QVariant(reinterpret_cast<quintptr>(caller)),
QVariant(function),
QVariant(arguments));
QString str(var.toString());

View file

@ -1,5 +1,3 @@
#undef SLOT
#include "qt_ecl.h"
#include "marshal.h"
#include "ecl_ext.h"

View file

@ -1,8 +1,6 @@
#ifndef SINGLE_SHOT_H
#define SINGLE_SHOT_H
#undef SLOT
#include <ecl/ecl.h>
#include <QObject>