mirror of
https://gitlab.com/eql/lqml.git
synced 2025-12-06 02:30:38 -08:00
Compare commits
3 commits
a64e53bb59
...
7a4918cc4b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a4918cc4b | ||
|
|
121170fcbd | ||
|
|
a9d93035b6 |
19 changed files with 598 additions and 7 deletions
|
|
@ -171,7 +171,7 @@ QVariant QT::iniDb(const QVariant& vName) {
|
|||
return vName;
|
||||
}
|
||||
|
||||
QVariant QT::sqlQuery(const QVariant& vQuery, const QVariant& vValues, const QVariant& vRows) {
|
||||
QVariant QT::sqlQuery(const QVariant& vQuery, const QVariant& vValues, const QVariant& vCols) {
|
||||
QVariantList results;
|
||||
QSqlQuery sqlQuery(db);
|
||||
if (db.open()) {
|
||||
|
|
@ -182,11 +182,11 @@ QVariant QT::sqlQuery(const QVariant& vQuery, const QVariant& vValues, const QVa
|
|||
sqlQuery.addBindValue(value);
|
||||
}
|
||||
if (sqlQuery.exec()) {
|
||||
auto rows = vRows.toInt();
|
||||
auto cols = vCols.toInt();
|
||||
while (sqlQuery.next()) {
|
||||
if (rows > 1) {
|
||||
if (cols > 1) {
|
||||
QVariantList list;
|
||||
for (auto r = 0; r < rows; r++) {
|
||||
for (auto r = 0; r < cols; r++) {
|
||||
list << sqlQuery.value(r);
|
||||
}
|
||||
results << QVariant(list);
|
||||
|
|
@ -194,7 +194,7 @@ QVariant QT::sqlQuery(const QVariant& vQuery, const QVariant& vValues, const QVa
|
|||
results << sqlQuery.value(0);
|
||||
}
|
||||
}
|
||||
if (!rows && query.startsWith("insert", Qt::CaseInsensitive)) {
|
||||
if (!cols && query.startsWith("insert", Qt::CaseInsensitive)) {
|
||||
results << sqlQuery.lastInsertId();
|
||||
}
|
||||
db.close();
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
(defvar *file* nil)
|
||||
|
||||
(defun query (query &rest values)
|
||||
(let ((rows (and (x:starts-with "select" query)
|
||||
(let ((cols (and (x:starts-with "select" query)
|
||||
(1+ (count #\, (subseq query 0 (search "from" query)))))))
|
||||
(qrun* (qt:sql-query qt:*cpp* query values rows))))
|
||||
(qrun* (qt:sql-query qt:*cpp* query values cols))))
|
||||
|
||||
(defun ini ()
|
||||
(setf *file* (app:in-data-path "db"))
|
||||
|
|
|
|||
9
examples/qsqlite/app.asd
Normal file
9
examples/qsqlite/app.asd
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
(defsystem :app
|
||||
:serial t
|
||||
:depends-on ()
|
||||
:components ((:file "lisp/package")
|
||||
(:file "lisp/qt")
|
||||
(:file "lisp/ui-vars")
|
||||
(:file "lisp/db")
|
||||
(:file "lisp/main")))
|
||||
|
||||
127
examples/qsqlite/app.pro
Normal file
127
examples/qsqlite/app.pro
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
LISP_FILES = $$files(lisp/*) app.asd make.lisp
|
||||
|
||||
exists(/etc/sailfish-release) {
|
||||
CONFIG += sfos
|
||||
}
|
||||
|
||||
android {
|
||||
32bit {
|
||||
ECL = $$(ECL_ANDROID_32)
|
||||
} else {
|
||||
ECL = $$(ECL_ANDROID)
|
||||
}
|
||||
lisp.commands = $$ECL/../ecl-android-host/bin/ecl \
|
||||
-norc -shell $$PWD/make.lisp
|
||||
} else:ios {
|
||||
lisp.commands = $$(ECL_IOS)/../ecl-ios-host/bin/ecl \
|
||||
-norc -shell $$PWD/make.lisp
|
||||
} else:unix {
|
||||
lisp.commands = /usr/local/bin/ecl -shell $$PWD/make.lisp
|
||||
} else:win32 {
|
||||
lisp.commands = ecl.exe -shell $$PWD/make.lisp
|
||||
}
|
||||
|
||||
lisp.input = LISP_FILES
|
||||
|
||||
win32: lisp.output = tmp/app.lib
|
||||
!win32: lisp.output = tmp/libapp.a
|
||||
|
||||
QMAKE_EXTRA_COMPILERS += lisp
|
||||
|
||||
win32: PRE_TARGETDEPS = tmp/app.lib
|
||||
!win32: PRE_TARGETDEPS = tmp/libapp.a
|
||||
|
||||
QT += quick qml quickcontrols2 sql
|
||||
TEMPLATE = app
|
||||
CONFIG += c++17 no_keywords release
|
||||
DEFINES = DESKTOP_APP INI_LISP QT_EXTENSION
|
||||
INCLUDEPATH = /usr/local/include
|
||||
LIBS = -L/usr/local/lib -lecl
|
||||
DESTDIR = .
|
||||
TARGET = app
|
||||
OBJECTS_DIR = tmp
|
||||
MOC_DIR = tmp
|
||||
|
||||
linux: LIBS += -L../../../platforms/linux/lib
|
||||
macx: LIBS += -L../../../platforms/macos/lib
|
||||
win32: LIBS += -L../../../platforms/windows/lib
|
||||
|
||||
win32 {
|
||||
include(../../src/windows.pri)
|
||||
}
|
||||
|
||||
android {
|
||||
DEFINES -= DESKTOP_APP
|
||||
INCLUDEPATH = $$ECL/include
|
||||
LIBS = -L$$ECL/lib -lecl
|
||||
LIBS += -L../../../platforms/android/lib
|
||||
|
||||
equals(QT_MAJOR_VERSION, 6) {
|
||||
QT += core-private
|
||||
}
|
||||
lessThan(QT_MAJOR_VERSION, 6) {
|
||||
QT += androidextras
|
||||
}
|
||||
|
||||
ANDROID_EXTRA_LIBS += $$ECL/lib/libecl.so
|
||||
ANDROID_PACKAGE_SOURCE_DIR = ../platforms/android
|
||||
|
||||
32bit {
|
||||
ANDROID_ABIS = "armeabi-v7a"
|
||||
} else {
|
||||
ANDROID_ABIS = "arm64-v8a"
|
||||
}
|
||||
}
|
||||
|
||||
ios {
|
||||
DEFINES -= DESKTOP_APP
|
||||
INCLUDEPATH = $$(ECL_IOS)/include
|
||||
LIBS = -L$$(ECL_IOS)/lib -lecl
|
||||
LIBS += -leclatomic -leclffi -leclgc -leclgmp
|
||||
LIBS += -L../../../platforms/ios/lib
|
||||
}
|
||||
|
||||
32bit {
|
||||
android {
|
||||
equals(QT_MAJOR_VERSION, 6) {
|
||||
LIBS += -llqml32_armeabi-v7a
|
||||
}
|
||||
lessThan(QT_MAJOR_VERSION, 6) {
|
||||
LIBS += -llqml32
|
||||
}
|
||||
}
|
||||
!android {
|
||||
LIBS += -llqml32
|
||||
}
|
||||
LIBS += -llisp32
|
||||
} else {
|
||||
android {
|
||||
equals(QT_MAJOR_VERSION, 6) {
|
||||
LIBS += -llqml_arm64-v8a
|
||||
}
|
||||
lessThan(QT_MAJOR_VERSION, 6) {
|
||||
LIBS += -llqml
|
||||
}
|
||||
}
|
||||
!android {
|
||||
LIBS += -llqml
|
||||
}
|
||||
LIBS += -llisp
|
||||
}
|
||||
|
||||
LIBS += -Ltmp -lapp
|
||||
|
||||
HEADERS += \
|
||||
../../src/cpp/main.h \
|
||||
cpp/qt.h
|
||||
|
||||
SOURCES += \
|
||||
../../src/cpp/main.cpp \
|
||||
cpp/qt.cpp
|
||||
|
||||
RESOURCES += $$files(qml/*)
|
||||
RESOURCES += $$files(i18n/*.qm)
|
||||
|
||||
lupdate_only {
|
||||
SOURCES += i18n/tr.h
|
||||
}
|
||||
BIN
examples/qsqlite/blob/logo-064.png
Executable file
BIN
examples/qsqlite/blob/logo-064.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
BIN
examples/qsqlite/blob/logo-128.png
Executable file
BIN
examples/qsqlite/blob/logo-128.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
examples/qsqlite/blob/logo-256.png
Executable file
BIN
examples/qsqlite/blob/logo-256.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
94
examples/qsqlite/cpp/qt.cpp
Normal file
94
examples/qsqlite/cpp/qt.cpp
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
#include "qt.h"
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include <QQuickView>
|
||||
#include <QtDebug>
|
||||
|
||||
QObject* ini() {
|
||||
static QObject* qt = nullptr;
|
||||
if (qt == nullptr) {
|
||||
qt = new QT;
|
||||
}
|
||||
return qt;
|
||||
}
|
||||
|
||||
QT::QT() : QObject() {
|
||||
}
|
||||
|
||||
QVariant QT::dataPath(const QVariant& prefix) {
|
||||
// for desktop
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
|
||||
path.truncate(path.lastIndexOf(QChar('/')));
|
||||
path.append(QStringLiteral("/lqml-qsqlite/") + prefix.toString());
|
||||
return path;
|
||||
}
|
||||
|
||||
// SQL
|
||||
|
||||
QVariant QT::iniDb(const QVariant& vName, const QVariant& vQuickView) {
|
||||
// add database image provider, in order to load images in QML directly from a SQL database
|
||||
auto quickView = vQuickView.value<QQuickView*>();
|
||||
quickView->engine()->addImageProvider(QLatin1String("db"), new DatabaseImageProvider(this));
|
||||
// ini
|
||||
db = QSqlDatabase::addDatabase("QSQLITE");
|
||||
db.setDatabaseName(vName.toString());
|
||||
return vName;
|
||||
}
|
||||
|
||||
QVariant QT::sqlQuery(const QVariant& vQuery, const QVariant& vValues, const QVariant& vCols) {
|
||||
QVariantList results;
|
||||
QSqlQuery sqlQuery(db);
|
||||
if (db.open()) {
|
||||
QString query = vQuery.toString();
|
||||
sqlQuery.prepare(vQuery.toString());
|
||||
const QVariantList values = vValues.value<QVariantList>();
|
||||
for (auto value : values) {
|
||||
sqlQuery.addBindValue(value);
|
||||
}
|
||||
if (sqlQuery.exec()) {
|
||||
auto cols = vCols.toInt();
|
||||
while (sqlQuery.next()) {
|
||||
if (cols > 1) {
|
||||
QVariantList list;
|
||||
for (auto r = 0; r < cols; r++) {
|
||||
list << sqlQuery.value(r);
|
||||
}
|
||||
results << QVariant(list);
|
||||
} else {
|
||||
results << sqlQuery.value(0);
|
||||
}
|
||||
}
|
||||
if (!cols && query.startsWith("insert", Qt::CaseInsensitive)) {
|
||||
results << sqlQuery.lastInsertId();
|
||||
}
|
||||
db.close();
|
||||
return results;
|
||||
}
|
||||
db.close();
|
||||
}
|
||||
QString text;
|
||||
if (sqlQuery.lastError().isValid()) {
|
||||
text = sqlQuery.lastError().text();
|
||||
} else {
|
||||
text = db.lastError().text();
|
||||
}
|
||||
qDebug() << "SQL error:" << text;
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
// database image provider
|
||||
|
||||
QPixmap DatabaseImageProvider::requestPixmap(const QString& name, QSize* size, const QSize& requestedSize) {
|
||||
auto result = qt->sqlQuery(
|
||||
"select data from images where name = ?",
|
||||
QVariantList() << name,
|
||||
1); // number of returned columns
|
||||
QPixmap pixmap;
|
||||
pixmap.loadFromData(result.value<QVariantList>().first().toByteArray());
|
||||
*size = pixmap.size();
|
||||
if (requestedSize.isValid() && (pixmap.size() != requestedSize)) {
|
||||
pixmap = pixmap.scaled(requestedSize);
|
||||
}
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
36
examples/qsqlite/cpp/qt.h
Normal file
36
examples/qsqlite/cpp/qt.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include <QtCore>
|
||||
#include <QSqlDatabase>
|
||||
#include <QQuickImageProvider>
|
||||
|
||||
#ifdef Q_CC_MSVC
|
||||
#define LIB_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define LIB_EXPORT
|
||||
#endif
|
||||
|
||||
extern "C" { LIB_EXPORT QObject* ini(); }
|
||||
|
||||
class QT : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Q_INVOKABLE QVariant dataPath(const QVariant&);
|
||||
Q_INVOKABLE QVariant iniDb(const QVariant&, const QVariant&);
|
||||
Q_INVOKABLE QVariant sqlQuery(const QVariant&, const QVariant&, const QVariant&);
|
||||
|
||||
QT();
|
||||
|
||||
QSqlDatabase db;
|
||||
};
|
||||
|
||||
class DatabaseImageProvider : public QQuickImageProvider {
|
||||
|
||||
public:
|
||||
DatabaseImageProvider(QT* _qt) : QQuickImageProvider(QQuickImageProvider::Pixmap), qt(_qt) {}
|
||||
|
||||
QPixmap requestPixmap(const QString&, QSize*, const QSize&);
|
||||
|
||||
QT* qt;
|
||||
};
|
||||
27
examples/qsqlite/cpp/qt.pro
Normal file
27
examples/qsqlite/cpp/qt.pro
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
QT += sql quick
|
||||
TEMPLATE = lib
|
||||
CONFIG += c++17 plugin release no_keywords
|
||||
DEFINES += PLUGIN
|
||||
INCLUDEPATH = /usr/local/include ../../../src/cpp
|
||||
LIBS = -L/usr/local/lib -lecl
|
||||
DESTDIR = ./
|
||||
TARGET = qt
|
||||
OBJECTS_DIR = ./tmp/
|
||||
MOC_DIR = ./tmp/
|
||||
|
||||
HEADERS += qt.h
|
||||
SOURCES += qt.cpp
|
||||
|
||||
linux {
|
||||
LIBS += -L../../../platforms/linux/lib
|
||||
}
|
||||
|
||||
macx {
|
||||
LIBS += -L../../../platforms/macos/lib
|
||||
}
|
||||
|
||||
win32 {
|
||||
include(../../../src/windows.pri)
|
||||
|
||||
LIBS += -L../../../platforms/windows/lib
|
||||
}
|
||||
34
examples/qsqlite/lisp/db.lisp
Normal file
34
examples/qsqlite/lisp/db.lisp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
(in-package :db)
|
||||
|
||||
(defvar *file* nil)
|
||||
|
||||
(defun query (query &rest values)
|
||||
(let ((rows (and (x:starts-with "select" query)
|
||||
(1+ (count #\, (subseq query 0 (search "from" query)))))))
|
||||
(qrun* (qt:sql-query qt:*cpp* query values rows))))
|
||||
|
||||
(defun ini ()
|
||||
(setf *file* (app:in-data-path "db"))
|
||||
(ensure-directories-exist *file*)
|
||||
(qt:ini-db qt:*cpp* (namestring *file*) *quick-view*)
|
||||
(query "create table if not exists images (id integer primary key autoincrement, name text, data blob)"))
|
||||
|
||||
(defun size ()
|
||||
(first (query "select count(*) from images")))
|
||||
|
||||
(defun save-image (name data)
|
||||
"Inserts image NAME, DATA (vector of octets) and returns the new image ID."
|
||||
(first (query "insert into images (name, data) values (?, ?)"
|
||||
name data)))
|
||||
|
||||
(defun load-images ()
|
||||
(query "select name, data from images order by id"))
|
||||
|
||||
(defun delete-image (id)
|
||||
(query "delete from images where id = ?"
|
||||
id)
|
||||
(values))
|
||||
|
||||
(defun delete-all-images ()
|
||||
(query "delete from images"))
|
||||
|
||||
35
examples/qsqlite/lisp/main.lisp
Normal file
35
examples/qsqlite/lisp/main.lisp
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
(in-package :app)
|
||||
|
||||
(defun ini ()
|
||||
(qt:ini)
|
||||
(db:ini)
|
||||
(populate-db)
|
||||
;; loads image directly from database, see 'cpp/qt.cpp::DatabaseImageProvider'
|
||||
(q> |source| ui:*logo* "image://db/logo-128"))
|
||||
|
||||
(defun in-data-path (&optional (file "") (prefix "data/"))
|
||||
#+mobile
|
||||
(merge-pathnames (x:cc prefix file))
|
||||
#-mobile
|
||||
(x:cc (qrun* (qt:data-path qt:*cpp* prefix)) file))
|
||||
|
||||
(defun file-bytes (file)
|
||||
(with-open-file (s file :element-type '(unsigned-byte 8))
|
||||
(let ((arr (make-array (file-length s) :element-type '(unsigned-byte 8))))
|
||||
(read-sequence arr s)
|
||||
arr)))
|
||||
|
||||
;; put images in database
|
||||
|
||||
(defun populate-db ()
|
||||
(let ((files (sort (directory (merge-pathnames "blob/*.png"))
|
||||
'string< :key 'pathname-name)))
|
||||
(when (/= (length files) (db:size))
|
||||
(if (probe-file (merge-pathnames "blob/"))
|
||||
(progn
|
||||
(db:delete-all-images)
|
||||
(dolist (file files)
|
||||
(db:save-image (pathname-name file) (file-bytes file)))))
|
||||
(x:d "No 'blob/' directory found."))))
|
||||
|
||||
(qlater 'ini)
|
||||
15
examples/qsqlite/lisp/package.lisp
Normal file
15
examples/qsqlite/lisp/package.lisp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
(defpackage :app
|
||||
(:use :cl :qml)
|
||||
(:export
|
||||
#:in-data-path))
|
||||
|
||||
(defpackage :db
|
||||
(:use :cl :qml)
|
||||
(:export
|
||||
#:delete-image
|
||||
#:delete-all-images
|
||||
#:ini
|
||||
#:load-images
|
||||
#:save-image
|
||||
#:size))
|
||||
|
||||
19
examples/qsqlite/lisp/qt.lisp
Normal file
19
examples/qsqlite/lisp/qt.lisp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
(defpackage :qt
|
||||
(:use :cl :qml)
|
||||
(:export
|
||||
#:*cpp*
|
||||
#:data-path
|
||||
#:ini
|
||||
#:ini-db
|
||||
#:sql-query))
|
||||
|
||||
(in-package :qt)
|
||||
|
||||
(defvar *cpp* nil)
|
||||
|
||||
(defun ini ()
|
||||
(setf *cpp*
|
||||
#+qt-plugin (qload-c++ "cpp/qt")
|
||||
#-qt-plugin (qfind-child nil "QT"))
|
||||
(let ((*package* (find-package :qt)))
|
||||
(define-qt-wrappers *cpp*)))
|
||||
9
examples/qsqlite/lisp/ui-vars.lisp
Normal file
9
examples/qsqlite/lisp/ui-vars.lisp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
(defpackage ui
|
||||
(:use :cl :qml)
|
||||
(:export
|
||||
#:*logo*))
|
||||
|
||||
(in-package :ui)
|
||||
|
||||
(defparameter *logo* "logo")
|
||||
|
||||
88
examples/qsqlite/make.lisp
Normal file
88
examples/qsqlite/make.lisp
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
;; check target
|
||||
(let ((arg (first (ext:command-args))))
|
||||
(mapc (lambda (name feature)
|
||||
(when (search name arg)
|
||||
(pushnew feature *features*)))
|
||||
(list "/ecl-android" "/ecl-ios")
|
||||
(list :android :ios)))
|
||||
|
||||
#+(or android ios)
|
||||
(pushnew :mobile *features*)
|
||||
|
||||
(when (probe-file "/etc/sailfish-release")
|
||||
(pushnew :sfos *features*))
|
||||
|
||||
(defun cc (&rest args)
|
||||
(apply 'concatenate 'string args))
|
||||
|
||||
#+mobile
|
||||
(defvar *assets* #+android "../platforms/android/assets/lib/"
|
||||
#+ios "../platforms/ios/assets/Library/")
|
||||
|
||||
#+mobile
|
||||
(defun shell (command)
|
||||
(ext:run-program "sh" (list "-c" command)))
|
||||
|
||||
#+mobile
|
||||
(let ((blob #+android *assets*
|
||||
#+ios (cc *assets* "../Documents/")))
|
||||
(ensure-directories-exist blob)
|
||||
(shell (cc "cp -r ../blob " blob)))
|
||||
|
||||
(require :asdf)
|
||||
(require :cmp)
|
||||
|
||||
(push (merge-pathnames "../")
|
||||
asdf:*central-registry*)
|
||||
|
||||
(setf *default-pathname-defaults*
|
||||
(truename (merge-pathnames "../../../"))) ; LQML root
|
||||
|
||||
(defvar *current*
|
||||
(let ((name (namestring *load-truename*)))
|
||||
(subseq name
|
||||
(length (namestring *default-pathname-defaults*))
|
||||
(1+ (position #\/ name :from-end t)))))
|
||||
|
||||
(dolist (file (list "package" "x" "ecl-ext" "ini" "qml")) ; load LQML symbols
|
||||
(load (merge-pathnames file "src/lisp/")))
|
||||
|
||||
(defun cc (&rest args)
|
||||
(apply 'concatenate 'string args))
|
||||
|
||||
(progn
|
||||
(defvar cl-user::*tr-path* (truename (cc *current* "i18n/")))
|
||||
(load "src/lisp/tr"))
|
||||
|
||||
#-mobile
|
||||
(asdf:make-build "app"
|
||||
:monolithic t
|
||||
:type :static-library
|
||||
:move-here (cc *current* "build/tmp/")
|
||||
:init-name "ini_app")
|
||||
|
||||
#+mobile
|
||||
(progn
|
||||
(pushnew :interpreter *features*)
|
||||
(defvar *asdf-system* "app")
|
||||
(defvar *ql-libs* (cc *current* "ql-libs.lisp"))
|
||||
(defvar *init-name* "ini_app")
|
||||
(defvar *library-path* (format nil "~Abuild-~A/tmp/"
|
||||
*current*
|
||||
#+android "android"
|
||||
#+ios "ios"))
|
||||
(defvar *require* (list :ecl-curl))
|
||||
(load "platforms/shared/make"))
|
||||
|
||||
;; rename lib
|
||||
(let* ((from #-mobile (cc *current* (format nil "build/tmp/app--all-systems.~A"
|
||||
#+msvc "lib"
|
||||
#-msvc "a"))
|
||||
#+mobile (cc *library-path* "app--all-systems.a"))
|
||||
(to #-msvc "libapp.a"
|
||||
#+msvc "app.lib")
|
||||
(to* #-mobile (cc *current* "build/tmp/" to)
|
||||
#+mobile (cc *library-path* to)))
|
||||
(when (probe-file to*)
|
||||
(delete-file to*))
|
||||
(rename-file from to))
|
||||
12
examples/qsqlite/qml/main.qml
Normal file
12
examples/qsqlite/qml/main.qml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
Item {
|
||||
width: 300
|
||||
height: 500
|
||||
|
||||
Image {
|
||||
objectName: "logo"
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
57
examples/qsqlite/readme.md
Normal file
57
examples/qsqlite/readme.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
Info
|
||||
----
|
||||
|
||||
This is a simple example of:
|
||||
|
||||
* using the **qsqlite** (Qt specific SQLite DB) library directly from Lisp
|
||||
* providing a custom image provider, so we can directly load images in QML from
|
||||
an SQL database
|
||||
|
||||
The qsqlite library that comes with Qt has the advantage of being pulled in
|
||||
automatically as a dependency, and behaving exactly the same, no matter what OS
|
||||
is used. This is especially convenient on mobile.
|
||||
|
||||
If you run the example with:
|
||||
```
|
||||
$ lqml run.lisp -slime
|
||||
```
|
||||
you can then try to change the image source from the REPL:
|
||||
```
|
||||
(in-package :app)
|
||||
|
||||
(q> |source| ui:*logo* "image://db/logo-256")
|
||||
```
|
||||
This will load the image directly from the database.
|
||||
|
||||
|
||||
Prepare
|
||||
-------
|
||||
|
||||
Please copy the app template files first:
|
||||
```
|
||||
$ cd ..
|
||||
$ ./copy.sh qsqlite
|
||||
```
|
||||
For running on the desktop, you'll also need to compile the plugin:
|
||||
```
|
||||
$ cd cpp
|
||||
$ qmake; make
|
||||
```
|
||||
|
||||
|
||||
Run
|
||||
---
|
||||
```
|
||||
lqml run.lisp
|
||||
```
|
||||
Optionally pass `-slime` to start a Swank server, and connect from Emacs with
|
||||
`M-x slime-connect`.
|
||||
|
||||
During development you can pass `-auto`, which will reload all QML files after
|
||||
you made a change to any of them and saved it. For re-initialization after
|
||||
reloading, file `lisp/qml-reload/on-reloaded` will be loaded.
|
||||
|
||||
Closing the window quits the app. If you try to kill it with `ctrl-c`, you need
|
||||
an additional `ctrl-d` to exit from ECL. To quit from Slime, do `(qq)` which is
|
||||
short for `(qquit)`.
|
||||
|
||||
29
examples/qsqlite/run.lisp
Normal file
29
examples/qsqlite/run.lisp
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
(in-package :qml-user)
|
||||
|
||||
(pushnew :qt-plugin *features*)
|
||||
|
||||
(require :asdf)
|
||||
|
||||
(push (merge-pathnames "./")
|
||||
asdf:*central-registry*)
|
||||
|
||||
(asdf:operate 'asdf:load-source-op :app)
|
||||
|
||||
(qset *quick-view*
|
||||
|x| 75
|
||||
|y| 75)
|
||||
|
||||
(defun option (name)
|
||||
(find name (ext:command-args) :test 'search))
|
||||
|
||||
;;; trivial auto reload of all QML files after saving any change
|
||||
|
||||
(when (option "-auto")
|
||||
(load "lisp/qml-reload/auto-reload"))
|
||||
|
||||
;;; for Slime after copying 'lqml-start-swank.lisp' from LQML sources
|
||||
;;; to your Slime directory, which is assumed to be '~/slime/'
|
||||
|
||||
(when (option "-slime")
|
||||
(load "~/slime/lqml-start-swank")) ; for 'slime-connect' from Emacs
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue