make all modules link on Windows; fix sparse DOS line endings; minor revisions;

This commit is contained in:
polos 2016-12-13 19:52:06 +01:00
parent b5654340e6
commit 1d5f1fcb3f
20 changed files with 3742 additions and 3735 deletions

View file

@ -21,9 +21,13 @@
<li>Add to your <code>~/.swank.lisp</code> file (or copy file <code>eql5/slime/.swank.lisp</code> in your home directory):
<br>(Please note: this isn't really optional -- you <b>need</b> to set this option for a useful Slime + EQL.)
<pre>(setf swank:*globally-redirect-io* t) ; show print output in Emacs</pre>
<li>Copy file <code>eql5/slime/eql-start-swank.lisp</code> in your <code>slime/</code> directory
</ul>
<li><p>Copy file <code>eql5/slime/eql-start-swank.lisp</code> in your <code>slime/</code> directory</p>
<li><i>Optionally:</i><br>In order to indent <code>qlet</code> correctly, edit your <code>slime/contrib/slime-cl-indent.el</code> file and add a line:
<pre>
(let* (as let)) ; already there
(qlet (as let)) ; new</pre>
<br>
</ul>
<h3>Run</h3>
<ul>
<li>Run the swank server (the command line option <code>-slime</code> can be omitted if the file name contains "start-swank"), optionally passing a Lisp file:

View file

@ -29,29 +29,29 @@ This macro simplifies the definition of UI variables:
Returns the <code>qt-object</code> of the given class/struct (see method <code>the-qt-object</code> in example <code>X-extras/CLOS-encapsulation.lisp</code>).<br>This function is used internally whenever a <code>qt-object</code> argument is expected.
<br>
<br><br>
<b>QADD-EVENT-FILTER (object event function) </b>
<b>QADD-EVENT-FILTER (object event function)</b>
<br><br>
Convenience function. Adds a Lisp function to be called on a given event type.<br>If the object argument is <code>NIL</code>, the event will be captured for the whole application.<br>If the Lisp function returns <code>NIL</code>, the event will be processed by Qt afterwards.<br><br>Returns a handle which can be used to remove the filter, see <code>qremove-event-filter</code>.<br><br>See also <code>qoverride</code> for <code>QObject::eventFilter(QObject*,QEvent*)</code> and <br><code>QObject::installEventFilter(QObject*)</code>,<br><code>QObject::removeEventFilter(QObject*)</code>.<br><br>The event class corresponds to the respective event type (no cast needed).
Convenience function. Adds a Lisp function to be called on a given event type.<br>If the object argument is <code>NIL</code>, the event will be captured for the whole application.<br>If the Lisp function returns <code>NIL</code>, the event will be processed by Qt afterwards.<br><br>Returns a handle which can be used to remove the filter, see <code>qremove-event-filter</code>.<br><br>See also <code>qoverride</code> for <code>QObject::eventFilter(QObject*,QEvent*)</code> and <br><code>QObject::installEventFilter(QObject*)</code>,<br><code>QObject::removeEventFilter(QObject*)</code>.<br><br>The event class corresponds to the respective event type (no cast needed).
<br>
<pre>
(qadd-event-filter nil |QEvent.MouseButtonPress| (lambda (object mouse-event) (print object) nil))
(qadd-event-filter nil |QEvent.MouseButtonPress| (lambda (object mouse-event) (print object) nil))
</pre>
<br><br>
<b>QAPP () </b>
<b>QAPP ()</b>
<br><br>
Convenience function returning <code>qApp</code>.
Convenience function returning <code>qApp</code>.
<br>
<br><br>
<b>QAPROPOS (&optional search-string class-name) </b>
<b>QAPROPOS (&optional search-string class-name)</b>
<br><br>
Finds all occurrencies of the given search string in the given object's meta information.<br>Constructors are listed under "Methods".<br>To list the user defined functions of external C++ classes (see Qt_EQL), pass the object instead of the class name.
Finds all occurrencies of the given search string in the given object's meta information.<br>Constructors are listed under "Methods".<br>To list the user defined functions of external C++ classes (see Qt_EQL), pass the object instead of the class name.
<br>
<pre>
(qapropos "html" "QTextEdit")
(qapropos nil "QWidget")
(qapropos)
(qapropos '|toString|) ; wrapper function symbol
(qapropos nil *qt-main*) ; see Qt_EQL, Qt_EQL (custom Qt classes)
(qapropos "html" "QTextEdit")
(qapropos nil "QWidget")
(qapropos)
(qapropos '|toString|) ; wrapper function symbol
(qapropos nil *qt-main*) ; see Qt_EQL, Qt_EQL (custom Qt classes)
</pre>
<br><br>
<b>QAPROPOS* (&optional search-string class-name)</b>
@ -69,62 +69,62 @@ Similar to <code>qapropos</code>, returning the results as nested list.
(setf *c++-reloaded* (lambda (var lib) (qapropos nil (symbol-value var)))) ; optional: set a notifier
</pre>
<br><br>
<b>QCALL-DEFAULT () </b>
<b>QCALL-DEFAULT ()</b>
<br><br>
To use anywhere inside an overridden function (see <code>qoverride</code>).<br>Calls the base implementation of the virtual Qt method <b>after</b> leaving the function body.<br><br>Optionally call the base implementation directly (if you want to do post-processing of the return value).
To use anywhere inside an overridden function (see <code>qoverride</code>).<br>Calls the base implementation of the virtual Qt method <b>after</b> leaving the function body.<br><br>Optionally call the base implementation directly (if you want to do post-processing of the return value).
<br>
<br><br>
<b>QCLEAR-EVENT-FILTERS () </b>
<b>QCLEAR-EVENT-FILTERS ()</b>
<br><br>
Clears all added event filters.
Clears all added event filters.
<br>
<br><br>
<b>QCONNECT (caller signal receiver/function &optional slot) </b>
<b>QCONNECT (caller signal receiver/function &optional slot)</b>
<br><br>
Connects either a Qt signal to a Qt slot, or a Qt signal to a Lisp function.
Connects either a Qt signal to a Qt slot, or a Qt signal to a Lisp function.
<br>
<pre>
(qconnect edit "textChanged(QString)" label "setText(QString)")
(qconnect edit "textChanged(QString)" (lambda (txt) (print txt)))
(qconnect edit "textChanged(QString)" label "setText(QString)")
(qconnect edit "textChanged(QString)" (lambda (txt) (print txt)))
</pre>
<br><br>
<b>QCOPY (object) </b>
<b>QCOPY (object)</b>
<br><br>
Copies <code>object</code> using copy-on-write, if such a constructor is available (non QObject derived classes only).<br>This function is short for e.g: <code>(qnew "QPixmap(QPixmap)" pixmap)</code><br><br>Note that the returned value will not be garbage collected (analogous to <code>qnew</code>).
Copies <code>object</code> using copy-on-write, if such a constructor is available (non QObject derived classes only).<br>This function is short for e.g: <code>(qnew "QPixmap(QPixmap)" pixmap)</code><br><br>Note that the returned value will not be garbage collected (analogous to <code>qnew</code>).
<br>
<pre>
(qcopy pixmap) ; QPen, QBrush, QFont, QPalette, QPixmap, QImage...
(qcopy pixmap) ; QPen, QBrush, QFont, QPalette, QPixmap, QImage...
</pre>
<br><br>
<b>QDELETE (object &optional later) </b>
<b>QDELETE (object &optional later)</b>
<br>
<b>QDEL </b>
<b>QDEL</b>
<br><br>
Deletes any Qt object, and sets the <code>pointer</code> value to <code>0</code>. Deleting a widget deletes all its child widgets, too.<br>If <code>later</code> is not <code>NIL</code>, the function <code>QObject::deleteLater()</code> will be called instead (but note: the <code>object</code> pointer will be set to <code>0</code> immediately.)<br>Returns <code>T</code> if the object has effectively been deleted.<br><br>See also <code>qlet</code> for local Qt objects.
Deletes any Qt object, and sets the <code>pointer</code> value to <code>0</code>. Deleting a widget deletes all its child widgets, too.<br>If <code>later</code> is not <code>NIL</code>, the function <code>QObject::deleteLater()</code> will be called instead (but note: the <code>object</code> pointer will be set to <code>0</code> immediately.)<br>Returns <code>T</code> if the object has effectively been deleted.<br><br>See also <code>qlet</code> for local Qt objects.
<br>
<pre>
(qdel widget)
(qdel socket :later)
(qdel widget)
(qdel socket :later)
</pre>
<br><br>
<b>QDISCONNECT (caller &optional signal receiver/function slot) </b>
<b>QDISCONNECT (caller &optional signal receiver/function slot)</b>
<br><br>
Disconnects signals to either Qt slots or Lisp functions. Anything but the caller can be either <code>NIL</code> or omitted.<br>Returns <code>T</code> if something has effectively been disconnected.
Disconnects signals to either Qt slots or Lisp functions. Anything but the caller can be either <code>NIL</code> or omitted.<br>Returns <code>T</code> if something has effectively been disconnected.
<br>
<pre>
(qdisconnect edit "textChanged(QString)" label "setText(QString)")
(qdisconnect edit "textChanged(QString)")
(qdisconnect edit nil label)
(qdisconnect edit)
(qdisconnect edit "textChanged(QString)" label "setText(QString)")
(qdisconnect edit "textChanged(QString)")
(qdisconnect edit nil label)
(qdisconnect edit)
</pre>
<br><br>
<b>QENUMS (class-name &optional enum-name) </b>
<b>QENUMS (class-name &optional enum-name)</b>
<br><br>
Returns the meta enum list of the given <code>class-name</code> and <code>enum-name</code> (see <code>Q_ENUMS</code> in Qt sources).<br>Omitting <code>enum-name</code> will return all meta enum lists of the class/scope.
Returns the meta enum list of the given <code>class-name</code> and <code>enum-name</code> (see <code>Q_ENUMS</code> in Qt sources).<br>Omitting <code>enum-name</code> will return all meta enum lists of the class/scope.
<br>
<pre>
(qenums "QLineEdit" "EchoMode") ; gives '("QLineEdit" ("EchoMode" ("Normal" . 0) ...))
(qenums "Qt")
(qenums "QLineEdit" "EchoMode") ; gives '("QLineEdit" ("EchoMode" ("Normal" . 0) ...))
(qenums "Qt")
</pre>
<br><br>
<b>QEQL (object1 object2)</b>
@ -135,9 +135,9 @@ Returns <code>T</code> for same instances of a Qt class. Comparing <code>QVarian
(= (qt-object-id object1) (qt-object-id object2))
</pre>
<br><br>
<b>QESCAPE (string) </b>
<b>QESCAPE (string)</b>
<br><br>
Calls <code>QString::toHtmlEscaped()</code>.
Calls <code>QString::toHtmlEscaped()</code>.
<br>
<br><br>
<b>QEVAL (&rest forms)</b>
@ -145,14 +145,14 @@ Calls <code>QString::toHtmlEscaped()</code>.
Slime mode <code>:repl-hook</code> only (not needed in default Slime mode): evaluate forms in GUI thread. Defaults to a simple <code>progn</code> outside of Slime.
<br>
<br><br>
<b>QEXEC (&optional milliseconds) </b>
<b>QEXEC (&optional milliseconds)</b>
<br><br>
Convenience function to call <code>QApplication::exec()</code>.<br>Optionally pass the time in milliseconds after which <code>QEventLoop::exit()</code> will be called.<br>See also <code>qsleep</code>.
Convenience function to call <code>QApplication::exec()</code>.<br>Optionally pass the time in milliseconds after which <code>QEventLoop::exit()</code> will be called.<br>See also <code>qsleep</code>.
<br>
<br><br>
<b>QEXIT () </b>
<b>QEXIT ()</b>
<br><br>
Calls <code>QEventLoop::exit()</code>, in order to exit event processing after a call to <code>qexec</code> with a timeout.<br>Returns <code>T</code> if the event loop has effectively been exited.
Calls <code>QEventLoop::exit()</code>, in order to exit event processing after a call to <code>qexec</code> with a timeout.<br>Returns <code>T</code> if the event loop has effectively been exited.
<br>
<br><br>
<b>QFIND-BOUND (&optional class-name)</b>
@ -168,25 +168,25 @@ Finds all symbols bound to Qt objects, returning both the Qt class names and the
Like <code>qfind-bound</code>, but returning the results as list of conses.
<br>
<br><br>
<b>QFIND-CHILD (object object-name) </b>
<b>QFIND-CHILD (object object-name)</b>
<br><br>
Calls <code>QObject::findChild&lt;QObject*&gt;()</code>.<br>Can be used to get the child objects of any Qt object (typically from a UI, see <code>qload-ui</code>), identified by <code>QObject::objectName()</code>.
Calls <code>QObject::findChild&lt;QObject*&gt;()</code>.<br>Can be used to get the child objects of any Qt object (typically from a UI, see <code>qload-ui</code>), identified by <code>QObject::objectName()</code>.
<br>
<pre>
(qfind-child *main* "editor")
(qfind-child *main* "editor")
</pre>
<br><br>
<b>QFIND-CHILDREN (object &optional object-name class-name) </b>
<b>QFIND-CHILDREN (object &optional object-name class-name)</b>
<br><br>
Calls <code>QObject::findChildren&lt;QObject*&gt;()</code>, returning a list of all child objects matching <code>object-name</code> and <code>class-name</code>.<br>Omitting the <code>&optional</code> arguments will find all children, recursively.
Calls <code>QObject::findChildren&lt;QObject*&gt;()</code>, returning a list of all child objects matching <code>object-name</code> and <code>class-name</code>.<br>Omitting the <code>&optional</code> arguments will find all children, recursively.
<br>
<pre>
(qfind-children *qt-main* nil "LightWidget") ; see Qt_EQL example
(qfind-children *qt-main* nil "LightWidget") ; see Qt_EQL example
</pre>
<br><br>
<b>QFROM-UTF8 (byte-array) </b>
<b>QFROM-UTF8 (byte-array)</b>
<br><br>
Returns the byte array (vector of octets) converted using <code>QString::fromUtf8()</code>.
Returns the byte array (vector of octets) converted using <code>QString::fromUtf8()</code>.
<br>
<br><br>
<b>QGUI (&optional process-events)</b>
@ -194,36 +194,36 @@ Returns the byte array (vector of octets) converted using <code>QString::fromUtf
Launches the EQL convenience GUI.<br>If you don't have an interactive environment, you can pass <code>T</code> to run a pseudo Qt event loop. A better option is to start the tool like so:<br><code>eql -qgui</code>, in order to run the Qt event loop natively.
<br>
<br><br>
<b>QID (name) </b>
<b>QID (name)</b>
<br><br>
Returns the internally used ID of the object name. Non QObject classes have negative ids.
Returns the internally used ID of the object name. Non QObject classes have negative ids.
<br>
<pre>
(qid "QWidget")
(qid "QWidget")
</pre>
<br><br>
<b>QINVOKE-METHOD (object function-name &rest arguments) </b>
<b>QINVOKE-METHOD (object function-name &rest arguments)</b>
<br>
<b>QFUN </b>
<b>QFUN</b>
<br><br>
Calls any of Qt methods, slots, signals. Static methods can be called by passing the string name of an object.<br><br>The most convenient way of calling Qt methods is to use the wrapper functions (see alternative 2 below), which allows for tab completion, showing all possible candidates in case of ambiguous type lists (overloaded methods). Additionally, static functions are shown as one symbol (easily catching the eye).<br><br>(Optionally you can pass the argument types (as for <code>qconnect</code> and <code>qoverride</code>), which may result in better performance, but only in some edge cases.)
Calls any of Qt methods, slots, signals. Static methods can be called by passing the string name of an object.<br><br>The most convenient way of calling Qt methods is to use the wrapper functions (see alternative 2 below), which allows for tab completion, showing all possible candidates in case of ambiguous type lists (overloaded methods). Additionally, static functions are shown as one symbol (easily catching the eye).<br><br>(Optionally you can pass the argument types (as for <code>qconnect</code> and <code>qoverride</code>), which may result in better performance, but only in some edge cases.)
<br>
<pre>
(qfun item "setText" 0 "Some objects are EQL.")
(qfun "QDateTime" "currentDateTime") ; static method
(qfun slider "valueChanged" 10) ; emit signal
;; alternative 1: (macro '!')
(! "setText" item 0 "Some objects are EQL.")
(! "currentDateTime" "QDateTime")
(! "valueChanged" slider 10)
;; alternative 2: (wrapper functions)
(|setText| item 0 "Some objects are EQL.")
(|currentDateTime.QDateTime|)
(|valueChanged| slider 10)
(qfun item "setText" 0 "Some objects are EQL.")
(qfun "QDateTime" "currentDateTime") ; static method
(qfun slider "valueChanged" 10) ; emit signal
;; alternative 1: (macro '!')
(! "setText" item 0 "Some objects are EQL.")
(! "currentDateTime" "QDateTime")
(! "valueChanged" slider 10)
;; alternative 2: (wrapper functions)
(|setText| item 0 "Some objects are EQL.")
(|currentDateTime.QDateTime|)
(|valueChanged| slider 10)
</pre>
<br><br>
<b>QINVOKE-METHOD* (object cast-class-name function-name &rest arguments)</b>
@ -312,29 +312,29 @@ Similar to <code>let*</code> (and to local C++ variables).<br><br>Creates tempor
Convenience function for Slime (or when loading EQL files from an ECL thread).<br>Loading files that create many Qt objects can be slow on the Slime REPL (many thread switches).<br>This function reduces all thread switches (GUI related) to a single one.
<br>
<br><br>
<b>QLOAD-C++ (library-name &optional unload) </b>
<b>QLOAD-C++ (library-name &optional unload)</b>
<br><br>
Loads a custom Qt/C++ plugin (see <code>Qt_EQL/</code>).<br>The <code>library-name</code> has to be passed as path to the plugin, without file ending.<br><br>This offers a simple way to extend your application with your own Qt/C++ functions.<br>The plugin will be reloaded (if supported by the OS) every time you call this function (Linux: see also <code>qauto-reload-c++</code>).<br>If the <code>unload</code> argument is not <code>NIL</code>, the plugin will be unloaded (if supported by the OS).
Loads a custom Qt/C++ plugin (see <code>Qt_EQL/</code>).<br>The <code>library-name</code> has to be passed as path to the plugin, without file ending.<br><br>This offers a simple way to extend your application with your own Qt/C++ functions.<br>The plugin will be reloaded (if supported by the OS) every time you call this function (Linux: see also <code>qauto-reload-c++</code>).<br>If the <code>unload</code> argument is not <code>NIL</code>, the plugin will be unloaded (if supported by the OS).
<br>
<pre>
(defparameter *c++* (qload-c++ "eql_cpp")) ; load (Linux: see also QAUTO-RELOAD-C++)
(qapropos nil *c++*) ; documentation
(! "mySpeedyQtFunction" (:qt *c++*)) ; call library function (note :qt)
(defparameter *c++* (qload-c++ "eql_cpp")) ; load (Linux: see also QAUTO-RELOAD-C++)
(qapropos nil *c++*) ; documentation
(! "mySpeedyQtFunction" (:qt *c++*)) ; call library function (note :qt)
</pre>
<br><br>
<b>QLOAD-UI (file-name) </b>
<b>QLOAD-UI (file-name)</b>
<br><br>
Calls a custom <code>QUiLoader::load()</code> function, loading a UI file created by Qt Designer. Returns the top level widget of the UI.<br>Use <code>qfind-child</code> to retrieve the child widgets.
Calls a custom <code>QUiLoader::load()</code> function, loading a UI file created by Qt Designer. Returns the top level widget of the UI.<br>Use <code>qfind-child</code> to retrieve the child widgets.
<br>
<pre>
(qload-ui "my-fancy-gui.ui")
(qload-ui "my-fancy-gui.ui")
</pre>
<br><br>
<b>QLOCAL8BIT (string) </b>
<b>QLOCAL8BIT (string)</b>
<br><br>
Converts a Unicode pathname to a simple ECL base string, using <code>QString::toLocal8Bit()</code> (see <code>QLocale</code> settings).<br>Depending on the OS (namely Windows), this is necessary if you get a filename from Qt and want to use it in ECL.<br><br>See also <b>QUTF8</b>.
Converts a Unicode pathname to a simple ECL base string, using <code>QString::toLocal8Bit()</code> (see <code>QLocale</code> settings).<br>Depending on the OS (namely Windows), this is necessary if you get a filename from Qt and want to use it in ECL.<br><br>See also <b>QUTF8</b>.
<br>
<br><br>
<b>QMESSAGE-BOX (x)</b>
@ -344,17 +344,17 @@ Converts a Unicode pathname to a simple ECL base string, using <code>QString::to
Convenience function: a simple message box, converting <code>x</code> to a string if necessary.<br>Returns its argument (just like <code>print</code>).
<br>
<br><br>
<b>QNEW-INSTANCE (class-name &rest arguments/properties) </b>
<b>QNEW-INSTANCE (class-name &rest arguments/properties)</b>
<br>
<b>QNEW </b>
<b>QNEW</b>
<br><br>
Creates a new Qt object, optionally passing the given arguments to the constructor.<br>Additionally you can pass any number of property/value pairs.<br>Please note how you can abbreviate long type lists.
Creates a new Qt object, optionally passing the given arguments to the constructor.<br>Additionally you can pass any number of property/value pairs.<br>Please note how you can abbreviate long type lists.
<br>
<pre>
(qnew "QWidget")
(qnew "QPixmap(int,int)" 50 50) ; constructor
(qnew "QLabel" "text" "Readme") ; set property
(qnew "QMatrix4x4(qreal...)" 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4)
(qnew "QWidget")
(qnew "QPixmap(int,int)" 50 50) ; constructor
(qnew "QLabel" "text" "Readme") ; set property
(qnew "QMatrix4x4(qreal...)" 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4)
</pre>
<br><br>
<b>QNEW-INSTANCE* (class-name &rest arguments/properties)</b>
@ -371,32 +371,32 @@ Convenience function for the REPL.<br>Same as <code>qnew</code>, but showing the
Checks for a <code>0</code> Qt object pointer.
<br>
<br><br>
<b>QOBJECT-NAMES (&optional type) </b>
<b>QOBJECT-NAMES (&optional type)</b>
<br><br>
Returns all supported object names. Passing either <code>:q</code> or <code>:n</code> returns only the QObject inherited, or not QObject inherited names, respectively.
Returns all supported object names. Passing either <code>:q</code> or <code>:n</code> returns only the QObject inherited, or not QObject inherited names, respectively.
<br>
<br><br>
<b>QOK () </b>
<b>QOK ()</b>
<br><br>
Needed to get the boolean <b>ok</b> value in cases like this:
Needed to get the boolean <b>ok</b> value in cases like this:
<br>
<pre>
(! "getFont(bool*)" "QFontDialog" nil)
(|getFont.QFontDialog| nil) ; NIL needed for &lt;bool*&gt;
(! "getFont(bool*)" "QFontDialog" nil)
(|getFont.QFontDialog| nil) ; NIL needed for &lt;bool*&gt;
</pre>
<br><br>
<b>QOVERRIDE (object name function) </b>
<b>QOVERRIDE (object name function)</b>
<br><br>
Sets a Lisp function to be called on a virtual Qt method.<br>To remove a function, pass <code>NIL</code> instead of the function argument.<br><br>If you call <code>qcall-default</code> anywhere inside your overridden function, the base implementation will be called <b>afterwards</b>.<br>Instead of <code>qcall-default</code> you can directly call the base implementation, which is useful if you want to do post-processing of the returned value.
Sets a Lisp function to be called on a virtual Qt method.<br>To remove a function, pass <code>NIL</code> instead of the function argument.<br><br>If you call <code>qcall-default</code> anywhere inside your overridden function, the base implementation will be called <b>afterwards</b>.<br>Instead of <code>qcall-default</code> you can directly call the base implementation, which is useful if you want to do post-processing of the returned value.
<br>
<pre>
(qoverride edit "keyPressEvent(QKeyEvent*)" (lambda (ev) (print (|key| ev)) (qcall-default)))
(qoverride edit "keyPressEvent(QKeyEvent*)" (lambda (ev) (print (|key| ev)) (qcall-default)))
</pre>
<br><br>
<b>QPROCESS-EVENTS () </b>
<b>QPROCESS-EVENTS ()</b>
<br><br>
Convenience function to call <code>QApplication::processEvents()</code>.
Convenience function to call <code>QApplication::processEvents()</code>.
<br>
<br><br>
<b>QPROPERTIES (object &optional (depth 1))</b>
@ -409,14 +409,14 @@ Prints all current properties of <code>object</code>, searching both all Qt prop
(qproperties *tool-button* 2) ; depth 2: both QToolButton and QAbstractButton
</pre>
<br><br>
<b>QPROPERTY (object name) </b>
<b>QPROPERTY (object name)</b>
<br>
<b>QGET </b>
<b>QGET</b>
<br><br>
Gets a Qt property. Enumerator values are returned as <code>int</code> values.<br>Returns <code>T</code> as second return value for successful calls.
Gets a Qt property. Enumerator values are returned as <code>int</code> values.<br>Returns <code>T</code> as second return value for successful calls.
<br>
<pre>
(qget label "text")
(qget label "text")
</pre>
<br><br>
<b>QQUIT (&optional (exit-status 0) (kill-all-threads t))</b>
@ -426,17 +426,17 @@ Gets a Qt property. Enumerator values are returned as <code>int</code> values.<b
Terminates EQL. Use this function to quit gracefully, <b>not</b> <code>ext:quit</code>.<br><br>Negative values for <code>exit-status</code> will call <code>abort()</code> instead of normal program exit (e.g. to prevent infinite error message loops in some nasty cases).
<br>
<br><br>
<b>QREMOVE-EVENT-FILTER (handle) </b>
<b>QREMOVE-EVENT-FILTER (handle)</b>
<br><br>
Removes the event filter corresponding to <code>handle</code>, which is the return value of <code>qadd-event-filter</code>.<br>Returns <code>handle</code> if the event filter has effectively been removed.<br>See also <code>qclear-event-filters</code>.
Removes the event filter corresponding to <code>handle</code>, which is the return value of <code>qadd-event-filter</code>.<br>Returns <code>handle</code> if the event filter has effectively been removed.<br>See also <code>qclear-event-filters</code>.
<br>
<br><br>
<b>QREQUIRE (module &optional quiet) </b>
<b>QREQUIRE (module &optional quiet)</b>
<br><br>
Loads an EQL module, corresponding to a Qt module.<br>Returns the module name if both loading and initializing have been successful.<br>If the <code>quiet</code> argument is not <code>NIL</code>, no error message will be shown on failure.<br><br>Currently available modules: <code>:help :multimedia :network :sql :svg :webkit</code>
Loads an EQL module, corresponding to a Qt module.<br>Returns the module name if both loading and initializing have been successful.<br>If the <code>quiet</code> argument is not <code>NIL</code>, no error message will be shown on failure.<br><br>Currently available modules: <code>:help :multimedia :network :sql :svg :webkit</code>
<br>
<pre>
(qrequire :network)
(qrequire :network)
</pre>
<br><br>
<b>QRGB (red green blue &optional (alpha 255))</b>
@ -444,14 +444,14 @@ Loads an EQL module, corresponding to a Qt module.<br>Returns the module name if
Constructs a <code>(unsigned-byte 32)</code> value that represents a 32 bit pixel color specified by the red, green, blue and alpha values.
<br>
<br><br>
<b>QRUN-IN-GUI-THREAD (function &optional (blocking t)) </b>
<b>QRUN-IN-GUI-THREAD (function &optional (blocking t))</b>
<br>
<b>QRUN </b>
<b>QRUN</b>
<br><br>
Runs <code>function</code> in GUI thread while (by default) blocking the calling thread (if called from main thread, <code>function</code> will simply be called directly).<br>This is needed to run GUI code from ECL threads other than the main thread.<br>Returns <code>T</code> on success.<br><br>There are 2 reasons to always wrap any EQL function like this, if called from another ECL thread:<ul><li>Qt GUI methods always need to run in the GUI thread<li>EQL functions are not designed to be reentrant (not needed for GUI code)</ul>See also macro <code>qrun*</code>.
Runs <code>function</code> in GUI thread while (by default) blocking the calling thread (if called from main thread, <code>function</code> will simply be called directly).<br>This is needed to run GUI code from ECL threads other than the main thread.<br>Returns <code>T</code> on success.<br><br>There are 2 reasons to always wrap any EQL function like this, if called from another ECL thread:<ul><li>Qt GUI methods always need to run in the GUI thread<li>EQL functions are not designed to be reentrant (not needed for GUI code)</ul>See also macro <code>qrun*</code>.
<br>
<pre>
(qrun 'update-view-data)
(qrun 'update-view-data)
</pre>
<br><br>
<b>QRUN-IN-GUI-THREAD* (&body body)</b>
@ -477,9 +477,9 @@ Allows to select (by clicking) any (child) widget.<br>The variable <code>qsel:*q
(qsel (lambda (widget) (qmsg widget)))
</pre>
<br><br>
<b>QSENDER () </b>
<b>QSENDER ()</b>
<br><br>
Corresponding to <code>QObject::sender()</code>. To use inside a Lisp function connected to a Qt signal.
Corresponding to <code>QObject::sender()</code>. To use inside a Lisp function connected to a Qt signal.
<br>
<br><br>
<b>QSET-COLOR (widget color-role color)</b>
@ -495,14 +495,14 @@ Convenience function for simple color settings (avoiding <code>QPalette</code> b
Sets the Qt object pointer to <code>0</code>. This function is called automatically after <code>qdel</code>.
<br>
<br><br>
<b>QSET-PROPERTY (object name value) </b>
<b>QSET-PROPERTY (object name value)</b>
<br>
<b>QSET </b>
<b>QSET</b>
<br><br>
Sets a Qt property. Enumerators have to be passed as <code>int</code> values.<br>Returns <code>T</code> as second return value for successful calls.
Sets a Qt property. Enumerators have to be passed as <code>int</code> values.<br>Returns <code>T</code> as second return value for successful calls.
<br>
<pre>
(qset label "alignment" |Qt.AlignCenter|)
(qset label "alignment" |Qt.AlignCenter|)
</pre>
<br><br>
<b>QSIGNAL (name)</b>
@ -510,15 +510,15 @@ Sets a Qt property. Enumerators have to be passed as <code>int</code> values.<br
Needed in functions which expect a <code>const char*</code> Qt signal (not needed in <code>qconnect</code>).
<br>
<br><br>
<b>QSINGLE-SHOT (milliseconds function) </b>
<b>QSINGLE-SHOT (milliseconds function)</b>
<br><br>
A single shot timer similar to <code>QTimer::singleShot()</code>.
A single shot timer similar to <code>QTimer::singleShot()</code>.
<br>
<pre>
(qsingle-shot 1000 'one-second-later)
(let ((ms 500))
&nbsp;&nbsp;(qsingle-shot ms (lambda () (qmsg ms))))
(qsingle-shot 1000 'one-second-later)
(let ((ms 500))
&nbsp;&nbsp;(qsingle-shot ms (lambda () (qmsg ms))))
</pre>
<br><br>
<b>QSLEEP (seconds)</b>
@ -531,51 +531,51 @@ Similar to <code>sleep</code>, but continuing to process Qt events.
Needed in functions which expect a <code>const char*</code> Qt slot (not needed in <code>qconnect</code>).
<br>
<br><br>
<b>QSTATIC-META-OBJECT (class-name) </b>
<b>QSTATIC-META-OBJECT (class-name)</b>
<br><br>
Returns the <code>::staticMetaObject</code> of the given class name.
Returns the <code>::staticMetaObject</code> of the given class name.
<br>
<pre>
(qstatic-meta-object "QEasingCurve")
(qstatic-meta-object "QEasingCurve")
</pre>
<br><br>
<b>QSUPER-CLASS-NAME (name) </b>
<b>QSUPER-CLASS-NAME (name)</b>
<br><br>
Returns the super class of an object name, or <code>NIL</code> if the class doesn't inherit another Qt class.<br>Returns <code>T</code> as second return value for successful calls.
Returns the super class of an object name, or <code>NIL</code> if the class doesn't inherit another Qt class.<br>Returns <code>T</code> as second return value for successful calls.
<br>
<pre>
(qsuper-class-name "QGraphicsLineItem")
(qsuper-class-name "QGraphicsLineItem")
</pre>
<br><br>
<b>QT-OBJECT-? (object) </b>
<b>QT-OBJECT-? (object)</b>
<br><br>
Returns the specific <code>qt-object</code> of a generic <code>qt-object</code>.<br>Works for QObject and QEvent inherited classes only.
Returns the specific <code>qt-object</code> of a generic <code>qt-object</code>.<br>Works for QObject and QEvent inherited classes only.
<br>
<pre>
(qt-object-? (|parentWidget| widget))
(qt-object-? (|widget| (|itemAt| box-layout 0)))
(qt-object-? event)
(qt-object-? (|parentWidget| widget))
(qt-object-? (|widget| (|itemAt| box-layout 0)))
(qt-object-? event)
</pre>
<br><br>
<b>QT-OBJECT-NAME (object) </b>
<b>QT-OBJECT-NAME (object)</b>
<br><br>
Returns the Qt class name.
Returns the Qt class name.
<br>
<br><br>
<b>QUI-CLASS (file-name &optional object-name) </b>
<b>QUI-CLASS (file-name &optional object-name)</b>
<br><br>
Finds the class name for the given user-defined object name in the given UI file.<br>Omitting the object name will return the top level class name of the UI.
Finds the class name for the given user-defined object name in the given UI file.<br>Omitting the object name will return the top level class name of the UI.
<br>
<pre>
(qui-class "examples/data/main-window.ui" "editor") ; returns "QTextEdit"
(qui-class "examples/data/main-window.ui" "editor") ; returns "QTextEdit"
</pre>
<br><br>
<b>QUI-NAMES (file-name) </b>
<b>QUI-NAMES (file-name)</b>
<br><br>
Finds all user-defined object names in the given UI file.
Finds all user-defined object names in the given UI file.
<br>
<pre>
(qui-names "examples/data/main-window.ui")
(qui-names "examples/data/main-window.ui")
</pre>
<br><br>
<b>QUIC (&optional (file.h "ui.h") (file.lisp "ui.lisp") (ui-package :ui))</b>
@ -583,14 +583,14 @@ Finds all user-defined object names in the given UI file.
Takes C++ code from a file generated by the <code>uic</code> user interface compiler, and generates the corresponding EQL code.<br>See also command line option <code>-quic</code>.
<br>
<br><br>
<b>QUTF8 (string) </b>
<b>QUTF8 (string)</b>
<br><br>
Converts a Unicode pathname to a simple ECL base string, using <code>QString::toUtf8()</code>.<br>Depending on the OS (namely OSX, Linux), this is necessary if you get a filename from Qt and want to use it in ECL.<br><br>See also <b>QLOCAL8BIT</b>.
Converts a Unicode pathname to a simple ECL base string, using <code>QString::toUtf8()</code>.<br>Depending on the OS (namely OSX, Linux), this is necessary if you get a filename from Qt and want to use it in ECL.<br><br>See also <b>QLOCAL8BIT</b>.
<br>
<br><br>
<b>QVERSION () </b>
<b>QVERSION ()</b>
<br><br>
Returns the EQL version number as "&lt;year&gt;.&lt;month&gt;.&lt;counter&gt;", analogous to the ECL version number.<br>The second return value is the Qt version as returned by <code>qVersion()</code>.
Returns the EQL version number as "&lt;year&gt;.&lt;month&gt;.&lt;counter&gt;", analogous to the ECL version number.<br>The second return value is the Qt version as returned by <code>qVersion()</code>.
<br>
<br><br>
<b>TR (source &optional context plural-number)</b>

View file

@ -1,31 +1,31 @@
#include <QtCore>
#include <QtNetwork>
#include <QtDebug>
#include <iostream>
int main(int argc, char** argv) {
QCoreApplication qapp(argc, argv);
QLocalSocket socket;
socket.connectToServer("EQL:local-server");
socket.waitForConnected();
qapp.processEvents();
QString exp(QCoreApplication::arguments().at(1));
if(socket.isWritable()) {
QString data(QString::number(exp.size()) + " " + exp);
socket.write(data.toLatin1());
qapp.processEvents();
socket.waitForBytesWritten();
while(true) {
socket.waitForReadyRead();
qapp.processEvents();
QString data(socket.readAll());
QString type(data.section(' ', 1, 1));
if(!(":EXPRESSION" == type)) {
QString print(data.section(' ', 2).trimmed());
if(!print.isEmpty()) {
std::cout << qPrintable(print) << std::endl; }
if(":VALUES" == type) {
exit(0); }}}}
qCritical() << "[send] error:" << exp;
return -1; }
#include <QtCore>
#include <QtNetwork>
#include <QtDebug>
#include <iostream>
int main(int argc, char** argv) {
QCoreApplication qapp(argc, argv);
QLocalSocket socket;
socket.connectToServer("EQL:local-server");
socket.waitForConnected();
qapp.processEvents();
QString exp(QCoreApplication::arguments().at(1));
if(socket.isWritable()) {
QString data(QString::number(exp.size()) + " " + exp);
socket.write(data.toLatin1());
qapp.processEvents();
socket.waitForBytesWritten();
while(true) {
socket.waitForReadyRead();
qapp.processEvents();
QString data(socket.readAll());
QString type(data.section(' ', 1, 1));
if(!(":EXPRESSION" == type)) {
QString print(data.section(' ', 2).trimmed());
if(!print.isEmpty()) {
std::cout << qPrintable(print) << std::endl; }
if(":VALUES" == type) {
exit(0); }}}}
qCritical() << "[send] error:" << exp;
return -1; }

View file

@ -1,5 +1,8 @@
;;; port of example "camera" (QtMultimediaWidgets)
#-qt-wrapper-functions ; see README-OPTIONAL.txt
(load (in-home "src/lisp/all-wrappers"))
(qrequire :multimedia)
(defpackage :camera

View file

@ -7,7 +7,7 @@
(in-package :eql-user)
(load "ui/ui-dom") ; generated: "eql5 -quic dom.ui"
(require :ui (in-home "examples/M-modules/webkit/ui/ui-dom")) ; generated: "eql5 -quic dom.ui"
(defun ini (&optional url)
(ui:ini t)

View file

@ -1,46 +1,46 @@
#include <ecl/ecl.h>
#include "eql.h"
#include "main.h"
extern "C" void ini_app(cl_object);
// Qt_EQL
QT_BEGIN_NAMESPACE
static qreal easingFunction(qreal progress) {
return eql_fun("eql-user::custom-easing-function", QVariant::Double,
Q_ARG(qreal, progress)).toDouble(); }
QEasingCurve* Qt_EQL_Application::easingCurve() {
static QEasingCurve* curve = 0;
if(!curve) {
curve = new QEasingCurve(QEasingCurve::Custom);
curve->setCustomType(easingFunction); }
return curve; }
QT_END_NAMESPACE
// main
int catch_all_qexec() {
int ret = 0;
CL_CATCH_ALL_BEGIN(ecl_process_env()) {
ret = QApplication::exec(); }
CL_CATCH_ALL_END;
return ret; }
int main(int argc, char** argv) {
EQL::ini(argv);
Qt_EQL_Application qapp(argc, argv);
QTextCodec* utf8 = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(utf8);
EQL eql;
eql.exec(ini_app);
return catch_all_qexec(); }
#include <ecl/ecl.h>
#include "eql.h"
#include "main.h"
extern "C" void ini_app(cl_object);
// Qt_EQL
QT_BEGIN_NAMESPACE
static qreal easingFunction(qreal progress) {
return eql_fun("eql-user::custom-easing-function", QVariant::Double,
Q_ARG(qreal, progress)).toDouble(); }
QEasingCurve* Qt_EQL_Application::easingCurve() {
static QEasingCurve* curve = 0;
if(!curve) {
curve = new QEasingCurve(QEasingCurve::Custom);
curve->setCustomType(easingFunction); }
return curve; }
QT_END_NAMESPACE
// main
int catch_all_qexec() {
int ret = 0;
CL_CATCH_ALL_BEGIN(ecl_process_env()) {
ret = QApplication::exec(); }
CL_CATCH_ALL_END;
return ret; }
int main(int argc, char** argv) {
EQL::ini(argv);
Qt_EQL_Application qapp(argc, argv);
QTextCodec* utf8 = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(utf8);
EQL eql;
eql.exec(ini_app);
return catch_all_qexec(); }

View file

@ -1,20 +1,20 @@
#ifndef MAIN_H
#define MAIN_H
#include <QtWidgets>
#include "eql_fun.h"
QT_BEGIN_NAMESPACE
class Qt_EQL_Application : public QApplication {
Q_OBJECT
public:
Qt_EQL_Application(int argc, char** argv) : QApplication(argc, argv) {}
// simple variant of "Qt_EQL" (in EXE instead of DLL)
Q_INVOKABLE QEasingCurve* easingCurve();
};
QT_END_NAMESPACE
#endif
#ifndef MAIN_H
#define MAIN_H
#include <QtWidgets>
#include "eql_fun.h"
QT_BEGIN_NAMESPACE
class Qt_EQL_Application : public QApplication {
Q_OBJECT
public:
Qt_EQL_Application(int argc, char** argv) : QApplication(argc, argv) {}
// simple variant of "Qt_EQL" (in EXE instead of DLL)
Q_INVOKABLE QEasingCurve* easingCurve();
};
QT_END_NAMESPACE
#endif

View file

@ -1,14 +1,14 @@
QT += widgets
TEMPLATE = app
CONFIG += no_keywords release
INCLUDEPATH += ../../../../src
LIBS += -lecl -L. -lstatic -L../../../.. -leql5
TARGET = palindrome
DESTDIR = ./
OBJECTS_DIR = ./tmp/
MOC_DIR = ./tmp/
include(../../../../src/windows.pri)
HEADERS += main.h
SOURCES += main.cpp
QT += widgets
TEMPLATE = app
CONFIG += no_keywords release
INCLUDEPATH += ../../../../src
LIBS += -lecl -L. -lstatic -L../../../.. -leql5
TARGET = palindrome
DESTDIR = ./
OBJECTS_DIR = ./tmp/
MOC_DIR = ./tmp/
include(../../../../src/windows.pri)
HEADERS += main.h
SOURCES += main.cpp

View file

@ -156,7 +156,7 @@
(change-values))
(defun save ()
(let ((name (|getSaveFileName.QFileDialog| nil "" *file* "Images (*.png *.jpg)")))
(let ((name (|getSaveFileName.QFileDialog| *main* "" *file* "Images (*.png *.jpg)")))
(unless (x:empty-string name)
(if (pathname-type name)
(let ((*saving* t))

File diff suppressed because it is too large Load diff

View file

@ -1,321 +1,321 @@
// copyright (c) Polos Ruetz
#ifndef ECL_FUN_H
#define ECL_FUN_H
#include "eql_global.h"
#include <ecl/ecl.h>
#include <QList>
#include <QUiLoader>
#include <QByteArray>
#include <QPair>
#include <QVariant>
QT_BEGIN_NAMESPACE
#define QSLOT(x) "1"#x
#define QSIGNAL(x) "2"#x
#define META_TYPE(constant, type) \
static const int constant = qRegisterMetaType< type >(#type);
#define DEFUN(name, c_name, num_args) \
cl_def_c_function(c_string_to_object((char*)name), (cl_objectfn_fixed)c_name, num_args);
#define STRING(s) make_constant_base_string((char*)s)
#define STRING_COPY(s) (s ? make_base_string_copy((char*)s) : Cnil)
#define PRINT(x) cl_print(1, x)
#define TERPRI() cl_terpri(0)
#define STATIC_SYMBOL(var, name) \
static cl_object var = cl_intern(1, make_constant_base_string((char*)name));
#define STATIC_SYMBOL_PKG(var, name, pkg) \
static cl_object var = cl_intern(2, \
make_constant_base_string((char*)name), \
cl_find_package(make_constant_base_string((char*)pkg)));
#define LEN(x) fixint(cl_length(x))
#define LIST1(a1) \
CONS(a1, Cnil)
#define LIST2(a1, a2) \
CONS(a1, LIST1(a2))
#define LIST3(a1, a2, a3) \
CONS(a1, LIST2(a2, a3))
#define LIST4(a1, a2, a3, a4) \
CONS(a1, LIST3(a2, a3, a4))
#define LIST5(a1, a2, a3, a4, a5) \
CONS(a1, LIST4(a2, a3, a4, a5))
#define LIST6(a1, a2, a3, a4, a5, a6) \
CONS(a1, LIST5(a2, a3, a4, a5, a6))
#define LIST7(a1, a2, a3, a4, a5, a6, a7) \
CONS(a1, LIST6(a2, a3, a4, a5, a6, a7))
#define LIST8(a1, a2, a3, a4, a5, a6, a7, a8) \
CONS(a1, LIST7(a2, a3, a4, a5, a6, a7, a8))
#define LIST9(a1, a2, a3, a4, a5, a6, a7, a8, a9) \
CONS(a1, LIST8(a2, a3, a4, a5, a6, a7, a8, a9))
#define LIST10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
CONS(a1, LIST9(a2, a3, a4, a5, a6, a7, a8, a9, a10))
#define TO_QT_TYPE(name) \
static name to##name(cl_object x) { \
if(LISTP(x)) { \
return name(toInt(cl_first(x)), toInt(cl_second(x))); } \
return name(); }
#define TO_QT_TYPEF(name) \
TO_QT_TYPE(name) \
static name##F to##name##F(cl_object x) { \
if(LISTP(x)) { \
return name##F(toReal(cl_first(x)), toReal(cl_second(x))); } \
return name##F(); }
#define TO_QT_TYPE2(name) \
static name to##name(cl_object x) { \
if(LISTP(x)) { \
return name(toInt(cl_first(x)), toInt(cl_second(x)), toInt(cl_third(x)), toInt(cl_fourth(x))); } \
return name(); }
#define TO_QT_TYPEF2(name) \
TO_QT_TYPE2(name) \
static name##F to##name##F(cl_object x) { \
if(LISTP(x)) { \
return name##F(toReal(cl_first(x)), toReal(cl_second(x)), toReal(cl_third(x)), toReal(cl_fourth(x))); } \
return name##F(); }
#define TO_QT_TYPE_PTR(cap_name, name) \
static cap_name* to##cap_name##Pointer(cl_object x) { \
cap_name* p = 0; \
QtObject o = toQtObject(x); \
if(#cap_name == o.className()) { \
p = (cap_name*)o.pointer; } \
return p; } \
static cl_object from_##name(const cap_name& x) { \
cl_object l_ret = Cnil; \
if(EQL::return_value_p) { \
l_ret = qt_object_from_name(#cap_name, new cap_name(x), 0, true); } \
else { \
l_ret = qt_object_from_name(#cap_name, (void*)&x); } \
return l_ret; }
#define TO_QT_TYPE_PTR2(cap_name, name) \
TO_QT_TYPE_PTR(cap_name, name) \
static cap_name to##cap_name(cl_object l_x) { \
cap_name* x = to##cap_name##Pointer(l_x); \
if(x) { \
return *x; } \
return cap_name(); }
#define TO_CL_TYPE(cap_name, name, x1, x2) \
static cl_object from_##name(const cap_name& q) { \
cl_object l_ret = LIST2(MAKE_FIXNUM(q.x1()), MAKE_FIXNUM(q.x2())); \
return l_ret; }
#define TO_CL_TYPEF(cap_name, name, x1, x2) \
TO_CL_TYPE(cap_name, name, x1, x2) \
static cl_object from_##name##f(const cap_name##F& q) { \
cl_object l_ret = LIST2(ecl_make_doublefloat(q.x1()), ecl_make_doublefloat(q.x2())); \
return l_ret; }
#define TO_CL_TYPE2(cap_name, name, x1, x2, x3, x4) \
static cl_object from_##name(const cap_name& q) { \
cl_object l_ret = LIST4(MAKE_FIXNUM(q.x1()), MAKE_FIXNUM(q.x2()), MAKE_FIXNUM(q.x3()), MAKE_FIXNUM(q.x4())); \
return l_ret; }
#define TO_CL_TYPEF2(cap_name, name, x1, x2, x3, x4) \
TO_CL_TYPE2(cap_name, name, x1, x2, x3, x4) \
static cl_object from_##name##f(const cap_name##F& q) { \
cl_object l_ret = LIST4(ecl_make_doublefloat(q.x1()), ecl_make_doublefloat(q.x2()), ecl_make_doublefloat(q.x3()), ecl_make_doublefloat(q.x4())); \
return l_ret; }
#define TO_CL_LIST_PTR(cap_type, type) \
static cl_object from_##type##list(const QList<cap_type*>& l) { \
cl_object l_list = Cnil; \
Q_FOREACH(cap_type* x, l) { \
l_list = CONS(qt_object_from_name(#cap_type, x), l_list); } \
l_list = cl_nreverse(l_list); \
return l_list; }
#define TO_CL_LIST_VAL(cap_type, type) \
static cl_object from_##type##list(const QList<cap_type>& l) { \
cl_object l_list = Cnil; \
Q_FOREACH(cap_type x, l) { \
l_list = CONS(from_##type(x), l_list); } \
l_list = cl_nreverse(l_list); \
return l_list; }
#define TO_CL_LIST_VAL2(cap_type, fun) \
static cl_object from_##type##list(const QList<cap_type*>& l) { \
cl_object l_list = Cnil; \
Q_FOREACH(cap_type* x, l) { \
l_list = CONS(fun(*x), l_list); } \
l_list = cl_nreverse(l_list); \
return l_list; }
#define TO_QT_LIST_PTR(type) \
static QList<type*> to##type##List(cl_object l_list) { \
QList<type*> l; \
if(LISTP(l_list)) { \
cl_object l_el = l_list; \
while(l_el != Cnil) { \
l << (type*)toQtObject(cl_car(l_el)).pointer; \
l_el = cl_cdr(l_el); }} \
return l; }
#define TO_QT_LIST_VAL(type) \
static QList<type> to##type##List(cl_object l_list) { \
QList<type> l; \
if(LISTP(l_list)) { \
cl_object l_el = l_list; \
while(l_el != Cnil) { \
l << to##type(cl_car(l_el)); \
l_el = cl_cdr(l_el); }} \
return l; }
#define TO_QT_LIST_VAL2(type, fun) \
static QList<type> to##fun##List(cl_object l_list) { \
QList<type> l; \
if(LISTP(l_list)) { \
cl_object l_el = l_list; \
while(l_el != Cnil) { \
l << to##fun(cl_car(l_el)); \
l_el = cl_cdr(l_el); }} \
return l; }
#define TO_QT_VECTOR_VAL(type) \
static QVector<type> to##type##Vector(cl_object l_v) { \
QVector<type> v; \
if(cl_simple_vector_p(l_v) == Ct) { \
for(int i = 0; i < LEN(l_v); ++i) { \
v.append(to##type(cl_svref(l_v, MAKE_FIXNUM(i)))); }} \
return v; }
#define TO_QT_VECTOR_VAL2(type, fun) \
static QVector<type> to##type##Vector(cl_object l_v) { \
QVector<type> v; \
if(cl_simple_vector_p(l_v) == Ct) { \
for(int i = 0; i < LEN(l_v); ++i) { \
v.append(to##fun(cl_svref(l_v, MAKE_FIXNUM(i)))); }} \
return v; }
#define TO_CL_VECTOR_VAL(cap_type, type) \
static cl_object from_##type##vector(const QVector<cap_type>& v) { \
cl_object l_vec = make_vector(); \
for(int i = 0; i < v.size(); ++i) { \
cl_vector_push_extend(2, from_##type(v.at(i)), l_vec); } \
return l_vec; }
#define TO_CL_VECTOR_VAL2(cap_type, type, fun) \
static cl_object from_##type##vector(const QVector<cap_type>& v) { \
cl_object l_vec = make_vector(); \
for(int i = 0; i < v.size(); ++i) { \
cl_vector_push_extend(2, fun(v.at(i)), l_vec); } \
return l_vec; }
typedef QPair<QByteArray, void*> MetaArg;
typedef QList<MetaArg> MetaArgList;
typedef QListIterator<MetaArg> MetaArgIterator;
typedef QList<QByteArray> StrList;
typedef QList<int> IntList;
class QByteArray;
class QObject;
class QEvent;
cl_object error_msg2 (cl_object, cl_object);
cl_object make_qimage_dangerous (cl_object, cl_object, cl_object, cl_object, cl_object);
cl_object no_qexec ();
cl_object qadd_event_filter (cl_object, cl_object, cl_object);
cl_object qapropos2 (cl_object, cl_object, cl_object);
cl_object qapp ();
cl_object qcall_default ();
cl_object qclear_event_filters ();
cl_object qconnect2 (cl_object, cl_object, cl_object, cl_object);
cl_object qcopy (cl_object);
cl_object qdelete2 (cl_object, cl_object);
cl_object qdisconnect2 (cl_object, cl_object, cl_object, cl_object);
cl_object qenums2 (cl_object, cl_object);
cl_object qescape (cl_object);
cl_object qexec2 (cl_object);
cl_object qexit ();
cl_object qfind_child (cl_object, cl_object);
cl_object qfind_children2 (cl_object, cl_object, cl_object);
cl_object qfrom_utf8 (cl_object);
cl_object qid (cl_object);
cl_object qinvoke_method2 (cl_object, cl_object, cl_object, cl_object);
cl_object qload_cpp (cl_object, cl_object);
cl_object qload_ui (cl_object);
cl_object qlocal8bit (cl_object);
cl_object qmeta_enums ();
cl_object qnew_instance2 (cl_object, cl_object);
cl_object qobject_names2 (cl_object);
cl_object qok ();
cl_object qoverride (cl_object, cl_object, cl_object);
cl_object qprocess_events ();
cl_object qproperty (cl_object, cl_object);
cl_object qremove_event_filter (cl_object);
cl_object qrequire2 (cl_object, cl_object);
cl_object qrun_in_gui_thread2 (cl_object, cl_object);
cl_object qsender ();
cl_object qset_gc (cl_object);
cl_object qset_property (cl_object, cl_object, cl_object);
cl_object qsingle_shot2 (cl_object, cl_object);
cl_object qstatic_meta_object (cl_object);
cl_object qsuper_class_name (cl_object);
cl_object qtranslate (cl_object, cl_object, cl_object);
cl_object qt_object_name (cl_object);
cl_object qt_object_x (cl_object);
cl_object qui_class2 (cl_object, cl_object);
cl_object qui_names (cl_object);
cl_object qutf8 (cl_object);
cl_object qvariant_equal2 (cl_object, cl_object);
cl_object qversion ();
struct EQL_EXPORT QtObject {
QtObject() : pointer(0), unique(0), id(0) {}
void* pointer;
uint unique;
int id;
bool isQObject() const { return (id > 0); }
bool isStatic() const { return !pointer; }
QByteArray className() const;
static QByteArray idToClassName(int);
};
// for Qt_EQL
struct eql_pointer {
void* pointer;
int id;
eql_pointer() : pointer(0), id(0) {}
eql_pointer(void* v, int i) : pointer(v), id(i) {}
};
struct QtMetaObject : private QObject {
// commonly used trick to access staticQtMetaObject
static const QMetaObject* get() { return &static_cast<QtMetaObject*>(0)->staticQtMetaObject; }
};
void iniCLFunctions();
void callConnectFun(void*, const QList<QByteArray>&, void**);
bool callEventFun(void*, QObject*, QEvent*);
void error_msg(const char*, cl_object);
QVariant toQVariant(cl_object, const char*, int = -1);
cl_object to_lisp_arg(const MetaArg&);
EQL_EXPORT QVariant callOverrideFun(void*, int, const void**, quint64);
EQL_EXPORT cl_object qt_object_from_name(const QByteArray&, void*, uint = 0, bool = false);
EQL_EXPORT QtObject toQtObject(cl_object, cl_object = Cnil, bool* = 0, bool = false);
QT_END_NAMESPACE
Q_DECLARE_METATYPE(eql_pointer)
#endif
// copyright (c) Polos Ruetz
#ifndef ECL_FUN_H
#define ECL_FUN_H
#include "eql_global.h"
#include <ecl/ecl.h>
#include <QList>
#include <QUiLoader>
#include <QByteArray>
#include <QPair>
#include <QVariant>
QT_BEGIN_NAMESPACE
#define QSLOT(x) "1"#x
#define QSIGNAL(x) "2"#x
#define META_TYPE(constant, type) \
static const int constant = qRegisterMetaType< type >(#type);
#define DEFUN(name, c_name, num_args) \
cl_def_c_function(c_string_to_object((char*)name), (cl_objectfn_fixed)c_name, num_args);
#define STRING(s) make_constant_base_string((char*)s)
#define STRING_COPY(s) (s ? make_base_string_copy((char*)s) : Cnil)
#define PRINT(x) cl_print(1, x)
#define TERPRI() cl_terpri(0)
#define STATIC_SYMBOL(var, name) \
static cl_object var = cl_intern(1, make_constant_base_string((char*)name));
#define STATIC_SYMBOL_PKG(var, name, pkg) \
static cl_object var = cl_intern(2, \
make_constant_base_string((char*)name), \
cl_find_package(make_constant_base_string((char*)pkg)));
#define LEN(x) fixint(cl_length(x))
#define LIST1(a1) \
CONS(a1, Cnil)
#define LIST2(a1, a2) \
CONS(a1, LIST1(a2))
#define LIST3(a1, a2, a3) \
CONS(a1, LIST2(a2, a3))
#define LIST4(a1, a2, a3, a4) \
CONS(a1, LIST3(a2, a3, a4))
#define LIST5(a1, a2, a3, a4, a5) \
CONS(a1, LIST4(a2, a3, a4, a5))
#define LIST6(a1, a2, a3, a4, a5, a6) \
CONS(a1, LIST5(a2, a3, a4, a5, a6))
#define LIST7(a1, a2, a3, a4, a5, a6, a7) \
CONS(a1, LIST6(a2, a3, a4, a5, a6, a7))
#define LIST8(a1, a2, a3, a4, a5, a6, a7, a8) \
CONS(a1, LIST7(a2, a3, a4, a5, a6, a7, a8))
#define LIST9(a1, a2, a3, a4, a5, a6, a7, a8, a9) \
CONS(a1, LIST8(a2, a3, a4, a5, a6, a7, a8, a9))
#define LIST10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
CONS(a1, LIST9(a2, a3, a4, a5, a6, a7, a8, a9, a10))
#define TO_QT_TYPE(name) \
static name to##name(cl_object x) { \
if(LISTP(x)) { \
return name(toInt(cl_first(x)), toInt(cl_second(x))); } \
return name(); }
#define TO_QT_TYPEF(name) \
TO_QT_TYPE(name) \
static name##F to##name##F(cl_object x) { \
if(LISTP(x)) { \
return name##F(toReal(cl_first(x)), toReal(cl_second(x))); } \
return name##F(); }
#define TO_QT_TYPE2(name) \
static name to##name(cl_object x) { \
if(LISTP(x)) { \
return name(toInt(cl_first(x)), toInt(cl_second(x)), toInt(cl_third(x)), toInt(cl_fourth(x))); } \
return name(); }
#define TO_QT_TYPEF2(name) \
TO_QT_TYPE2(name) \
static name##F to##name##F(cl_object x) { \
if(LISTP(x)) { \
return name##F(toReal(cl_first(x)), toReal(cl_second(x)), toReal(cl_third(x)), toReal(cl_fourth(x))); } \
return name##F(); }
#define TO_QT_TYPE_PTR(cap_name, name) \
static cap_name* to##cap_name##Pointer(cl_object x) { \
cap_name* p = 0; \
QtObject o = toQtObject(x); \
if(#cap_name == o.className()) { \
p = (cap_name*)o.pointer; } \
return p; } \
static cl_object from_##name(const cap_name& x) { \
cl_object l_ret = Cnil; \
if(EQL::return_value_p) { \
l_ret = qt_object_from_name(#cap_name, new cap_name(x), 0, true); } \
else { \
l_ret = qt_object_from_name(#cap_name, (void*)&x); } \
return l_ret; }
#define TO_QT_TYPE_PTR2(cap_name, name) \
TO_QT_TYPE_PTR(cap_name, name) \
static cap_name to##cap_name(cl_object l_x) { \
cap_name* x = to##cap_name##Pointer(l_x); \
if(x) { \
return *x; } \
return cap_name(); }
#define TO_CL_TYPE(cap_name, name, x1, x2) \
static cl_object from_##name(const cap_name& q) { \
cl_object l_ret = LIST2(MAKE_FIXNUM(q.x1()), MAKE_FIXNUM(q.x2())); \
return l_ret; }
#define TO_CL_TYPEF(cap_name, name, x1, x2) \
TO_CL_TYPE(cap_name, name, x1, x2) \
static cl_object from_##name##f(const cap_name##F& q) { \
cl_object l_ret = LIST2(ecl_make_doublefloat(q.x1()), ecl_make_doublefloat(q.x2())); \
return l_ret; }
#define TO_CL_TYPE2(cap_name, name, x1, x2, x3, x4) \
static cl_object from_##name(const cap_name& q) { \
cl_object l_ret = LIST4(MAKE_FIXNUM(q.x1()), MAKE_FIXNUM(q.x2()), MAKE_FIXNUM(q.x3()), MAKE_FIXNUM(q.x4())); \
return l_ret; }
#define TO_CL_TYPEF2(cap_name, name, x1, x2, x3, x4) \
TO_CL_TYPE2(cap_name, name, x1, x2, x3, x4) \
static cl_object from_##name##f(const cap_name##F& q) { \
cl_object l_ret = LIST4(ecl_make_doublefloat(q.x1()), ecl_make_doublefloat(q.x2()), ecl_make_doublefloat(q.x3()), ecl_make_doublefloat(q.x4())); \
return l_ret; }
#define TO_CL_LIST_PTR(cap_type, type) \
static cl_object from_##type##list(const QList<cap_type*>& l) { \
cl_object l_list = Cnil; \
Q_FOREACH(cap_type* x, l) { \
l_list = CONS(qt_object_from_name(#cap_type, x), l_list); } \
l_list = cl_nreverse(l_list); \
return l_list; }
#define TO_CL_LIST_VAL(cap_type, type) \
static cl_object from_##type##list(const QList<cap_type>& l) { \
cl_object l_list = Cnil; \
Q_FOREACH(cap_type x, l) { \
l_list = CONS(from_##type(x), l_list); } \
l_list = cl_nreverse(l_list); \
return l_list; }
#define TO_CL_LIST_VAL2(cap_type, fun) \
static cl_object from_##type##list(const QList<cap_type*>& l) { \
cl_object l_list = Cnil; \
Q_FOREACH(cap_type* x, l) { \
l_list = CONS(fun(*x), l_list); } \
l_list = cl_nreverse(l_list); \
return l_list; }
#define TO_QT_LIST_PTR(type) \
static QList<type*> to##type##List(cl_object l_list) { \
QList<type*> l; \
if(LISTP(l_list)) { \
cl_object l_el = l_list; \
while(l_el != Cnil) { \
l << (type*)toQtObject(cl_car(l_el)).pointer; \
l_el = cl_cdr(l_el); }} \
return l; }
#define TO_QT_LIST_VAL(type) \
static QList<type> to##type##List(cl_object l_list) { \
QList<type> l; \
if(LISTP(l_list)) { \
cl_object l_el = l_list; \
while(l_el != Cnil) { \
l << to##type(cl_car(l_el)); \
l_el = cl_cdr(l_el); }} \
return l; }
#define TO_QT_LIST_VAL2(type, fun) \
static QList<type> to##fun##List(cl_object l_list) { \
QList<type> l; \
if(LISTP(l_list)) { \
cl_object l_el = l_list; \
while(l_el != Cnil) { \
l << to##fun(cl_car(l_el)); \
l_el = cl_cdr(l_el); }} \
return l; }
#define TO_QT_VECTOR_VAL(type) \
static QVector<type> to##type##Vector(cl_object l_v) { \
QVector<type> v; \
if(cl_simple_vector_p(l_v) == Ct) { \
for(int i = 0; i < LEN(l_v); ++i) { \
v.append(to##type(cl_svref(l_v, MAKE_FIXNUM(i)))); }} \
return v; }
#define TO_QT_VECTOR_VAL2(type, fun) \
static QVector<type> to##type##Vector(cl_object l_v) { \
QVector<type> v; \
if(cl_simple_vector_p(l_v) == Ct) { \
for(int i = 0; i < LEN(l_v); ++i) { \
v.append(to##fun(cl_svref(l_v, MAKE_FIXNUM(i)))); }} \
return v; }
#define TO_CL_VECTOR_VAL(cap_type, type) \
static cl_object from_##type##vector(const QVector<cap_type>& v) { \
cl_object l_vec = make_vector(); \
for(int i = 0; i < v.size(); ++i) { \
cl_vector_push_extend(2, from_##type(v.at(i)), l_vec); } \
return l_vec; }
#define TO_CL_VECTOR_VAL2(cap_type, type, fun) \
static cl_object from_##type##vector(const QVector<cap_type>& v) { \
cl_object l_vec = make_vector(); \
for(int i = 0; i < v.size(); ++i) { \
cl_vector_push_extend(2, fun(v.at(i)), l_vec); } \
return l_vec; }
typedef QPair<QByteArray, void*> MetaArg;
typedef QList<MetaArg> MetaArgList;
typedef QListIterator<MetaArg> MetaArgIterator;
typedef QList<QByteArray> StrList;
typedef QList<int> IntList;
class QByteArray;
class QObject;
class QEvent;
cl_object error_msg2 (cl_object, cl_object);
cl_object make_qimage_dangerous (cl_object, cl_object, cl_object, cl_object, cl_object);
cl_object no_qexec ();
cl_object qadd_event_filter (cl_object, cl_object, cl_object);
cl_object qapropos2 (cl_object, cl_object, cl_object);
cl_object qapp ();
cl_object qcall_default ();
cl_object qclear_event_filters ();
cl_object qconnect2 (cl_object, cl_object, cl_object, cl_object);
cl_object qcopy (cl_object);
cl_object qdelete2 (cl_object, cl_object);
cl_object qdisconnect2 (cl_object, cl_object, cl_object, cl_object);
cl_object qenums2 (cl_object, cl_object);
cl_object qescape (cl_object);
cl_object qexec2 (cl_object);
cl_object qexit ();
cl_object qfind_child (cl_object, cl_object);
cl_object qfind_children2 (cl_object, cl_object, cl_object);
cl_object qfrom_utf8 (cl_object);
cl_object qid (cl_object);
cl_object qinvoke_method2 (cl_object, cl_object, cl_object, cl_object);
cl_object qload_cpp (cl_object, cl_object);
cl_object qload_ui (cl_object);
cl_object qlocal8bit (cl_object);
cl_object qmeta_enums ();
cl_object qnew_instance2 (cl_object, cl_object);
cl_object qobject_names2 (cl_object);
cl_object qok ();
cl_object qoverride (cl_object, cl_object, cl_object);
cl_object qprocess_events ();
cl_object qproperty (cl_object, cl_object);
cl_object qremove_event_filter (cl_object);
cl_object qrequire2 (cl_object, cl_object);
cl_object qrun_in_gui_thread2 (cl_object, cl_object);
cl_object qsender ();
cl_object qset_gc (cl_object);
cl_object qset_property (cl_object, cl_object, cl_object);
cl_object qsingle_shot2 (cl_object, cl_object);
cl_object qstatic_meta_object (cl_object);
cl_object qsuper_class_name (cl_object);
cl_object qtranslate (cl_object, cl_object, cl_object);
cl_object qt_object_name (cl_object);
cl_object qt_object_x (cl_object);
cl_object qui_class2 (cl_object, cl_object);
cl_object qui_names (cl_object);
cl_object qutf8 (cl_object);
cl_object qvariant_equal2 (cl_object, cl_object);
cl_object qversion ();
struct EQL_EXPORT QtObject {
QtObject() : pointer(0), unique(0), id(0) {}
void* pointer;
uint unique;
int id;
bool isQObject() const { return (id > 0); }
bool isStatic() const { return !pointer; }
QByteArray className() const;
static QByteArray idToClassName(int);
};
// for Qt_EQL
struct eql_pointer {
void* pointer;
int id;
eql_pointer() : pointer(0), id(0) {}
eql_pointer(void* v, int i) : pointer(v), id(i) {}
};
struct QtMetaObject : private QObject {
// commonly used trick to access staticQtMetaObject
static const QMetaObject* get() { return &static_cast<QtMetaObject*>(0)->staticQtMetaObject; }
};
void iniCLFunctions();
void callConnectFun(void*, const QList<QByteArray>&, void**);
bool callEventFun(void*, QObject*, QEvent*);
void error_msg(const char*, cl_object);
QVariant toQVariant(cl_object, const char*, int = -1);
cl_object to_lisp_arg(const MetaArg&);
EQL_EXPORT QVariant callOverrideFun(void*, int, const void**, quint64);
EQL_EXPORT cl_object qt_object_from_name(const QByteArray&, void*, uint = 0, bool = false);
EQL_EXPORT QtObject toQtObject(cl_object, cl_object = Cnil, bool* = 0, bool = false);
QT_END_NAMESPACE
Q_DECLARE_METATYPE(eql_pointer)
#endif

View file

@ -1,177 +1,177 @@
// copyright (c) Polos Ruetz
#include "eql.h"
#include "ecl_fun.h"
#include "gen/_lobjects.h"
#include <QApplication>
#include <QTimer>
#include <QStringList>
const char EQL::version[] = "16.12.3"; // Dec 2016
extern "C" void ini_EQL(cl_object);
static const char* _argv_[] = {"EQL5"};
EQL::EQL() : QObject() {
if(!cl_booted) {
cl_boot(1, (char**)_argv_); }
iniCLFunctions();
LObjects::ini(this);
read_VV(OBJNULL, ini_EQL); } // see "src/make-eql-lib.lisp"
void EQL::ini(char** argv) {
cl_booted = true;
cl_boot(1, argv); }
void EQL::eval(const char* lisp_code) {
CL_CATCH_ALL_BEGIN(ecl_process_env()) {
si_safe_eval(2, ecl_read_from_cstring((char*)lisp_code), Cnil); }
CL_CATCH_ALL_END; }
QString EQL::home() {
static QString path;
if(path.isEmpty()) {
path = QApplication::applicationDirPath();
#ifdef Q_OS_DARWIN
path.truncate(path.lastIndexOf('/', path.indexOf(".app")));
#endif
path.append('/'); }
return path; }
void EQL::exec(const QStringList& args) {
cl_object s_qtpl = cl_intern(1, make_constant_base_string("*QTPL*"));
bool exec_with_simple_restart = false;
QStringList arguments(args);
eval("(in-package :eql-user)");
eval(QString("(eql::set-home \"%1\")").arg(home()).toLatin1().constData());
QStringList forms;
// .eclrc
if(arguments.contains("-norc")) {
arguments.removeAll("-norc"); }
else {
eval("(x:when-it (probe-file \"~/.eclrc\") (load x:it))"); }
// Slime
int i_swank = arguments.indexOf(QRegExp("*start-swank*.lisp", Qt::CaseInsensitive, QRegExp::Wildcard));
if(arguments.contains("-slime") || (i_swank != -1)) {
arguments.removeAll("-slime");
QString swankFile;
if(i_swank != -1) {
swankFile = arguments.at(i_swank);
arguments.removeAt(i_swank); }
QApplication::setQuitOnLastWindowClosed(false);
forms << "(unless eql:*slime-mode*" // see mode :REPL-HOOK in "slime/eql-start-swank.lisp"
" (setf eql:*slime-mode* t))"
"(setf eql:*qtpl* nil)";
if(arguments.length() == 2) {
QString fileName(QDir::fromNativeSeparators(arguments.at(1)));
forms << QString("(load \"%1\")").arg(fileName);
arguments.removeAt(1); }
if(!swankFile.isEmpty()) {
arguments << swankFile; }
exec_with_simple_restart = true; }
// -qtpl
else if(arguments.contains("-qtpl") || (cl_symbol_value(s_qtpl) == Ct)) {
arguments.removeAll("-qtpl");
ecl_setq(ecl_process_env(), s_qtpl, Ct);
QApplication::setQuitOnLastWindowClosed(false);
forms << "(when (directory (in-home \"src/lisp/ecl-readline.fas*\"))"
" (load (in-home \"src/lisp/ecl-readline\")))"
<< "(qsingle-shot 500 'eql::start-read-thread)";
exec_with_simple_restart = true; }
// -qgui
if(arguments.contains("-qgui")) {
arguments.removeAll("-qgui");
forms << "(qgui)"; }
// -quic
if(arguments.contains("-quic")) {
arguments.removeAll("-quic");
bool maximized = false;
if(arguments.contains(":maximized")) {
arguments.removeAll(":maximized");
maximized = true; }
if(arguments.length() >= 2) {
QString uiFile(QDir::fromNativeSeparators(arguments.at(1)));
int sep = uiFile.lastIndexOf('/') + 1;
forms << QString("(ext:run-program \"uic\" (list \"-o\" \"ui.h\" \"%1\"))").arg(uiFile)
<< QString("(eql:quic \"ui.h\" \"%1ui-%2.lisp\" %3 %4)")
.arg(uiFile.left(sep))
.arg(uiFile.mid(sep, uiFile.length() - sep - 3))
.arg((arguments.length() == 2) ? ":ui" : arguments.at(2))
.arg(maximized ? ":maximized" : "")
<< QString("(delete-file \"ui.h\")")
<< QString("(eql:qq)"); }
else {
qDebug() << "\nPlease pass a file.ui (Qt Designer).\n";
exit(-1); }}
else {
if(arguments.length() == 1) {
// simple top-level
if(forms.isEmpty()) {
qexec = false;
forms << "(si:top-level)"; }}
else {
// load file
QString fileName(QDir::fromNativeSeparators(arguments.at(1)));
forms.prepend(QString("(load \"%1\")").arg(fileName)); }}
// eval
QString code;
if(forms.length() == 1) {
code = forms.first(); }
else {
code = "(progn " + forms.join(" ") + ")"; }
eval(code.toLatin1().constData());
// RESTART for Qt event loop
if(exec_with_simple_restart) {
qexec = false;
eval("(eql::exec-with-simple-restart)"); }}
void EQL::exec(lisp_ini ini, const QByteArray& expression, const QByteArray& package) {
// see my_app example
eval(QString("(eql::set-home \"%1\")").arg(home()).toLatin1().constData());
read_VV(OBJNULL, ini);
eval(QString("(in-package :%1)").arg(QString(package)).toLatin1().constData());
eval(expression.constData()); }
enum { NotFound = -1 };
void EQL::exec(QWidget* widget, const QString& lispFile, const QString& slimeHookFile) {
// see Qt_EQL example
bool exec_with_simple_restart = false;
QStringList forms;
eval("(in-package :eql)");
forms << QString("(set-home \"%1\")").arg(home())
<< QString("(defvar *qt-main* (qt-object %1 0 (qid \"%2\")))")
.arg((quintptr)widget)
.arg(QString(LObjects::vanillaQtSuperClassName(widget->metaObject())))
<< QString("(export '*qt-main*)")
<< QString("(in-package :eql-user)")
<< QString("(load \"%1\")").arg(lispFile);
if(!slimeHookFile.isEmpty()) {
QString startSwankFile(QCoreApplication::arguments().last());
if(NotFound == startSwankFile.indexOf(QRegExp("*start-swank*.lisp", Qt::CaseInsensitive, QRegExp::Wildcard))) {
qDebug() << "\nPlease pass the pathname for \"eql-start-swank.lisp\".\n";
exit(-1); }
QApplication::setQuitOnLastWindowClosed(false);
forms << QString("(load \"%1\")").arg(startSwankFile)
<< QString("(setf eql::*slime-hook-file* \"%1\")").arg(slimeHookFile)
<< QString("(setf eql:*slime-mode* t"
" eql:*qtpl* nil)");
exec_with_simple_restart = true; }
eval(QString("(progn " + forms.join(" ") + ")").toLatin1().constData());
if(exec_with_simple_restart) {
eval("(eql::exec-with-simple-restart)"); }}
void EQL::runInGuiThread(void* function_or_closure) {
const cl_env_ptr l_env = ecl_process_env();
CL_CATCH_ALL_BEGIN(l_env) {
CL_UNWIND_PROTECT_BEGIN(l_env) {
cl_funcall(1, (cl_object)function_or_closure); }
CL_UNWIND_PROTECT_EXIT {}
CL_UNWIND_PROTECT_END; }
CL_CATCH_ALL_END; }
bool EQL::cl_booted = false;
bool EQL::return_value_p = false;
bool EQL::qexec = true;
QEventLoop* EQL::eventLoop = 0;
// copyright (c) Polos Ruetz
#include "eql.h"
#include "ecl_fun.h"
#include "gen/_lobjects.h"
#include <QApplication>
#include <QTimer>
#include <QStringList>
const char EQL::version[] = "16.12.3"; // Dec 2016
extern "C" void ini_EQL(cl_object);
static const char* _argv_[] = {"EQL5"};
EQL::EQL() : QObject() {
if(!cl_booted) {
cl_boot(1, (char**)_argv_); }
iniCLFunctions();
LObjects::ini(this);
read_VV(OBJNULL, ini_EQL); } // see "src/make-eql-lib.lisp"
void EQL::ini(char** argv) {
cl_booted = true;
cl_boot(1, argv); }
void EQL::eval(const char* lisp_code) {
CL_CATCH_ALL_BEGIN(ecl_process_env()) {
si_safe_eval(2, ecl_read_from_cstring((char*)lisp_code), Cnil); }
CL_CATCH_ALL_END; }
QString EQL::home() {
static QString path;
if(path.isEmpty()) {
path = QApplication::applicationDirPath();
#ifdef Q_OS_DARWIN
path.truncate(path.lastIndexOf('/', path.indexOf(".app")));
#endif
path.append('/'); }
return path; }
void EQL::exec(const QStringList& args) {
cl_object s_qtpl = cl_intern(1, make_constant_base_string("*QTPL*"));
bool exec_with_simple_restart = false;
QStringList arguments(args);
eval("(in-package :eql-user)");
eval(QString("(eql::set-home \"%1\")").arg(home()).toLatin1().constData());
QStringList forms;
// .eclrc
if(arguments.contains("-norc")) {
arguments.removeAll("-norc"); }
else {
eval("(x:when-it (probe-file \"~/.eclrc\") (load x:it))"); }
// Slime
int i_swank = arguments.indexOf(QRegExp("*start-swank*.lisp", Qt::CaseInsensitive, QRegExp::Wildcard));
if(arguments.contains("-slime") || (i_swank != -1)) {
arguments.removeAll("-slime");
QString swankFile;
if(i_swank != -1) {
swankFile = arguments.at(i_swank);
arguments.removeAt(i_swank); }
QApplication::setQuitOnLastWindowClosed(false);
forms << "(unless eql:*slime-mode*" // see mode :REPL-HOOK in "slime/eql-start-swank.lisp"
" (setf eql:*slime-mode* t))"
"(setf eql:*qtpl* nil)";
if(arguments.length() == 2) {
QString fileName(QDir::fromNativeSeparators(arguments.at(1)));
forms << QString("(load \"%1\")").arg(fileName);
arguments.removeAt(1); }
if(!swankFile.isEmpty()) {
arguments << swankFile; }
exec_with_simple_restart = true; }
// -qtpl
else if(arguments.contains("-qtpl") || (cl_symbol_value(s_qtpl) == Ct)) {
arguments.removeAll("-qtpl");
ecl_setq(ecl_process_env(), s_qtpl, Ct);
QApplication::setQuitOnLastWindowClosed(false);
forms << "(when (directory (in-home \"src/lisp/ecl-readline.fas*\"))"
" (load (in-home \"src/lisp/ecl-readline\")))"
<< "(qsingle-shot 500 'eql::start-read-thread)";
exec_with_simple_restart = true; }
// -qgui
if(arguments.contains("-qgui")) {
arguments.removeAll("-qgui");
forms << "(qgui)"; }
// -quic
if(arguments.contains("-quic")) {
arguments.removeAll("-quic");
bool maximized = false;
if(arguments.contains(":maximized")) {
arguments.removeAll(":maximized");
maximized = true; }
if(arguments.length() >= 2) {
QString uiFile(QDir::fromNativeSeparators(arguments.at(1)));
int sep = uiFile.lastIndexOf('/') + 1;
forms << QString("(ext:run-program \"uic\" (list \"-o\" \"ui.h\" \"%1\"))").arg(uiFile)
<< QString("(eql:quic \"ui.h\" \"%1ui-%2.lisp\" %3 %4)")
.arg(uiFile.left(sep))
.arg(uiFile.mid(sep, uiFile.length() - sep - 3))
.arg((arguments.length() == 2) ? ":ui" : arguments.at(2))
.arg(maximized ? ":maximized" : "")
<< QString("(delete-file \"ui.h\")")
<< QString("(eql:qq)"); }
else {
qDebug() << "\nPlease pass a file.ui (Qt Designer).\n";
exit(-1); }}
else {
if(arguments.length() == 1) {
// simple top-level
if(forms.isEmpty()) {
qexec = false;
forms << "(si:top-level)"; }}
else {
// load file
QString fileName(QDir::fromNativeSeparators(arguments.at(1)));
forms.prepend(QString("(load \"%1\")").arg(fileName)); }}
// eval
QString code;
if(forms.length() == 1) {
code = forms.first(); }
else {
code = "(progn " + forms.join(" ") + ")"; }
eval(code.toLatin1().constData());
// RESTART for Qt event loop
if(exec_with_simple_restart) {
qexec = false;
eval("(eql::exec-with-simple-restart)"); }}
void EQL::exec(lisp_ini ini, const QByteArray& expression, const QByteArray& package) {
// see my_app example
eval(QString("(eql::set-home \"%1\")").arg(home()).toLatin1().constData());
read_VV(OBJNULL, ini);
eval(QString("(in-package :%1)").arg(QString(package)).toLatin1().constData());
eval(expression.constData()); }
enum { NotFound = -1 };
void EQL::exec(QWidget* widget, const QString& lispFile, const QString& slimeHookFile) {
// see Qt_EQL example
bool exec_with_simple_restart = false;
QStringList forms;
eval("(in-package :eql)");
forms << QString("(set-home \"%1\")").arg(home())
<< QString("(defvar *qt-main* (qt-object %1 0 (qid \"%2\")))")
.arg((quintptr)widget)
.arg(QString(LObjects::vanillaQtSuperClassName(widget->metaObject())))
<< QString("(export '*qt-main*)")
<< QString("(in-package :eql-user)")
<< QString("(load \"%1\")").arg(lispFile);
if(!slimeHookFile.isEmpty()) {
QString startSwankFile(QCoreApplication::arguments().last());
if(NotFound == startSwankFile.indexOf(QRegExp("*start-swank*.lisp", Qt::CaseInsensitive, QRegExp::Wildcard))) {
qDebug() << "\nPlease pass the pathname for \"eql-start-swank.lisp\".\n";
exit(-1); }
QApplication::setQuitOnLastWindowClosed(false);
forms << QString("(load \"%1\")").arg(startSwankFile)
<< QString("(setf eql::*slime-hook-file* \"%1\")").arg(slimeHookFile)
<< QString("(setf eql:*slime-mode* t"
" eql:*qtpl* nil)");
exec_with_simple_restart = true; }
eval(QString("(progn " + forms.join(" ") + ")").toLatin1().constData());
if(exec_with_simple_restart) {
eval("(eql::exec-with-simple-restart)"); }}
void EQL::runInGuiThread(void* function_or_closure) {
const cl_env_ptr l_env = ecl_process_env();
CL_CATCH_ALL_BEGIN(l_env) {
CL_UNWIND_PROTECT_BEGIN(l_env) {
cl_funcall(1, (cl_object)function_or_closure); }
CL_UNWIND_PROTECT_EXIT {}
CL_UNWIND_PROTECT_END; }
CL_CATCH_ALL_END; }
bool EQL::cl_booted = false;
bool EQL::return_value_p = false;
bool EQL::qexec = true;
QEventLoop* EQL::eventLoop = 0;

106
src/eql.h
View file

@ -1,53 +1,53 @@
// copyright (c) Polos Ruetz
#ifndef EQL_H
#define EQL_H
#include <QObject>
#include <QByteArray>
#include <QStringList>
#include <QCoreApplication>
#include <ecl/ecl.h>
#include "dyn_object.h"
#include "eql_global.h"
QT_BEGIN_NAMESPACE
#define QSLOT(x) "1"#x
#define QSIGNAL(x) "2"#x
typedef void (*lisp_ini)(cl_object);
class EQL_EXPORT EQL : public QObject {
Q_OBJECT
public:
EQL();
static bool cl_booted;
static bool return_value_p;
static bool qexec;
static const char version[];
static QEventLoop* eventLoop;
static void ini(char**);
static void eval(const char*);
static QString home();
void exec(const QStringList&);
void exec(lisp_ini, const QByteArray& = "nil", const QByteArray& = "eql-user"); // see my_app example
void exec(QWidget*, const QString&, const QString& = QString()); // see Qt_EQL example
void printVersion() {
eval("(multiple-value-bind (eql qt)"
" (eql:qversion)"
" (format t \"EQL5 ~A (ECL ~A, Qt ~A)~%\" eql (lisp-implementation-version) qt))"); }
Q_INVOKABLE void runInGuiThread(void*);
public Q_SLOTS:
void exitEventLoop() { eventLoop->exit(); }
void removeConnections(QObject* object) { DynObject::removeConnections(object); }
};
QT_END_NAMESPACE
#endif
// copyright (c) Polos Ruetz
#ifndef EQL_H
#define EQL_H
#include <QObject>
#include <QByteArray>
#include <QStringList>
#include <QCoreApplication>
#include <ecl/ecl.h>
#include "dyn_object.h"
#include "eql_global.h"
QT_BEGIN_NAMESPACE
#define QSLOT(x) "1"#x
#define QSIGNAL(x) "2"#x
typedef void (*lisp_ini)(cl_object);
class EQL_EXPORT EQL : public QObject {
Q_OBJECT
public:
EQL();
static bool cl_booted;
static bool return_value_p;
static bool qexec;
static const char version[];
static QEventLoop* eventLoop;
static void ini(char**);
static void eval(const char*);
static QString home();
void exec(const QStringList&);
void exec(lisp_ini, const QByteArray& = "nil", const QByteArray& = "eql-user"); // see my_app example
void exec(QWidget*, const QString&, const QString& = QString()); // see Qt_EQL example
void printVersion() {
eval("(multiple-value-bind (eql qt)"
" (eql:qversion)"
" (format t \"EQL5 ~A (ECL ~A, Qt ~A)~%\" eql (lisp-implementation-version) qt))"); }
Q_INVOKABLE void runInGuiThread(void*);
public Q_SLOTS:
void exitEventLoop() { eventLoop->exit(); }
void removeConnections(QObject* object) { DynObject::removeConnections(object); }
};
QT_END_NAMESPACE
#endif

View file

@ -1,37 +1,37 @@
// copyright (c) Polos Ruetz
#include <QApplication>
#include <QtCore>
#include <iostream>
#include "eql.h"
int catch_all_qexec() {
int ret = 0;
CL_CATCH_ALL_BEGIN(ecl_process_env()) {
ret = QApplication::exec(); }
CL_CATCH_ALL_END;
return ret; }
int main(int argc, char** argv) {
EQL::ini(argv); // best initialized here
QApplication qapp(argc, argv);
QStringList args(QCoreApplication::arguments());
if(args.contains("-h") || (args.contains("--help"))) {
std::cout << "Usage: eql5 [file] [-qtpl] [-qgui] [-quic file.ui [:ui-package] [:maximized]] [-slime] [-norc]" << std::endl;
exit(0); }
QTextCodec* utf8 = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(utf8);
EQL eql;
eql.printVersion();
if(args.contains("-v") || args.contains("--version")) {
std::cout << std::endl;
exit(0); }
eql.exec(args);
if(EQL::qexec) {
return catch_all_qexec(); }
return 0; }
// copyright (c) Polos Ruetz
#include <QApplication>
#include <QtCore>
#include <iostream>
#include "eql.h"
int catch_all_qexec() {
int ret = 0;
CL_CATCH_ALL_BEGIN(ecl_process_env()) {
ret = QApplication::exec(); }
CL_CATCH_ALL_END;
return ret; }
int main(int argc, char** argv) {
EQL::ini(argv); // best initialized here
QApplication qapp(argc, argv);
QStringList args(QCoreApplication::arguments());
if(args.contains("-h") || (args.contains("--help"))) {
std::cout << "Usage: eql5 [file] [-qtpl] [-qgui] [-quic file.ui [:ui-package] [:maximized]] [-slime] [-norc]" << std::endl;
exit(0); }
QTextCodec* utf8 = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(utf8);
EQL eql;
eql.printVersion();
if(args.contains("-v") || args.contains("--version")) {
std::cout << std::endl;
exit(0); }
eql.exec(args);
if(EQL::qexec) {
return catch_all_qexec(); }
return 0; }

View file

@ -1,7 +1,7 @@
QT += help printsupport uitools
TEMPLATE = lib
CONFIG += dll no_keywords release
LIBS += -L.. -leql5
LIBS += -L.. -lecl -leql5
TARGET = eql5_help
DESTDIR = ../
OBJECTS_DIR = ./tmp/help/

View file

@ -1,7 +1,7 @@
QT += multimedia multimediawidgets printsupport uitools
TEMPLATE = lib
CONFIG += dll no_keywords release
LIBS += -L.. -leql5
LIBS += -L.. -lecl -leql5
TARGET = eql5_multimedia
DESTDIR = ../
OBJECTS_DIR = ./tmp/multimedia/

View file

@ -1,7 +1,7 @@
QT += network printsupport uitools
TEMPLATE = lib
CONFIG += dll no_keywords release
LIBS += -L.. -leql5
LIBS += -L.. -lecl -leql5
TARGET = eql5_network
DESTDIR = ../
OBJECTS_DIR = ./tmp/network/

View file

@ -1,7 +1,7 @@
QT += sql printsupport uitools
TEMPLATE = lib
CONFIG += dll no_keywords release
LIBS += -L.. -leql5
LIBS += -L.. -lecl -leql5
TARGET = eql5_sql
DESTDIR = ../
OBJECTS_DIR = ./tmp/sql/

View file

@ -1,7 +1,7 @@
QT += svg printsupport uitools
TEMPLATE = lib
CONFIG += dll no_keywords release
LIBS += -L.. -leql5
LIBS += -L.. -lecl -leql5
TARGET = eql5_svg
DESTDIR = ../
OBJECTS_DIR = ./tmp/svg/

View file

@ -1,7 +1,7 @@
QT += webkitwidgets printsupport uitools
TEMPLATE = lib
CONFIG += dll no_keywords release
LIBS += -L.. -leql5
LIBS += -L.. -lecl -leql5
TARGET = eql5_webkit
DESTDIR = ../
OBJECTS_DIR = ./tmp/webkit/