1. Henning Schröder
  2. embeddedpyqt

Commits

Henning Schröder  committed 233c2d8

updated example

  • Participants
  • Parent commits dbf6e7e
  • Branches default

Comments (0)

Files changed (7)

File demo.sh

View file
+#!/bin/sh
+qmake
+make
+./embeddedpyqt

File doc/index.rst

View file
 Welcome to EmbeddedPyQt's documentation!
 ========================================
 
+EmbeddedPyQt is a small library which can be integrated into your C++
+project to add Python scripting functionality.
+
+Every sub-class of QObject in Qt contains meta data which
+contains information about names, properties, signals, slots, etc.
+This can be used by PyQt to create *dynamic* bindings. 
+
+To make your objects available to Python you only have to make sure
+that you subclass from QObject. Every property can be read/written
+and every method is callable which is defined as a slot or marked with Q_INVOKABLE.
+
+This is a huge advantage over sip which requires definition files for
+each class to produce a binding library. But EmbeddedPyQt will
+never be as fast as sip. So if you need perfomance and flexibility
+you should stay with sip.
+
+
+
+
 Contents:
+---------
 
 .. toctree::
    :maxdepth: 2
    
    integration
+   using
 
 
 
+Download
+--------
+
+The newest snapshot is available at
+
+  http://www.henning-schroeder.de/embeddedpyqt/embeddedpyqt.tar.gz
+  
+  
+.. warning::
+  
+  This project is still in early stages and probably contains bugs.
+
+
 
 Indices and tables
-==================
+------------------
 
 * :ref:`genindex`
 * :ref:`modindex`

File doc/integration.rst

View file
 attribute. The same applies to instance properties.
 
 
-5. Call the init script:
+5. After that call the init script:
 
 .. code-block:: c
 
 by your build system and that the path is correct.
 
 
-6. Now you can call Python from C++ by using the execute method:
+Demo
+----
 
-.. code-block:: c
+The embeddedpyqt package already comes with a simple example. 
+The root folder contains a small C++ application
 
- embpyqt->execute("embpyqt_console.Visible = True", true);
+ * ``main.cpp`` creates the QApplication and main window instance
+ * ``mainwindow.{cpp,h,ui}`` sets up the user interface and integrates EmbeddedPyQt as show above
+ * ``test.{cpp.h}`` is a demo class which has to methods (test and calc)
+ * ``embeddedpyqt.pro`` is used by qmake to create a Makefile
  
-Python can connect to existing C++ signals and is able to modify the
-user interface.

File doc/using.rst

View file
+How to use EmbeddedPyQt
+=======================
+
+
+Calling Python from C++
+------------------------
+
+The method ``EmbeddedPyQt::execute`` emits a signal
+``excecutionRequested(QString command, bool globalContext)``
+which is connected to the Python interpreter. 
+
+.. code-block:: c
+
+ embpyqt->execute("embpyqt_console.Visible = True", true);
+ 
+
+If the second parameter is true then the command will be executed in a
+global context. Else the call will be executed in a new context.
+
+To execute a complete script you could use Python's execfile function:
+
+.. code-block:: c
+
+ embpyqt->execute("execfile('myscript.py')", false);
+
+
+Or you import the script as a module
+
+.. code-block:: c
+
+ embpyqt->execute("import myscript", false);
+
+
+But beware that a module will be only imported once.
+
+To pass complex parameters (e.g. QObject instances) to Python the best
+way is to create a signal. Then load a script into the global context
+and connect the C++ signal with your Python callback. After that you can
+emit the signal.
+
+
+Using C++ from Python
+---------------------
+
+Python can connect to existing C++ signals and is able to modify the
+user interface. All available classes and instances are availale in
+the global context. With a *fresh* context you have to import the names
+from the embeddedpyqt package.
+
+.. code-block:: python
+
+  from embeddedpyqt import *
+  embpyqt_console.Visible = True
+  test = Test()        # available in to demo app
+  print test.calc(1,2) # should return 3 
+  embpyqt_console.WindowTitle = "Done"
+ 
+
+Differences to sip
+------------------
+
+Because the bindings are dynamically created they behave not like sip
+bindings. The classes are created on-the-fly with Python meta
+programming. 
+
+Using the descriptor protocol it is possible to support
+properties natively (without using property/setProperty). 
+To prevent name clashes between properties and their getter methods
+the property name always starts with a captital letter.
+So while you would do the following with PyQt objects
+
+.. code-block:: python
+
+   old_title = dlg.windowTitle()
+   dlg.setWindowTitle(old_title + "*")
+   
+You now can write
+
+.. code-block:: python
+
+   dlg.WindowTitle = dlg.WindowTitle + "*"
+
+The idea is to provide a really simple scripting api for the end user.
+
+Additionally -like QtScript- a child object can be accessed like an attribute if
+the child has a object name.
+
+**Known limitations**:
+
+  * a little bit slower than sip
+  * currently sub-classing is not really working and untested
+  * explicit garbage collection handling might be needed for some objects
+  * exception handling not fully tested and undocumented
+  * creating a new QApplication instance will stop your app from working, please use qApp or QCoreApplication.instance() instead
+
+
+.. hint::
+
+  The underlying QObject of every wrapped class is available as an attribute 
+  called ``_qt``.
+  
+

File embpyqt/python/embeddedpyqt/__init__.py

View file
 
 
 def execute(command, global_context=False):
-	print "context", global_context
 	if global_context:
 		namespace = global_namespace
 	else:

File embpyqt/python/embeddedpyqt/miniconsole.py

View file
 
 example = """\
 from embeddedpyqt import *
-print dir()
+print 'names in current namespace', dir()
+t = Test()
+print 'members of Test instance', dir(t)
 for i in range(3):
-    print i, 'Hello, world!'
+    print 'Hello, world!', t.calc(i, i)
+embpyqt_console.WindowTitle = 'Done'
 """
 
 class PythonHighlighter(QSyntaxHighlighter):

File embpyqt/python/embeddedpyqt/proxy.py

View file
         instance = kwargs.pop("_wrap_instance", None)
         if not instance:
             mo = self.__class__.__dict__["_metaobject"]
-            instance = mo.newInstance(*args, **kwargs)
+            instance = mo.newInstance(*args)
+        elif args:
+            raise TypeError("Could not handle args %r for %s" % (args, self))
         self._qt = instance
+        if kwargs:
+            for name, value in kwargs.items():
+                self.__set__(self, self.__class__, value)
 
         
     def __del__(self):