update
This commit is contained in:
parent
bc84139179
commit
e72d0f7546
|
@ -1,5 +1,5 @@
|
|||
#ifndef _PYTHONQTDOC_H
|
||||
#define _PYTHONQTDOC_H
|
||||
#ifndef PYTHONQTDOC_H
|
||||
#define PYTHONQTDOC_H
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -53,21 +53,22 @@
|
|||
|
||||
\section Introduction
|
||||
|
||||
\b PythonQt is a dynamic <a href="http://www.python.org" target="_blank">
|
||||
Python</a> binding for the <a href="http://qt-project.org/" target="_blank">
|
||||
\b PythonQt is a dynamic <a href="http://www.python.org" target="_blank">
|
||||
Python</a> binding for the <a href="http://qt-project.org/" target="_blank">
|
||||
Qt framework</a>.
|
||||
It offers an easy way to embed the Python scripting language into
|
||||
your C++ Qt applications.
|
||||
|
||||
The focus of PythonQt is on embedding Python into an existing C++ application, not on writing the whole
|
||||
application completely in Python.
|
||||
|
||||
If you are looking for a simple way to embed Python objects into your C++/Qt Application
|
||||
and to script parts of your application via Python, PythonQt is the way to go!
|
||||
The focus of PythonQt is on embedding Python into an existing C++ application,
|
||||
not on writing the whole application completely in Python.
|
||||
|
||||
If you are looking for a simple way to embed Python objects into your C++/Qt
|
||||
Application and to script parts of your application via Python, PythonQt is the
|
||||
way to go!
|
||||
|
||||
PythonQt is a stable library that was developed to make the
|
||||
Image Processing and Visualization platform <a href="http://www.mevislab.de" target="_blank">MeVisLab</a>
|
||||
scriptable from Python.
|
||||
Image Processing and Visualization platform <a href="http://www.mevislab.de"
|
||||
target="_blank">MeVisLab</a> scriptable from Python.
|
||||
|
||||
- \ref Features
|
||||
- \ref Download
|
||||
|
@ -77,34 +78,55 @@ Qt framework</a>.
|
|||
- \ref Examples
|
||||
|
||||
\page Features Features
|
||||
|
||||
|
||||
\section Builtin Built-in Features
|
||||
|
||||
The following are the built-in features of the PythonQt library:
|
||||
|
||||
- Access all \b slots, \b properties, children and registered enums of any QObject derived class from Python
|
||||
- Connecting Qt Signals to Python functions (both from within Python and from C++)
|
||||
- Easy wrapping of Python objects from C++ with smart, reference-counting PythonQtObjectPtr.
|
||||
- Access all \b slots, \b properties, children and registered enums of any
|
||||
QObject derived class from Python
|
||||
- Connecting Qt Signals to Python functions (both from within Python and from
|
||||
C++)
|
||||
- Easy wrapping of Python objects from C++ with smart, reference-counting
|
||||
PythonQtObjectPtr.
|
||||
- Convenient conversions to/from QVariant for PythonQtObjectPtr.
|
||||
- Wrapping of C++ objects (which are not derived from QObject) via PythonQtCppWrapperFactory
|
||||
- Extending C++ and QObject derived classes with additional slots, static methods and constructors (see Decorators)
|
||||
- Wrapping of C++ objects (which are not derived from QObject) via
|
||||
PythonQtCppWrapperFactory
|
||||
- Extending C++ and QObject derived classes with additional slots, static
|
||||
methods and constructors (see Decorators)
|
||||
- StdOut/Err redirection to Qt signals instead of cout
|
||||
- Interface for creating your own \c import replacement, so that Python scripts can be e.g. signed/verified before they are executed (PythonQtImportFileInterface)
|
||||
- Interface for creating your own \c import replacement, so that Python scripts
|
||||
can be e.g. signed/verified before they are executed
|
||||
(PythonQtImportFileInterface)
|
||||
- Mapping of plain-old-datatypes and ALL QVariant types to and from Python
|
||||
- Support for wrapping of user QVariant types which are registerd via QMetaType
|
||||
- Support for Qt namespace (with all enumerators)
|
||||
- All PythonQt wrapped objects support the dir() statement, so that you can see easily which attributes a QObject, CPP object or QVariant has
|
||||
- No preprocessing/wrapping tool needs to be started, PythonQt can script any QObject without prior knowledge about it (except for the MetaObject information from the \b moc)
|
||||
- Multiple inheritance for C++ objects (e.g. a QWidget is derived from QObject and QPaintDevice, PythonQt will automatically cast a QWidget to a QPaintDevice when needed)
|
||||
- Polymorphic downcasting (if e.g. PythonQt sees a QEvent, it can downcast it depending on the type(), so the Python e.g. sees a QPaintEvent instead of a plain QEvent)
|
||||
- Deriving C++ objects from Python and overwriting virtual method with a Python implementation (requires usage of wrapper generator or manual work!)
|
||||
- Extensible handler for Python/C++ conversion of complex types, e.g. mapping of QVector<SomeObject> to/from a Python array
|
||||
- Setting of dynamic QObject properties via setProperty(), dynamic properties can be accessed for reading and writing like normal Python attributes (but creating a new property needs to be done with setProperty(), to distinguish from normal Python attributes)
|
||||
- Support for QtCore.Signal, QtCore.Slot and QtCore.Property, including the creation of a dynamic QMetaObject.
|
||||
|
||||
- All PythonQt wrapped objects support the dir() statement, so that you can see
|
||||
easily which attributes a QObject, CPP object or QVariant has
|
||||
- No preprocessing/wrapping tool needs to be started, PythonQt can script any
|
||||
QObject without prior knowledge about it (except for the MetaObject information
|
||||
from the \b moc)
|
||||
- Multiple inheritance for C++ objects (e.g. a QWidget is derived from QObject
|
||||
and QPaintDevice, PythonQt will automatically cast a QWidget to a QPaintDevice
|
||||
when needed)
|
||||
- Polymorphic downcasting (if e.g. PythonQt sees a QEvent, it can downcast it
|
||||
depending on the type(), so the Python e.g. sees a QPaintEvent instead of a
|
||||
plain QEvent)
|
||||
- Deriving C++ objects from Python and overwriting virtual method with a Python
|
||||
implementation (requires usage of wrapper generator or manual work!)
|
||||
- Extensible handler for Python/C++ conversion of complex types, e.g. mapping
|
||||
of QVector<SomeObject> to/from a Python array
|
||||
- Setting of dynamic QObject properties via setProperty(), dynamic properties
|
||||
can be accessed for reading and writing like normal Python attributes (but
|
||||
creating a new property needs to be done with setProperty(), to distinguish from
|
||||
normal Python attributes)
|
||||
- Support for QtCore.Signal, QtCore.Slot and QtCore.Property, including the
|
||||
creation of a dynamic QMetaObject.
|
||||
|
||||
\section FeaturesQtAll Features with wrapper generator
|
||||
|
||||
PythonQt offers the additional PythonQt_QtAll library which wraps the complete Qt API, including all C++ classes and all non-slots on QObject derived classes.
|
||||
PythonQt offers the additional PythonQt_QtAll library which wraps the complete
|
||||
Qt API, including all C++ classes and all non-slots on QObject derived classes.
|
||||
This offers the following features:
|
||||
|
||||
- Complete Qt API wrapped and accessible
|
||||
|
@ -121,11 +143,14 @@ Qt framework</a>.
|
|||
- QtMultimedia
|
||||
- QtQml
|
||||
- QtQuick
|
||||
- Any Qt class that has virtual methods can be easily derived from Python and the virtual methods can be reimplemented in Python
|
||||
- Any Qt class that has virtual methods can be easily derived from Python and
|
||||
the virtual methods can be reimplemented in Python
|
||||
- Polymorphic downcasting on QEvent, QGraphicsItem, QStyleOption, ...
|
||||
- Multiple inheritance support (e.g., QGraphicsTextItem is a QObject and a QGraphicsItem, PythonQt will handle this well)
|
||||
- QtQuick support is experimental and currently it is not possible to register new qml components from Python
|
||||
|
||||
- Multiple inheritance support (e.g., QGraphicsTextItem is a QObject and a
|
||||
QGraphicsItem, PythonQt will handle this well)
|
||||
- QtQuick support is experimental and currently it is not possible to register
|
||||
new qml components from Python
|
||||
|
||||
\section Supported Supported Versions
|
||||
|
||||
PythonQt supports:
|
||||
|
@ -133,49 +158,68 @@ Qt framework</a>.
|
|||
- Python 3 (>= Python 3.3)
|
||||
- Qt 4.x (Qt 4.7 and Qt 4.8 recommended)
|
||||
- Qt 5.x (Tested with Qt 5.0, 5.3, 5.4 and 5.6)
|
||||
|
||||
The last working Qt4 version is available at svn branches/Qt4LastWorkingVersion or you can download the PythonQt 3.0 release.
|
||||
The current svn trunk no longer supports Qt4, since we started to make use of some Qt5-only features.
|
||||
|
||||
The last working Qt4 version is available at svn branches/Qt4LastWorkingVersion
|
||||
or you can download the PythonQt 3.0 release. The current svn trunk no longer
|
||||
supports Qt4, since we started to make use of some Qt5-only features.
|
||||
|
||||
\section Comparison Comparison with PySide
|
||||
|
||||
- PythonQt is not as pythonic as PySide in many details (e.g. buffer protocol, pickling, translation support, ...) and it is mainly thought for embedding and intercommunication between Qt/Cpp and Python
|
||||
- PythonQt offers properties as Python attributes, while PySide offers them as setter/getter methods (e.g. QWidget.width is a property in PythonQt and a method in PySide)
|
||||
- PythonQt currently does not support instanceof checks for Qt classes, except for the exact match and derived Python classes
|
||||
- QObject.emit to emit Qt signals from Python is not yet implemented but PythonQt allows to just emit a signal by calling it like a normal slot
|
||||
- Ownership handling of objects is not as complete as in PySide and PySide, especially in situations where the ownership is not clearly passed to C++ on the C++ API.
|
||||
- QStrings are always converted to unicode Python objects, QByteArray always stays a QByteArray and can be converted using QByteArray.data()
|
||||
- Qt methods that take an extra "bool* ok" parameter can be called passing PythonQt.BoolResult as parameter. In PySide, a tuple is returned instead.
|
||||
|
||||
- PythonQt is not as pythonic as PySide in many details (e.g. buffer protocol,
|
||||
pickling, translation support, ...) and it is mainly thought for embedding and
|
||||
intercommunication between Qt/Cpp and Python
|
||||
- PythonQt offers properties as Python attributes, while PySide offers them as
|
||||
setter/getter methods (e.g. QWidget.width is a property in PythonQt and a method
|
||||
in PySide)
|
||||
- PythonQt currently does not support instanceof checks for Qt classes, except
|
||||
for the exact match and derived Python classes
|
||||
- QObject.emit to emit Qt signals from Python is not yet implemented but
|
||||
PythonQt allows to just emit a signal by calling it like a normal slot
|
||||
- Ownership handling of objects is not as complete as in PySide and PySide,
|
||||
especially in situations where the ownership is not clearly passed to C++ on the
|
||||
C++ API.
|
||||
- QStrings are always converted to unicode Python objects, QByteArray always
|
||||
stays a QByteArray and can be converted using QByteArray.data()
|
||||
- Qt methods that take an extra "bool* ok" parameter can be called passing
|
||||
PythonQt.BoolResult as parameter. In PySide, a tuple is returned instead.
|
||||
|
||||
\page Download Download
|
||||
|
||||
PythonQt is hosted on <a href="http://sourceforge.net/projects/pythonqt/" target="_blank">SourceForge</a>.
|
||||
PythonQt is hosted on <a href="http://sourceforge.net/projects/pythonqt/"
|
||||
target="_blank">SourceForge</a>.
|
||||
|
||||
You can download the source code as a tarball at http://sourceforge.net/projects/pythonqt/files/.
|
||||
Alternatively you can get the latest version from the svn repository.
|
||||
|
||||
You can also browse the source code online via ViewVC: http://pythonqt.svn.sourceforge.net/viewvc/pythonqt/trunk/
|
||||
You can download the source code as a tarball at
|
||||
http://sourceforge.net/projects/pythonqt/files/. Alternatively you can get the
|
||||
latest version from the svn repository.
|
||||
|
||||
\note We do not offer prebuilt binaries, since there are so many possible combinations of
|
||||
platforms (Windows/Linux/MacOs), architectures (32/64 bit) and Qt / Python versions.
|
||||
You can also browse the source code online via ViewVC:
|
||||
http://pythonqt.svn.sourceforge.net/viewvc/pythonqt/trunk/
|
||||
|
||||
\note We do not offer prebuilt binaries, since there are so many possible
|
||||
combinations of platforms (Windows/Linux/MacOs), architectures (32/64 bit) and
|
||||
Qt / Python versions.
|
||||
|
||||
\page License License
|
||||
|
||||
PythonQt is distributed under the LGPL 2.1 license. It can be used in commercial applications when following the LGPL 2.1 obligations.
|
||||
|
||||
The build system of PythonQt makes use of a modified version of the LGPL'ed QtScript generator,
|
||||
located in the "generator" directory.
|
||||
PythonQt is distributed under the LGPL 2.1 license. It can be used in
|
||||
commercial applications when following the LGPL 2.1 obligations.
|
||||
|
||||
See http://qt.gitorious.org/qt-labs/qtscriptgenerator for details on the original project.
|
||||
Thanks a lot to the QtJambi guys and the QtScript Generator project for the C++ parser and
|
||||
Qt typesystem files!
|
||||
The build system of PythonQt makes use of a modified version of the LGPL'ed
|
||||
QtScript generator, located in the "generator" directory.
|
||||
|
||||
The PythonQt wrappers generated by the generator located in the "generated_cpp" directory are free to be used without any licensing restrictions.
|
||||
See http://qt.gitorious.org/qt-labs/qtscriptgenerator for details on the
|
||||
original project. Thanks a lot to the QtJambi guys and the QtScript Generator
|
||||
project for the C++ parser and Qt typesystem files!
|
||||
|
||||
The generated wrappers are pre-generated and checked-in for 5.0, 5.3, 5.4 and 5.6, so you only need to build and run the
|
||||
generator when you want to build additional wrappers or you want to upgrade/downgrade to another Qt version.
|
||||
You may use the generator to generate C++ bindings for your own C++ classes (e.g., to make them inheritable in Python),
|
||||
but this is currently not documented and involves creating your own typesystem files.
|
||||
The PythonQt wrappers generated by the generator located in the "generated_cpp"
|
||||
directory are free to be used without any licensing restrictions.
|
||||
|
||||
The generated wrappers are pre-generated and checked-in for 5.0, 5.3, 5.4
|
||||
and 5.6, so you only need to build and run the generator when you want to build
|
||||
additional wrappers or you want to upgrade/downgrade to another Qt version. You
|
||||
may use the generator to generate C++ bindings for your own C++ classes (e.g.,
|
||||
to make them inheritable in Python), but this is currently not documented and
|
||||
involves creating your own typesystem files.
|
||||
|
||||
\page Developer Developer
|
||||
|
||||
|
@ -206,35 +250,40 @@ Qt framework</a>.
|
|||
<tr><td>QVariantList</td><td>tuple of objects</td></tr>
|
||||
<tr><td>QVariantMap</td><td>dict of objects</td></tr>
|
||||
<tr><td>QVariant</td><td>depends on type, see below</td></tr>
|
||||
<tr><td>QSize, QRect and all other standard Qt QVariants</td><td>variant wrapper that supports complete API of the respective Qt classes</td></tr>
|
||||
<tr><td>OwnRegisteredMetaType</td><td>C++ wrapper, optionally with additional information/wrapping provided by registerCPPClass()</td></tr>
|
||||
<tr><td>QSize, QRect and all other standard Qt QVariants</td><td>variant
|
||||
wrapper that supports complete API of the respective Qt classes</td></tr>
|
||||
<tr><td>OwnRegisteredMetaType</td><td>C++ wrapper, optionally with additional
|
||||
information/wrapping provided by registerCPPClass()</td></tr>
|
||||
<tr><td>QList<AnyObject*></td><td>converts to a list of CPP wrappers</td></tr>
|
||||
<tr><td>QVector<AnyObject*></td><td>converts to a list of CPP wrappers</td></tr>
|
||||
<tr><td>EnumType</td><td>Enum wrapper derived from python integer</td></tr>
|
||||
<tr><td>QObject (and derived classes)</td><td>QObject wrapper</td></tr>
|
||||
<tr><td>C++ object</td><td>CPP wrapper, either wrapped via PythonQtCppWrapperFactory or just decorated with decorators</td></tr>
|
||||
<tr><td>QVector<AnyObject*></td><td>converts to a list of CPP
|
||||
wrappers</td></tr> <tr><td>EnumType</td><td>Enum wrapper derived from python
|
||||
integer</td></tr> <tr><td>QObject (and derived classes)</td><td>QObject
|
||||
wrapper</td></tr> <tr><td>C++ object</td><td>CPP wrapper, either wrapped via
|
||||
PythonQtCppWrapperFactory or just decorated with decorators</td></tr>
|
||||
<tr><td>PyObject</td><td>PyObject</td></tr>
|
||||
</table>
|
||||
|
||||
PyObject is passed as direct pointer, which allows to pass/return any Python object directly to/from
|
||||
a Qt slot that uses PyObject* as its argument/return value.
|
||||
QVariants are mapped recursively as given above, e.g. a dictionary can
|
||||
PyObject is passed as direct pointer, which allows to pass/return any Python
|
||||
object directly to/from a Qt slot that uses PyObject* as its argument/return
|
||||
value. QVariants are mapped recursively as given above, e.g. a dictionary can
|
||||
contain lists of dictionaries of doubles.
|
||||
All Qt QVariant types are implemented, PythonQt supports the complete Qt API for these object.
|
||||
All Qt QVariant types are implemented, PythonQt supports the complete Qt API
|
||||
for these object.
|
||||
|
||||
\section QObject QObject Wrapping
|
||||
|
||||
All classes derived from QObject are automatically wrapped with a python wrapper class
|
||||
when they become visible to the Python interpreter. This can happen via
|
||||
All classes derived from QObject are automatically wrapped with a python
|
||||
wrapper class when they become visible to the Python interpreter. This can
|
||||
happen via
|
||||
- the PythonQt::addObject() method
|
||||
- when a Qt \b slot returns a QObject derived object to python
|
||||
- when a Qt \b signal contains a QObject and is connected to a python function
|
||||
|
||||
It is important that you call PythonQt::registerClass() for any QObject derived class
|
||||
that may become visible to Python, except when you add it via PythonQt::addObject().
|
||||
This will register the complete parent hierachy of the registered class, so that
|
||||
when you register e.g. a QPushButton, QWidget will be registered as well (and all intermediate
|
||||
parents).
|
||||
It is important that you call PythonQt::registerClass() for any QObject derived
|
||||
class that may become visible to Python, except when you add it via
|
||||
PythonQt::addObject(). This will register the complete parent hierachy of the
|
||||
registered class, so that when you register e.g. a QPushButton, QWidget will be
|
||||
registered as well (and all intermediate parents).
|
||||
|
||||
From Python, you can talk to the returned QObjects in a natural way by calling
|
||||
their slots and receiving the return values. You can also read/write all
|
||||
|
@ -242,12 +291,18 @@ Qt framework</a>.
|
|||
|
||||
In addition to this, the wrapped objects support
|
||||
- className() - returns a string that reprents the classname of the QObject
|
||||
- help() - shows all properties, slots, enums, decorator slots and constructors of the object, in a printable form
|
||||
- delete() - deletes the object (use with care, especially if you passed the ownership to C++)
|
||||
- connect(signal, function) - connect the signal of the given object to a python function
|
||||
- connect(signal, qobject, slot) - connect the signal of the given object to a slot of another QObject
|
||||
- disconnect(signal, function) - disconnect the signal of the given object from a python function
|
||||
- disconnect(signal, qobject, slot) - disconnect the signal of the given object from a slot of another QObject
|
||||
- help() - shows all properties, slots, enums, decorator slots and constructors
|
||||
of the object, in a printable form
|
||||
- delete() - deletes the object (use with care, especially if you passed the
|
||||
ownership to C++)
|
||||
- connect(signal, function) - connect the signal of the given object to a
|
||||
python function
|
||||
- connect(signal, qobject, slot) - connect the signal of the given object to a
|
||||
slot of another QObject
|
||||
- disconnect(signal, function) - disconnect the signal of the given object from
|
||||
a python function
|
||||
- disconnect(signal, qobject, slot) - disconnect the signal of the given object
|
||||
from a slot of another QObject
|
||||
- children() - returns the children of the object
|
||||
- setParent(QObject) - set the parent
|
||||
- QObject* parent() - get the parent
|
||||
|
@ -267,17 +322,20 @@ Qt framework</a>.
|
|||
|
||||
\section CPP CPP Wrapping
|
||||
|
||||
You can create dedicated wrapper QObjects for any C++ class. This is done by deriving from PythonQtCppWrapperFactory
|
||||
and adding your factory via addWrapperFactory().
|
||||
Whenever PythonQt encounters a CPP pointer (e.g. on a slot or signal)
|
||||
and it does not known it as a QObject derived class, it will create a generic CPP wrapper. So even unknown C++ objects
|
||||
can be passed through Python. If the wrapper factory supports the CPP class, a QObject wrapper will be created for each
|
||||
instance that enters Python. An alternative to a complete wrapper via the wrapper factory are decorators, see \ref Decorators
|
||||
You can create dedicated wrapper QObjects for any C++ class. This is done by
|
||||
deriving from PythonQtCppWrapperFactory and adding your factory via
|
||||
addWrapperFactory(). Whenever PythonQt encounters a CPP pointer (e.g. on a slot
|
||||
or signal) and it does not known it as a QObject derived class, it will create a
|
||||
generic CPP wrapper. So even unknown C++ objects can be passed through Python.
|
||||
If the wrapper factory supports the CPP class, a QObject wrapper will be created
|
||||
for each instance that enters Python. An alternative to a complete wrapper via
|
||||
the wrapper factory are decorators, see \ref Decorators
|
||||
|
||||
\section MetaObject Meta Object/Class access
|
||||
|
||||
For each known C++ class, PythonQt provides a Python class. These classes are visible
|
||||
inside of the "PythonQt" python module or in subpackages if a package is given when the class is registered.
|
||||
For each known C++ class, PythonQt provides a Python class. These classes are
|
||||
visible inside of the "PythonQt" python module or in subpackages if a package is
|
||||
given when the class is registered.
|
||||
|
||||
A Meta class supports:
|
||||
|
||||
|
@ -287,7 +345,8 @@ A Meta class supports:
|
|||
- unbound non-static methods
|
||||
- help() and className()
|
||||
|
||||
From within Python, you can import the module "PythonQt" to access these classes and the Qt namespace.
|
||||
From within Python, you can import the module "PythonQt" to access these classes
|
||||
and the Qt namespace.
|
||||
|
||||
\code
|
||||
from PythonQt import QtCore
|
||||
|
@ -309,27 +368,37 @@ QtCore.QFont.UltraCondensed
|
|||
|
||||
\section Decorators Decorator slots
|
||||
|
||||
PythonQt introduces a new generic approach to extend any wrapped QObject or CPP object with
|
||||
PythonQt introduces a new generic approach to extend any wrapped QObject or CPP
|
||||
object with
|
||||
|
||||
- constructors
|
||||
- destructors (for CPP objects)
|
||||
- additional slots
|
||||
- static slots (callable on both the Meta object and the instances)
|
||||
|
||||
The idea behind decorators is that we wanted to make it as easy as possible to extend
|
||||
wrapped objects. Since we already have an implementation for invoking any Qt Slot from
|
||||
Python, it looked promising to use this approach for the extension of wrapped objects as well.
|
||||
This avoids that the PythonQt user needs to care about how Python arguments are mapped from/to
|
||||
Qt when he wants to create static methods, constructors and additional member functions.
|
||||
The idea behind decorators is that we wanted to make it as easy as possible to
|
||||
extend wrapped objects. Since we already have an implementation for invoking any
|
||||
Qt Slot from Python, it looked promising to use this approach for the extension
|
||||
of wrapped objects as well. This avoids that the PythonQt user needs to care
|
||||
about how Python arguments are mapped from/to Qt when he wants to create static
|
||||
methods, constructors and additional member functions.
|
||||
|
||||
The basic idea about decorators is to create a QObject derived class that implements slots
|
||||
which take one of the above roles (e.g. constructor, destructor etc.) via a naming convention.
|
||||
These slots are then assigned to other classes via the naming convention.
|
||||
The basic idea about decorators is to create a QObject derived class that
|
||||
implements slots which take one of the above roles (e.g. constructor, destructor
|
||||
etc.) via a naming convention. These slots are then assigned to other classes
|
||||
via the naming convention.
|
||||
|
||||
- SomeClassName* new_SomeClassName(...) - defines a constructor for "SomeClassName" that returns a new object of type SomeClassName (where SomeClassName can be any CPP class, not just QObject classes)
|
||||
- void delete_SomeClassName(SomeClassName* o) - defines a destructor, which should delete the passed in object o
|
||||
- anything static_SomeClassName_someMethodName(...) - defines a static method that is callable on instances and the meta class
|
||||
- anything someMethodName(SomeClassName* o, ...) - defines a slot that will be available on SomeClassName instances (and derived instances). When such a slot is called the first argument is the pointer to the instance and the rest of the arguments can be used to make a call on the instance.
|
||||
- SomeClassName* new_SomeClassName(...) - defines a constructor for
|
||||
"SomeClassName" that returns a new object of type SomeClassName (where
|
||||
SomeClassName can be any CPP class, not just QObject classes)
|
||||
- void delete_SomeClassName(SomeClassName* o) - defines a destructor, which
|
||||
should delete the passed in object o
|
||||
- anything static_SomeClassName_someMethodName(...) - defines a static method
|
||||
that is callable on instances and the meta class
|
||||
- anything someMethodName(SomeClassName* o, ...) - defines a slot that will be
|
||||
available on SomeClassName instances (and derived instances). When such a slot
|
||||
is called the first argument is the pointer to the instance and the rest of the
|
||||
arguments can be used to make a call on the instance.
|
||||
|
||||
The below example shows all kinds of decorators in action:
|
||||
|
||||
|
@ -358,10 +427,12 @@ public slots:
|
|||
QSize* new_QSize(const QPoint& p) { return new QSize(p.x(), p.y()); }
|
||||
|
||||
// add a constructor for QPushButton that takes a text and a parent widget
|
||||
QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) { return new QPushButton(text, parent); }
|
||||
QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) {
|
||||
return new QPushButton(text, parent); }
|
||||
|
||||
// add a constructor for a CPP object
|
||||
YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new YourCPPObject(arg1, arg2); }
|
||||
YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new
|
||||
YourCPPObject(arg1, arg2); }
|
||||
|
||||
// add a destructor for a CPP object
|
||||
void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
|
||||
|
@ -369,14 +440,16 @@ public slots:
|
|||
// add a static method to QWidget
|
||||
QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
|
||||
|
||||
// add an additional slot to QWidget (make move() callable, which is not declared as a slot in QWidget)
|
||||
void move(QWidget* w, const QPoint& p) { w->move(p); }
|
||||
// add an additional slot to QWidget (make move() callable, which is not
|
||||
declared as a slot in QWidget) void move(QWidget* w, const QPoint& p) {
|
||||
w->move(p); }
|
||||
|
||||
// add an additional slot to QWidget, overloading the above move method
|
||||
void move(QWidget* w, int x, int y) { w->move(x,y); }
|
||||
|
||||
// add a method to your own CPP object
|
||||
int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1); }
|
||||
int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1);
|
||||
}
|
||||
};
|
||||
|
||||
...
|
||||
|
@ -386,8 +459,9 @@ PythonQt::self()->registerCPPClass("YourCPPObject");
|
|||
|
||||
\endcode
|
||||
|
||||
After you have registered an instance of the above ExampleDecorator, you can do the following from Python
|
||||
(all these calls are mapped to the above decorator slots):
|
||||
After you have registered an instance of the above ExampleDecorator, you can do
|
||||
the following from Python (all these calls are mapped to the above decorator
|
||||
slots):
|
||||
|
||||
\code
|
||||
from PythonQt import QtCore, QtGui, YourCPPObject
|
||||
|
@ -420,18 +494,22 @@ yourCpp = None
|
|||
|
||||
\section Ownership Ownership management
|
||||
|
||||
In PythonQt, each wrapped C++ object is either owned by Python or C++. When an object is created via a Python constructor,
|
||||
it is owned by Python by default. When an object is returned from a C++ API (e.g. a slot), it is owned by C++ by default.
|
||||
Since the Qt API contains various APIs that pass the ownership from/to other C++ objects, PythonQt needs to keep track of
|
||||
such API calls. This is archieved by annotating arguments and return values in wrapper slots with magic templates:
|
||||
|
||||
In PythonQt, each wrapped C++ object is either owned by Python or C++. When an
|
||||
object is created via a Python constructor, it is owned by Python by default.
|
||||
When an object is returned from a C++ API (e.g. a slot), it is owned by C++ by
|
||||
default. Since the Qt API contains various APIs that pass the ownership from/to
|
||||
other C++ objects, PythonQt needs to keep track of such API calls. This is
|
||||
archieved by annotating arguments and return values in wrapper slots with magic
|
||||
templates:
|
||||
|
||||
- PythonQtPassOwnershipToCPP
|
||||
- PythonQtPassOwnershipToPython
|
||||
- PythonQtNewOwnerOfThis
|
||||
|
||||
These annotation templates work for since C++ pointer types. In addition to that, they work for QList<AnyObject*>,
|
||||
to pass the ownership for each object in the list.
|
||||
|
||||
These annotation templates work for since C++ pointer types. In addition to
|
||||
that, they work for QList<AnyObject*>, to pass the ownership for each object in
|
||||
the list.
|
||||
|
||||
Examples:
|
||||
\code
|
||||
public slots:
|
||||
|
@ -441,31 +519,34 @@ yourCpp = None
|
|||
//! Pass ownership of item to C++
|
||||
void addItemToCPP(PythonQtPassOwnershipToPython<QGraphicsItem*> item);
|
||||
|
||||
//! Pass ownership of items to C++ (Note that the QList can't be a reference nor a pointer).
|
||||
void addItemToCPP(PythonQtPassOwnershipToPython<QList<QGraphicsItem*> > items);
|
||||
//! Pass ownership of items to C++ (Note that the QList can't be a reference
|
||||
nor a pointer). void
|
||||
addItemToCPP(PythonQtPassOwnershipToPython<QList<QGraphicsItem*> > items);
|
||||
|
||||
//! Pass ownership of wrapped object to C++ if parent is != NULL
|
||||
void addItemParent(QGraphicsItem* wrappedObject, PythonQtNewOwnerOfThis<QGraphicsItem*> parent);
|
||||
\endcode
|
||||
|
||||
void addItemParent(QGraphicsItem* wrappedObject,
|
||||
PythonQtNewOwnerOfThis<QGraphicsItem*> parent); \endcode
|
||||
|
||||
\page Building Building
|
||||
|
||||
PythonQt requires at least Qt 4.6.1 (for earlier Qt versions, you will need to run the pythonqt_generator, Qt 4.3 is the absolute minimum) and Python 2.6.x/2.7.x or Python 3.3 (or higher).
|
||||
To compile PythonQt, you will need a python developer installation which includes Python's header files and
|
||||
the python2x.[lib | dll | so | dynlib].
|
||||
The recommended way to build PythonQt is to use the QMake-based *.pro file.
|
||||
The build scripts a currently set to use Python 2.6.
|
||||
You may need to tweak the \b build/python.prf file to set the correct Python includes and libs on your system.
|
||||
|
||||
PythonQt requires at least Qt 4.6.1 (for earlier Qt versions, you will need to
|
||||
run the pythonqt_generator, Qt 4.3 is the absolute minimum) and
|
||||
Python 2.6.x/2.7.x or Python 3.3 (or higher). To compile PythonQt, you will need
|
||||
a python developer installation which includes Python's header files and the
|
||||
python2x.[lib | dll | so | dynlib]. The recommended way to build PythonQt is to
|
||||
use the QMake-based *.pro file. The build scripts a currently set to use
|
||||
Python 2.6. You may need to tweak the \b build/python.prf file to set the
|
||||
correct Python includes and libs on your system.
|
||||
|
||||
\subsection Windows
|
||||
|
||||
On Windows, the (non-source) Python Windows installer can be used.
|
||||
Make sure that you use the same compiler as the one that your Python distribution is built with.
|
||||
If you want to use another compiler, you will need to build
|
||||
Python yourself, using your compiler.
|
||||
Make sure that you use the same compiler as the one that your Python
|
||||
distribution is built with. If you want to use another compiler, you will need
|
||||
to build Python yourself, using your compiler.
|
||||
|
||||
To build PythonQt, you need to set the environment variable \b PYTHON_PATH to point to the root
|
||||
dir of the python installation and \b PYTHON_LIB to point to
|
||||
To build PythonQt, you need to set the environment variable \b PYTHON_PATH to
|
||||
point to the root dir of the python installation and \b PYTHON_LIB to point to
|
||||
the directory where the python lib file is located.
|
||||
|
||||
When using the prebuild Python installer, this will be:
|
||||
|
@ -491,16 +572,16 @@ the python2x.[lib | dll | so | dynlib].
|
|||
> nmake
|
||||
\endcode
|
||||
|
||||
This should build everything. If Python can not be linked or include files can not be found,
|
||||
you probably need to tweak \b build/python.prf
|
||||
This should build everything. If Python can not be linked or include files can
|
||||
not be found, you probably need to tweak \b build/python.prf
|
||||
|
||||
The tests and examples are located in PythonQt/lib.
|
||||
|
||||
When using a Python distribution, the debug build typically does not work because the
|
||||
pythonxx_d.lib/.dll are not provided. You can tweak linking of the debug build to the release
|
||||
Python version, but this typically requires patching pyconfig.h and removing Py_DEBUG and linker pragmas
|
||||
(google for it!).
|
||||
|
||||
When using a Python distribution, the debug build typically does not work
|
||||
because the pythonxx_d.lib/.dll are not provided. You can tweak linking of the
|
||||
debug build to the release Python version, but this typically requires patching
|
||||
pyconfig.h and removing Py_DEBUG and linker pragmas (google for it!).
|
||||
|
||||
\subsection Linux
|
||||
|
||||
On Linux, you need to install a Python-dev package.
|
||||
|
@ -521,8 +602,8 @@ the python2x.[lib | dll | so | dynlib].
|
|||
|
||||
\subsection MacOsX
|
||||
|
||||
On Mac, Python is installed as a Framework, so you should not need to install it.
|
||||
To build PythonQt, just do a:
|
||||
On Mac, Python is installed as a Framework, so you should not need to install
|
||||
it. To build PythonQt, just do a:
|
||||
|
||||
\code
|
||||
> cd PythonQtRoot
|
||||
|
@ -532,14 +613,18 @@ the python2x.[lib | dll | so | dynlib].
|
|||
|
||||
\section Tests
|
||||
|
||||
There is a unit test that tests most features of PythonQt, see the \b tests subdirectory for details.
|
||||
There is a unit test that tests most features of PythonQt, see the \b tests
|
||||
subdirectory for details.
|
||||
|
||||
\page Examples Examples
|
||||
|
||||
Examples are available in the \b examples directory. The PyScriptingConsole implements a simple
|
||||
interactive scripting console that shows how to script a simple application. The PyLauncher application can be used to run arbitrary PythonQt scripts given on the commandline.
|
||||
Examples are available in the \b examples directory. The PyScriptingConsole
|
||||
implements a simple interactive scripting console that shows how to script a
|
||||
simple application. The PyLauncher application can be used to run arbitrary
|
||||
PythonQt scripts given on the commandline.
|
||||
|
||||
The following shows a simple example on how to integrate PythonQt into your Qt application:
|
||||
The following shows a simple example on how to integrate PythonQt into your Qt
|
||||
application:
|
||||
|
||||
\code
|
||||
#include "PythonQt.h"
|
||||
|
@ -557,9 +642,8 @@ the python2x.[lib | dll | so | dynlib].
|
|||
// get a smart pointer to the __main__ module of the Python interpreter
|
||||
PythonQtObjectPtr context = PythonQt::self()->getMainModule();
|
||||
|
||||
// add a QObject as variable of name "example" to the namespace of the __main__ module
|
||||
PyExampleObject example;
|
||||
context.addObject("example", &example);
|
||||
// add a QObject as variable of name "example" to the namespace of the
|
||||
__main__ module PyExampleObject example; context.addObject("example", &example);
|
||||
|
||||
// do something
|
||||
context.evalScript("print example");
|
||||
|
@ -572,3 +656,5 @@ the python2x.[lib | dll | so | dynlib].
|
|||
|
||||
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef _PYTHONQTMISC_H
|
||||
#define _PYTHONQTMISC_H
|
||||
#ifndef PYTHONQTMISC_H
|
||||
#define PYTHONQTMISC_H
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -42,61 +42,63 @@
|
|||
*/
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <QList>
|
||||
|
||||
#define PythonQtValueStorage_ADD_VALUE(store, type, value, ptr) \
|
||||
{ type* item = (type*)store.nextValuePtr(); \
|
||||
*item = value; \
|
||||
ptr = (void*)item; \
|
||||
}
|
||||
#define PythonQtValueStorage_ADD_VALUE(store, type, value, ptr) \
|
||||
{ \
|
||||
type *item = (type *)store.nextValuePtr(); \
|
||||
*item = value; \
|
||||
ptr = (void *)item; \
|
||||
}
|
||||
|
||||
#define PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedPtr,store, type, value, ptr) \
|
||||
{ \
|
||||
type* item = (type*)(alreadyAllocatedPtr?alreadyAllocatedPtr:store.nextValuePtr()); \
|
||||
*item = value; \
|
||||
ptr = (void*)item; \
|
||||
}
|
||||
#define PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedPtr, store, \
|
||||
type, value, ptr) \
|
||||
{ \
|
||||
type *item = (type *)(alreadyAllocatedPtr ? alreadyAllocatedPtr \
|
||||
: store.nextValuePtr()); \
|
||||
*item = value; \
|
||||
ptr = (void *)item; \
|
||||
}
|
||||
|
||||
//! stores a position in the PythonQtValueStorage
|
||||
class PythonQtValueStoragePosition {
|
||||
|
||||
public:
|
||||
PythonQtValueStoragePosition() { chunkIdx = 0; chunkOffset = 0; }
|
||||
PythonQtValueStoragePosition() {
|
||||
chunkIdx = 0;
|
||||
chunkOffset = 0;
|
||||
}
|
||||
|
||||
int chunkIdx;
|
||||
int chunkOffset;
|
||||
|
||||
};
|
||||
|
||||
//! a helper class that stores basic C++ value types in chunks
|
||||
template <typename T, int chunkEntries> class PythonQtValueStorage
|
||||
{
|
||||
template <typename T, int chunkEntries> class PythonQtValueStorage {
|
||||
public:
|
||||
PythonQtValueStorage() {
|
||||
_chunkIdx = 0;
|
||||
_chunkIdx = 0;
|
||||
_chunkOffset = 0;
|
||||
_currentChunk = new T[chunkEntries];
|
||||
_chunks.append(_currentChunk);
|
||||
};
|
||||
}
|
||||
|
||||
//! clear all memory
|
||||
void clear() {
|
||||
T* chunk;
|
||||
Q_FOREACH(chunk, _chunks) {
|
||||
delete[]chunk;
|
||||
}
|
||||
T *chunk;
|
||||
Q_FOREACH (chunk, _chunks) { delete[] chunk; }
|
||||
_chunks.clear();
|
||||
}
|
||||
|
||||
//! get the current position to be restored with setPos
|
||||
void getPos(PythonQtValueStoragePosition & pos) {
|
||||
void getPos(PythonQtValueStoragePosition &pos) {
|
||||
pos.chunkIdx = _chunkIdx;
|
||||
pos.chunkOffset = _chunkOffset;
|
||||
}
|
||||
|
||||
//! set the current position (without freeing memory, thus caching old entries for reuse)
|
||||
void setPos(const PythonQtValueStoragePosition& pos) {
|
||||
//! set the current position (without freeing memory, thus caching old entries
|
||||
//! for reuse)
|
||||
void setPos(const PythonQtValueStoragePosition &pos) {
|
||||
_chunkOffset = pos.chunkOffset;
|
||||
if (_chunkIdx != pos.chunkIdx) {
|
||||
_chunkIdx = pos.chunkIdx;
|
||||
|
@ -105,11 +107,11 @@ public:
|
|||
}
|
||||
|
||||
//! add one default constructed value and return the pointer to it
|
||||
T* nextValuePtr() {
|
||||
if (_chunkOffset>=chunkEntries) {
|
||||
T *nextValuePtr() {
|
||||
if (_chunkOffset >= chunkEntries) {
|
||||
_chunkIdx++;
|
||||
if (_chunkIdx >= _chunks.size()) {
|
||||
T* newChunk = new T[chunkEntries];
|
||||
T *newChunk = new T[chunkEntries];
|
||||
_chunks.append(newChunk);
|
||||
_currentChunk = newChunk;
|
||||
} else {
|
||||
|
@ -117,47 +119,48 @@ public:
|
|||
}
|
||||
_chunkOffset = 0;
|
||||
}
|
||||
T* newEntry = _currentChunk + _chunkOffset;
|
||||
T *newEntry = _currentChunk + _chunkOffset;
|
||||
_chunkOffset++;
|
||||
return newEntry;
|
||||
};
|
||||
}
|
||||
|
||||
protected:
|
||||
QList<T*> _chunks;
|
||||
QList<T *> _chunks;
|
||||
|
||||
int _chunkIdx;
|
||||
int _chunkOffset;
|
||||
T* _currentChunk;
|
||||
|
||||
T *_currentChunk;
|
||||
};
|
||||
|
||||
//! a helper class that stores basic C++ value types in chunks and clears the unused values on setPos() usage.
|
||||
template <typename T, int chunkEntries> class PythonQtValueStorageWithCleanup : public PythonQtValueStorage<T, chunkEntries>
|
||||
{
|
||||
//! a helper class that stores basic C++ value types in chunks and clears the
|
||||
//! unused values on setPos() usage.
|
||||
template <typename T, int chunkEntries>
|
||||
class PythonQtValueStorageWithCleanup
|
||||
: public PythonQtValueStorage<T, chunkEntries> {
|
||||
public:
|
||||
void setPos(const PythonQtValueStoragePosition& pos) {
|
||||
void setPos(const PythonQtValueStoragePosition &pos) {
|
||||
if (_chunkIdx > pos.chunkIdx) {
|
||||
T* firstChunk = _chunks.at(pos.chunkIdx);
|
||||
T *firstChunk = _chunks.at(pos.chunkIdx);
|
||||
// clear region in first chunk
|
||||
for (int i = pos.chunkOffset; i < chunkEntries; i++) {
|
||||
firstChunk[i] = T();
|
||||
}
|
||||
for (int chunk = pos.chunkIdx + 1; chunk < _chunkIdx; chunk++) {
|
||||
// clear the full chunks between the first and last chunk
|
||||
T* fullChunk = _chunks.at(chunk);
|
||||
T *fullChunk = _chunks.at(chunk);
|
||||
for (int i = 0; i < chunkEntries; i++) {
|
||||
fullChunk[i] = T();
|
||||
}
|
||||
}
|
||||
// clear region in last chunk
|
||||
T* lastChunk = _chunks.at(_chunkIdx);
|
||||
T *lastChunk = _chunks.at(_chunkIdx);
|
||||
for (int i = 0; i < _chunkOffset; i++) {
|
||||
lastChunk[i] = T();
|
||||
}
|
||||
} else if (_chunkIdx == pos.chunkIdx) {
|
||||
// clear the region in the last chunk only
|
||||
T* lastChunk = _chunks.at(_chunkIdx);
|
||||
for (int i = pos.chunkOffset; i<_chunkOffset; i++) {
|
||||
T *lastChunk = _chunks.at(_chunkIdx);
|
||||
for (int i = pos.chunkOffset; i < _chunkOffset; i++) {
|
||||
lastChunk[i] = T();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,11 +82,11 @@ public Q_SLOTS:
|
|||
return connect(sender, signal, receiver, slot, type);
|
||||
}
|
||||
bool disconnect(QObject *sender, const QString &signal,
|
||||
PyObject *callable = NULL);
|
||||
PyObject *callable = nullptr);
|
||||
bool disconnect(QObject *sender, const QString &signal, QObject *receiver,
|
||||
const QString &slot);
|
||||
bool static_QObject_disconnect(QObject *sender, const QString &signal,
|
||||
PyObject *callable = NULL) {
|
||||
PyObject *callable = nullptr) {
|
||||
return disconnect(sender, signal, callable);
|
||||
}
|
||||
bool static_QObject_disconnect(QObject *sender, const QString &signal,
|
||||
|
@ -253,7 +253,7 @@ public Q_SLOTS:
|
|||
class PYTHONQT_EXPORT PythonQtDebugAPI : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
PythonQtDebugAPI(QObject *parent) : QObject(parent){};
|
||||
PythonQtDebugAPI(QObject *parent) : QObject(parent) {}
|
||||
|
||||
public slots:
|
||||
//! Returns if the C++ object is owned by PythonQt and will be deleted when
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<name>if</name>
|
||||
<name>else</name>
|
||||
<name>def</name>
|
||||
<name>from</name>
|
||||
<name>import</name>
|
||||
<name>return</name>
|
||||
<name>class</name>
|
||||
|
@ -29,110 +30,6 @@
|
|||
<name>max</name>
|
||||
<name>len</name>
|
||||
<name>main</name>
|
||||
<name>currentDoc</name>
|
||||
<name>currentDocFilename</name>
|
||||
<name>isReadOnly</name>
|
||||
<name>isKeepSize</name>
|
||||
<name>isLocked</name>
|
||||
<name>documentLines</name>
|
||||
<name>documentBytes</name>
|
||||
<name>currentPos</name>
|
||||
<name>selectionPos</name>
|
||||
<name>currentRow</name>
|
||||
<name>currentColumn</name>
|
||||
<name>currentOffset</name>
|
||||
<name>selectlength</name>
|
||||
<name>stringVisible</name>
|
||||
<name>addressVisible</name>
|
||||
<name>headerVisible</name>
|
||||
<name>addressBase</name>
|
||||
<name>isModified</name>
|
||||
<name>isEmpty</name>
|
||||
<name>atEnd</name>
|
||||
<name>canUndo</name>
|
||||
<name>canRedo</name>
|
||||
<name>copy</name>
|
||||
<name>read</name>
|
||||
<name>searchForward</name>
|
||||
<name>searchBackward</name>
|
||||
<name>findAllBytes</name>
|
||||
<name>documentLastLine</name>
|
||||
<name>documentLastColumn</name>
|
||||
<name>lineHasMetadata</name>
|
||||
<name>getMetadatas</name>
|
||||
<name>getMetaLine</name>
|
||||
<name>lineHasBookMark</name>
|
||||
<name>getsBookmarkPos</name>
|
||||
<name>bookMark</name>
|
||||
<name>bookMarkComment</name>
|
||||
<name>getBookMarks</name>
|
||||
<name>existBookMark</name>
|
||||
<name>getOpenFiles</name>
|
||||
<name>getSupportedEncodings</name>
|
||||
<name>currentEncoding</name>
|
||||
<name>switchDocument</name>
|
||||
<name>setKeepSize</name>
|
||||
<name>setStringVisible</name>
|
||||
<name>setAddressVisible</name>
|
||||
<name>setHeaderVisible</name>
|
||||
<name>setAddressBase</name>
|
||||
<name>undo</name>
|
||||
<name>redo</name>
|
||||
<name>cut</name>
|
||||
<name>paste</name>
|
||||
<name>insert</name>
|
||||
<name>paste</name>
|
||||
<name>remove</name>
|
||||
<name>moveTo</name>
|
||||
<name>select</name>
|
||||
<name>selectOffset</name>
|
||||
<name>setInsertionMode</name>
|
||||
<name>enabledCursor</name>
|
||||
<name>metadata</name>
|
||||
<name>removeMetadata</name>
|
||||
<name>clearMeta</name>
|
||||
<name>color</name>
|
||||
<name>foreground</name>
|
||||
<name>background</name>
|
||||
<name>comment</name>
|
||||
<name>applyMetas</name>
|
||||
<name>setMetaVisible</name>
|
||||
<name>setMetafgVisible</name>
|
||||
<name>setMetabgVisible</name>
|
||||
<name>setMetaCommentVisible</name>
|
||||
<name>newFile</name>
|
||||
<name>openFile</name>
|
||||
<name>openDriver</name>
|
||||
<name>closeFile</name>
|
||||
<name>saveFile</name>
|
||||
<name>exportFile</name>
|
||||
<name>exportFileGUI</name>
|
||||
<name>saveasFile</name>
|
||||
<name>saveasFileGUI</name>
|
||||
<name>closeCurrentFile</name>
|
||||
<name>saveCurrentFile</name>
|
||||
<name>openFileGUI</name>
|
||||
<name>openDriverGUI</name>
|
||||
<name>findGUI</name>
|
||||
<name>gotoGUI</name>
|
||||
<name>fillGUI</name>
|
||||
<name>fillzeroGUI</name>
|
||||
<name>fillnopGUI</name>
|
||||
<name>addBookMark</name>
|
||||
<name>modBookMark</name>
|
||||
<name>applyBookMarks</name>
|
||||
<name>removeBookMark</name>
|
||||
<name>clearBookMark</name>
|
||||
<name>openWorkSpace</name>
|
||||
<name>setCurrentEncoding</name>
|
||||
<name>toast</name>
|
||||
<name>print</name>
|
||||
<name>errPrint</name>
|
||||
<name>infoPrint</name>
|
||||
<name>warnPrint</name>
|
||||
<name>requestControl</name>
|
||||
<name>hasControl</name>
|
||||
<name>requestRelease</name>
|
||||
</section>
|
||||
<section name="PrimitiveType">
|
||||
<name>float</name>
|
||||
|
|
|
@ -21,9 +21,8 @@
|
|||
### 使用声明
|
||||
|
||||
1. 开发本软件目的是让羽云十六进制编辑器具有强大的脚本分析功能,使用 C++ 的 Python 拓展来弥补羽云十六进制编辑器相对于 010 Editor 的不足之处。
|
||||
2. 本软件仅供学习交流使用,不得私自用于商业用途。如需将本软件某些部分用于商业用途,必须找我购买商业授权,价格私聊。
|
||||
3. 本人学生,由于本软件是用我的业余时间编写,不能及时修复 Bug 或者提供技术支持,请见谅。
|
||||
4. 本人非计算机专业,编写程序难免有 Bug ,欢迎提交 PR 。
|
||||
2. 本人学生,由于本软件是用我的业余时间编写,不能及时修复 Bug 或者提供技术支持,请见谅。
|
||||
3. 本人非计算机专业,编写程序难免有 Bug ,欢迎提交 PR 。
|
||||
|
||||
### 参与贡献
|
||||
|
||||
|
|
|
@ -40,7 +40,8 @@ SOURCES += \
|
|||
linebar.cpp \
|
||||
replacebar.cpp \
|
||||
aboutsoftwaredialog.cpp \
|
||||
sponsordialog.cpp
|
||||
sponsordialog.cpp \
|
||||
jumplinebar.cpp
|
||||
|
||||
HEADERS += \
|
||||
winghexpy.h \
|
||||
|
@ -88,9 +89,13 @@ HEADERS += \
|
|||
linebar.h \
|
||||
replacebar.h \
|
||||
aboutsoftwaredialog.h \
|
||||
sponsordialog.h
|
||||
sponsordialog.h \
|
||||
jumplinebar.h
|
||||
|
||||
DISTFILES += WingHexPy.json
|
||||
DISTFILES += WingHexPy.json \
|
||||
img/infotable.png \
|
||||
img/infotree.png \
|
||||
img/infotxt.png
|
||||
|
||||
TRANSLATIONS += \
|
||||
$$PWD/WingHexPy.ts
|
||||
|
|
16
findbar.cpp
16
findbar.cpp
|
@ -93,8 +93,7 @@ void FindBar::focus() {
|
|||
m_editLine->lineEdit()->selectAll();
|
||||
}
|
||||
|
||||
void FindBar::activeInput(QString text, QString file, int row, int column,
|
||||
int scrollOffset) {
|
||||
void FindBar::activeInput(QString text, int row, int column, int scrollOffset) {
|
||||
// Try fill keyword with select text.
|
||||
m_editLine->lineEdit()->clear();
|
||||
m_editLine->lineEdit()->insert(text);
|
||||
|
@ -104,7 +103,6 @@ void FindBar::activeInput(QString text, QString file, int row, int column,
|
|||
QWidget::show();
|
||||
|
||||
// Save file info for back to position.
|
||||
m_findFile = file;
|
||||
m_findFileRow = row;
|
||||
m_findFileColumn = column;
|
||||
m_findFileSrollOffset = scrollOffset;
|
||||
|
@ -119,12 +117,16 @@ void FindBar::findCancel() {
|
|||
}
|
||||
|
||||
void FindBar::handleContentChanged() {
|
||||
updateSearchKeyword(m_findFile, m_editLine->lineEdit()->text());
|
||||
updateSearchKeyword(m_editLine->lineEdit()->text().trimmed());
|
||||
}
|
||||
|
||||
void FindBar::handleFindPrev() { findPrev(m_editLine->lineEdit()->text()); }
|
||||
void FindBar::handleFindPrev() {
|
||||
findPrev(m_editLine->lineEdit()->text().trimmed());
|
||||
}
|
||||
|
||||
void FindBar::handleFindNext() { findNext(m_editLine->lineEdit()->text()); }
|
||||
void FindBar::handleFindNext() {
|
||||
findNext(m_editLine->lineEdit()->text().trimmed());
|
||||
}
|
||||
|
||||
void FindBar::hideEvent(QHideEvent *) {
|
||||
//保留查询标记
|
||||
|
@ -179,7 +181,7 @@ void FindBar::setSearched(bool _) { searched = _; }
|
|||
|
||||
void FindBar::findPreClicked() {
|
||||
if (!searched) {
|
||||
updateSearchKeyword(m_findFile, m_editLine->lineEdit()->text());
|
||||
updateSearchKeyword(m_editLine->lineEdit()->text());
|
||||
emit findPrev(m_editLine->lineEdit()->text());
|
||||
searched = true;
|
||||
} else {
|
||||
|
|
|
@ -53,8 +53,7 @@ public:
|
|||
bool isFocus();
|
||||
void focus();
|
||||
|
||||
void activeInput(QString text, QString file, int row, int column,
|
||||
int scrollOffset);
|
||||
void activeInput(QString text, int row, int column, int scrollOffset);
|
||||
void setMismatchAlert(bool isAlert);
|
||||
void receiveText(QString t);
|
||||
void setSearched(bool _);
|
||||
|
@ -66,7 +65,7 @@ signals:
|
|||
void findPrev(const QString &keyword);
|
||||
|
||||
void removeSearchKeyword();
|
||||
void updateSearchKeyword(QString file, QString keyword);
|
||||
void updateSearchKeyword(QString keyword);
|
||||
|
||||
// add guoshao
|
||||
void sigFindbarClose();
|
||||
|
@ -89,7 +88,6 @@ private:
|
|||
LineBar *m_editLine;
|
||||
QHBoxLayout *m_layout;
|
||||
QLabel *m_findLabel;
|
||||
QString m_findFile;
|
||||
int m_findFileColumn;
|
||||
int m_findFileRow;
|
||||
int m_findFileSrollOffset;
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
|
@ -0,0 +1,120 @@
|
|||
/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*-
|
||||
* -*- coding: utf-8 -*-
|
||||
*
|
||||
* Copyright (C) 2011 ~ 2018 Deepin, Inc.
|
||||
*
|
||||
* Author: Wang Yong <wangyong@deepin.com>
|
||||
* Maintainer: Rekols <rekols@foxmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "jumplinebar.h"
|
||||
#include "dthememanager.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
JumpLineBar::JumpLineBar(DFloatingWidget *parent) : DFloatingWidget(parent) {
|
||||
// Init.
|
||||
setFixedSize(nJumpLineBarWidth, nJumpLineBarHeight);
|
||||
|
||||
// Init layout and widgets.
|
||||
m_layout = new QHBoxLayout();
|
||||
m_layout->setContentsMargins(10, 6, 10, 6);
|
||||
m_layout->setSpacing(0);
|
||||
|
||||
m_label = new QLabel();
|
||||
m_label->setText(tr("Go to Line: "));
|
||||
m_editLine = new LineBar();
|
||||
|
||||
m_lineValidator = new QIntValidator;
|
||||
m_editLine->lineEdit()->setValidator(m_lineValidator);
|
||||
|
||||
m_layout->addWidget(m_label);
|
||||
m_layout->addWidget(m_editLine);
|
||||
this->setLayout(m_layout);
|
||||
|
||||
connect(this, &JumpLineBar::pressEsc, this, &JumpLineBar::jumpCancel,
|
||||
Qt::QueuedConnection);
|
||||
connect(m_editLine, &LineBar::returnPressed, this, &JumpLineBar::jumpConfirm,
|
||||
Qt::QueuedConnection);
|
||||
connect(m_editLine, &LineBar::textChanged, this,
|
||||
&JumpLineBar::handleLineChanged, Qt::QueuedConnection);
|
||||
connect(m_editLine, &LineBar::focusOut, this, &JumpLineBar::handleFocusOut,
|
||||
Qt::QueuedConnection);
|
||||
connect(m_editLine, &LineBar::focusChanged, this,
|
||||
&JumpLineBar::slotFocusChanged, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void JumpLineBar::focus() { m_editLine->lineEdit()->setFocus(); }
|
||||
|
||||
bool JumpLineBar::isFocus() { return m_editLine->lineEdit()->hasFocus(); }
|
||||
|
||||
void JumpLineBar::activeInput(int row, int column, int lineCount,
|
||||
int scrollOffset) {
|
||||
// Save file info for back to line.
|
||||
m_rowBeforeJump = row;
|
||||
m_columnBeforeJump = column;
|
||||
m_jumpFileScrollOffset = scrollOffset;
|
||||
m_lineValidator->setRange(1, lineCount);
|
||||
setFixedSize(nJumpLineBarWidth + QString::number(lineCount).size() *
|
||||
fontMetrics().horizontalAdvance('9'),
|
||||
nJumpLineBarHeight);
|
||||
|
||||
// Clear line number.
|
||||
if (m_editLine->lineEdit()->text().toInt() > lineCount)
|
||||
m_editLine->lineEdit()->setText("");
|
||||
|
||||
// Show jump line bar.
|
||||
// show();
|
||||
// raise();
|
||||
|
||||
// // Focus default.
|
||||
// m_editLine->lineEdit()->setFocus();
|
||||
}
|
||||
|
||||
void JumpLineBar::handleFocusOut() {
|
||||
hide();
|
||||
|
||||
lostFocusExit();
|
||||
}
|
||||
|
||||
void JumpLineBar::handleLineChanged() {
|
||||
QString content = m_editLine->lineEdit()->text();
|
||||
if (content != "") {
|
||||
jumpToLine(content.toInt(), false);
|
||||
}
|
||||
}
|
||||
|
||||
void JumpLineBar::jumpCancel() {
|
||||
hide();
|
||||
// esc键不跳转 返回当前
|
||||
// backToPosition(m_jumpFile, m_rowBeforeJump, m_columnBeforeJump,
|
||||
// m_jumpFileScrollOffset);
|
||||
}
|
||||
|
||||
void JumpLineBar::jumpConfirm() {
|
||||
QString content = m_editLine->lineEdit()->text();
|
||||
if (content != "") {
|
||||
jumpToLine(content.toInt(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void JumpLineBar::slotFocusChanged(bool bFocus) {
|
||||
if (bFocus == false) {
|
||||
// hide();
|
||||
|
||||
lostFocusExit();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*-
|
||||
* -*- coding: utf-8 -*-
|
||||
*
|
||||
* Copyright (C) 2011 ~ 2018 Deepin, Inc.
|
||||
*
|
||||
* Author: Wang Yong <wangyong@deepin.com>
|
||||
* Maintainer: Rekols <rekols@foxmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef JUMPLINEBAR_H
|
||||
#define JUMPLINEBAR_H
|
||||
|
||||
#include "linebar.h"
|
||||
|
||||
#include <DApplicationHelper>
|
||||
#include <DFloatingWidget>
|
||||
#include <QHBoxLayout>
|
||||
#include <QIntValidator>
|
||||
#include <QLabel>
|
||||
#include <QPainter>
|
||||
#include <QWidget>
|
||||
|
||||
DWIDGET_USE_NAMESPACE
|
||||
|
||||
const int nJumpLineBarWidth = 212;
|
||||
const int nJumpLineBarHeight = 60;
|
||||
|
||||
class JumpLineBar : public DFloatingWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit JumpLineBar(DFloatingWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void focus();
|
||||
bool isFocus();
|
||||
|
||||
void activeInput(int row, int column, int lineCount, int scrollOffset);
|
||||
|
||||
void handleFocusOut();
|
||||
void handleLineChanged();
|
||||
|
||||
void jumpCancel();
|
||||
void jumpConfirm();
|
||||
|
||||
void slotFocusChanged(bool bFocus);
|
||||
|
||||
signals:
|
||||
void backToPosition(int row, int column, int scrollOffset);
|
||||
void jumpToLine(int line, bool focusEditor);
|
||||
void lostFocusExit();
|
||||
void pressEsc();
|
||||
|
||||
protected:
|
||||
private:
|
||||
LineBar *m_editLine;
|
||||
QHBoxLayout *m_layout;
|
||||
QIntValidator *m_lineValidator;
|
||||
QLabel *m_label;
|
||||
int m_jumpFileScrollOffset;
|
||||
int m_rowBeforeJump;
|
||||
int m_columnBeforeJump;
|
||||
QColor m_backgroundColor;
|
||||
};
|
||||
|
||||
#endif
|
35
linebar.h
35
linebar.h
|
@ -29,34 +29,33 @@
|
|||
|
||||
DWIDGET_USE_NAMESPACE
|
||||
|
||||
class LineBar : public DLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
class LineBar : public DLineEdit {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LineBar(DLineEdit *parent = 0);
|
||||
explicit LineBar(DLineEdit *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void handleTextChangeTimer();
|
||||
void handleTextChanged();
|
||||
void sendText(QString t);
|
||||
void handleTextChangeTimer();
|
||||
void handleTextChanged();
|
||||
void sendText(QString t);
|
||||
|
||||
signals:
|
||||
void contentChanged();
|
||||
void focusOut();
|
||||
void pressAltEnter();
|
||||
void pressCtrlEnter();
|
||||
void pressEnter();
|
||||
void pressMetaEnter();
|
||||
void signal_sentText(QString t);
|
||||
void contentChanged();
|
||||
void focusOut();
|
||||
void pressAltEnter();
|
||||
void pressCtrlEnter();
|
||||
void pressEnter();
|
||||
void pressMetaEnter();
|
||||
void signal_sentText(QString t);
|
||||
|
||||
protected:
|
||||
virtual void focusOutEvent(QFocusEvent *e);
|
||||
virtual void keyPressEvent(QKeyEvent *e);
|
||||
virtual void focusOutEvent(QFocusEvent *e);
|
||||
virtual void keyPressEvent(QKeyEvent *e);
|
||||
|
||||
private:
|
||||
QTimer *m_autoSaveTimer;
|
||||
int m_autoSaveInternal;
|
||||
QTimer *m_autoSaveTimer;
|
||||
int m_autoSaveInternal;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "plginterface.h"
|
||||
#include "PythonQt/PythonQtCppWrapperFactory.h"
|
||||
#include <QKeySequence>
|
||||
#include <QListWidgetItem>
|
||||
#include <QShortcut>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
|
@ -9,12 +10,17 @@ PlgInterface *PlgInterface::m_instace = nullptr;
|
|||
bool PlgInterface::init() {
|
||||
PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
|
||||
auto py = PythonQt::self();
|
||||
py->addDecorators(new PyInfoDecorators(this));
|
||||
py->registerClass(&QListWidget::staticMetaObject, "QtGui");
|
||||
py->registerClass(&QTableWidget::staticMetaObject, "QtGui");
|
||||
py->registerClass(&QTreeWidget::staticMetaObject, "QtGui");
|
||||
py->registerCPPClass("plgreader", nullptr, "wingplg",
|
||||
PythonQtCreateObject<WingPlugin::Reader>);
|
||||
py->registerCPPClass("plgcontroller", nullptr, "wingplg",
|
||||
PythonQtCreateObject<WingPlugin::Controller>);
|
||||
py->registerCPPClass("plgservice", nullptr, "wingplg",
|
||||
PythonQtCreateObject<PlgService>);
|
||||
|
||||
qRegisterMetaType<HexPosition>("hexposition");
|
||||
qRegisterMetaType<BookMark>("bookmark");
|
||||
qRegisterMetaType<ErrFile>("errfile");
|
||||
|
@ -27,8 +33,8 @@ bool PlgInterface::init() {
|
|||
mainContext.addObject("reader", &plg->reader);
|
||||
mainContext.addObject("controller", &plg->controller);
|
||||
mainContext.addObject("service", new PlgService(this));
|
||||
mainContext.evalScript(
|
||||
"from PythonQt import *\nfrom PythonQt import wingplg");
|
||||
|
||||
mainContext.evalScript("from PythonQt import *");
|
||||
console = new PythonQtScriptingConsole(nullptr, mainContext);
|
||||
m_instace = this;
|
||||
auto shortcut = new QShortcut(
|
||||
|
@ -37,14 +43,31 @@ bool PlgInterface::init() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void PlgInterface::initInfo(QListWidget *infolist, QTreeWidget *infotree,
|
||||
QTableWidget *infotable) {
|
||||
mainContext.addObject("infotree", infotree);
|
||||
mainContext.addObject("infotable", infotable);
|
||||
mainContext.addObject("infolist", infolist);
|
||||
}
|
||||
|
||||
PythonQtScriptingConsole *PlgInterface::getScriptingConsole() {
|
||||
return console;
|
||||
}
|
||||
|
||||
void PlgInterface::RunPyFile(QString filename) {
|
||||
mainContext.evalFile(filename);
|
||||
if (plg->hasControl())
|
||||
plg->requestRelease();
|
||||
bool PlgInterface::RunPyFile(QString filename) {
|
||||
if (mutex.tryLock()) {
|
||||
auto cur = console->textCursor();
|
||||
cur.movePosition(QTextCursor::End);
|
||||
console->setTextCursor(cur);
|
||||
console->insertPlainText(filename);
|
||||
mainContext.evalFile(filename);
|
||||
console->appendCommandPrompt();
|
||||
if (plg->hasControl())
|
||||
plg->requestRelease();
|
||||
mutex.unlock();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlgInterface::requestControl(int timeout) {
|
||||
|
@ -53,10 +76,20 @@ bool PlgInterface::requestControl(int timeout) {
|
|||
|
||||
bool PlgInterface::requestRelease() { return plg->requestRelease(); }
|
||||
|
||||
void PlgInterface::RunPyText(QString content) {
|
||||
mainContext.evalScript(content);
|
||||
if (plg->hasControl())
|
||||
plg->requestRelease();
|
||||
bool PlgInterface::RunPyText(QString content) {
|
||||
if (mutex.tryLock()) {
|
||||
auto cur = console->textCursor();
|
||||
cur.movePosition(QTextCursor::End);
|
||||
console->setTextCursor(cur);
|
||||
console->insertPlainText(tr("[ExcuteFromScriptWindow]"));
|
||||
mainContext.evalScript(content);
|
||||
console->appendCommandPrompt();
|
||||
if (plg->hasControl())
|
||||
plg->requestRelease();
|
||||
mutex.unlock();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PlgInterface::PlgInterface(IWingPlugin *parent) : QObject(parent) {
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
#include "plginterface.h"
|
||||
#include "PythonQt/PythonQtCppWrapperFactory.h"
|
||||
#include <QKeySequence>
|
||||
#include <QListWidgetItem>
|
||||
#include <QShortcut>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
PlgInterface *PlgInterface::m_instace = nullptr;
|
||||
|
||||
bool PlgInterface::init() {
|
||||
PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
|
||||
auto py = PythonQt::self();
|
||||
py->registerClass(&QListWidget::staticMetaObject, "QtGui");
|
||||
py->registerClass(&QTableWidget::staticMetaObject, "QtGui");
|
||||
py->registerClass(&QTreeWidget::staticMetaObject, "QtGui");
|
||||
py->registerCPPClass("plgreader", nullptr, "wingplg",
|
||||
PythonQtCreateObject<WingPlugin::Reader>);
|
||||
py->registerCPPClass("plgcontroller", nullptr, "wingplg",
|
||||
PythonQtCreateObject<WingPlugin::Controller>);
|
||||
py->registerCPPClass("plgservice", nullptr, "wingplg",
|
||||
PythonQtCreateObject<PlgService>);
|
||||
|
||||
qRegisterMetaType<HexPosition>("hexposition");
|
||||
qRegisterMetaType<BookMark>("bookmark");
|
||||
qRegisterMetaType<ErrFile>("errfile");
|
||||
qRegisterMetaType<FindResult>("findresult");
|
||||
qRegisterMetaType<HexMetadataAbsoluteItem>("absmetadata");
|
||||
qRegisterMetaType<HexMetadataItem>("metadata");
|
||||
qRegisterMetaType<HexLineMetadata>("linematadata");
|
||||
|
||||
mainContext = PythonQt::self()->getMainModule();
|
||||
mainContext.addObject("reader", &plg->reader);
|
||||
mainContext.addObject("controller", &plg->controller);
|
||||
mainContext.addObject("service", new PlgService(this));
|
||||
|
||||
mainContext.evalScript("from PythonQt import *");
|
||||
console = new PythonQtScriptingConsole(nullptr, mainContext);
|
||||
m_instace = this;
|
||||
auto shortcut = new QShortcut(
|
||||
QKeySequence(Qt::KeyboardModifier::ControlModifier | Qt::Key_L), console);
|
||||
connect(shortcut, &QShortcut::activated, this, [=] { console->clear(); });
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlgInterface::initInfo(QListWidget *infolist, QTreeWidget *infotree,
|
||||
QTableWidget *infotable) {
|
||||
mainContext.addObject("infotree", infotree);
|
||||
mainContext.addObject("infotable", infotable);
|
||||
mainContext.addObject("infolist", infolist);
|
||||
}
|
||||
|
||||
PythonQtScriptingConsole *PlgInterface::getScriptingConsole() {
|
||||
return console;
|
||||
}
|
||||
|
||||
bool PlgInterface::RunPyFile(QString filename) {
|
||||
if (mutex.tryLock()) {
|
||||
auto cur = console->textCursor();
|
||||
cur.movePosition(QTextCursor::End);
|
||||
console->setTextCursor(cur);
|
||||
console->insertPlainText(filename);
|
||||
mainContext.evalFile(filename);
|
||||
console->appendCommandPrompt();
|
||||
if (plg->hasControl())
|
||||
plg->requestRelease();
|
||||
mutex.unlock();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlgInterface::requestControl(int timeout) {
|
||||
return plg->requestControl(timeout);
|
||||
}
|
||||
|
||||
bool PlgInterface::requestRelease() { return plg->requestRelease(); }
|
||||
|
||||
bool PlgInterface::RunPyText(QString content) {
|
||||
if (mutex.tryLock()) {
|
||||
auto cur = console->textCursor();
|
||||
cur.movePosition(QTextCursor::End);
|
||||
console->setTextCursor(cur);
|
||||
console->insertPlainText(tr("[ExcuteFromScriptWindow]"));
|
||||
mainContext.evalScript(content);
|
||||
console->appendCommandPrompt();
|
||||
if (plg->hasControl())
|
||||
plg->requestRelease();
|
||||
mutex.unlock();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PlgInterface::PlgInterface(IWingPlugin *parent) : QObject(parent) {
|
||||
plg = parent;
|
||||
}
|
||||
|
||||
PlgInterface *PlgInterface::instance() { return m_instace; }
|
|
@ -6,11 +6,15 @@
|
|||
#include "../WingHexExplorer/wing-hex-explorer.sourcecode/WingHexExplorer/plugin/iwingplugin.h"
|
||||
#include "PythonQt/PythonQt.h"
|
||||
#include "PythonQt/gui/PythonQtScriptingConsole.h"
|
||||
#include <QListWidget>
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
#include <QTableWidget>
|
||||
#include <QTreeWidget>
|
||||
|
||||
#define INFOLOG(msg) "<font color=\"green\">" + msg + "</font>"
|
||||
#define ERRLOG(msg) "<font color=\"red\">" + msg + "</font>"
|
||||
#define WARNLOG(msg) "<font color=\"yellow\">" + msg + "</font>"
|
||||
#define WARNLOG(msg) "<font color=\"gold\">" + msg + "</font>"
|
||||
|
||||
class PlgInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -22,9 +26,11 @@ signals:
|
|||
|
||||
public:
|
||||
bool init();
|
||||
void initInfo(QListWidget *infolist, QTreeWidget *infotree,
|
||||
QTableWidget *infotable);
|
||||
PythonQtScriptingConsole *getScriptingConsole();
|
||||
void RunPyFile(QString filename);
|
||||
void RunPyText(QString content);
|
||||
bool RunPyFile(QString filename);
|
||||
bool RunPyText(QString content);
|
||||
bool requestControl(int timeout = 1500);
|
||||
bool requestRelease();
|
||||
|
||||
|
@ -36,6 +42,8 @@ private:
|
|||
PythonQtObjectPtr mainContext;
|
||||
PythonQtScriptingConsole *console;
|
||||
|
||||
QMutex mutex;
|
||||
|
||||
private:
|
||||
static PlgInterface *m_instace;
|
||||
};
|
||||
|
@ -61,4 +69,81 @@ private:
|
|||
PlgInterface *inter;
|
||||
};
|
||||
|
||||
class InfoListWrapper : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
InfoListWrapper() {}
|
||||
InfoListWrapper(QListWidget *list) : m_list(list) {}
|
||||
|
||||
void addItem(QString content) { m_list.addItem(content); }
|
||||
void addIconItem(QIcon icon, QString content) {
|
||||
m_list.addItem(new QListWidgetItem(icon, content));
|
||||
}
|
||||
void clear() { m_list.clear(); }
|
||||
void insertItem(int index, QString content) {
|
||||
m_list.insertItem(index, content);
|
||||
}
|
||||
void insertIconItem(int index, QIcon icon, QString content) {
|
||||
m_list.insertItem(index, new QListWidgetItem(icon, content));
|
||||
}
|
||||
void removeAt(int index) {
|
||||
auto item = m_list.item(index);
|
||||
m_list.removeItemWidget(item);
|
||||
delete item;
|
||||
}
|
||||
|
||||
private:
|
||||
QListWidget m_list;
|
||||
};
|
||||
|
||||
class InfoTableWrapper : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
InfoTableWrapper() {}
|
||||
InfoTableWrapper(QTableWidget *table) : m_table(table) {}
|
||||
|
||||
void setColumnCount(int count) { m_table->setColumnCount(count); }
|
||||
void setRowCount(int count) { m_table->setRowCount(count); }
|
||||
void setRowHeight(int row, int height) { m_table->setRowHeight(row, height); }
|
||||
void setColumnWidth(int col, int width) {
|
||||
m_table->setColumnWidth(col, width);
|
||||
}
|
||||
void clear() { m_table->clear(); }
|
||||
void clearContents() { m_table->clearContents(); }
|
||||
void setItem(int row, int col, QString content) {
|
||||
m_table->setItem(row, col, new QTableWidgetItem(content));
|
||||
}
|
||||
void setIconItem(int row, int col, QIcon icon, QString content) {
|
||||
m_table->setItem(row, col, new QTableWidgetItem(icon, content));
|
||||
}
|
||||
void hideRow(int row) { m_table->hideRow(row); }
|
||||
void hideCol(int col) { m_table->hideColumn(col); }
|
||||
void setHorizontalHeaderLabels(QStringList lbls) {
|
||||
m_table->setHorizontalHeaderLabels(lbls);
|
||||
}
|
||||
void setVerticalHeaderLabels(QStringList lbls) {
|
||||
m_table->setVerticalHeaderLabels(lbls);
|
||||
}
|
||||
void setHorizontalHeaderLabel(int index, QString lbl) {
|
||||
m_table->setHorizontalHeaderItem(index, new QTableWidgetItem(lbl));
|
||||
}
|
||||
void setVerticalHeaderLabel(int index, QString lbl) {
|
||||
m_table->setVerticalHeaderItem(index, new QTableWidgetItem(lbl));
|
||||
}
|
||||
void setCurrentCell(int row, int col) { m_table->setCurrentCell(row, col); }
|
||||
|
||||
private:
|
||||
QTableWidget *m_table;
|
||||
};
|
||||
|
||||
class InfoTreeWrapper : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
InfoTreeWrapper() {}
|
||||
InfoTreeWrapper(QTreeWidget *tree) : m_tree(tree) {}
|
||||
|
||||
private:
|
||||
QTreeWidget *m_tree;
|
||||
};
|
||||
|
||||
#endif // PLGINTERFACE_H
|
||||
|
|
|
@ -45,9 +45,6 @@ ReplaceBar::ReplaceBar(QWidget *parent) : DFloatingWidget(parent) {
|
|||
// m_replaceButton->setMinimumWidth(66);
|
||||
// m_replaceButton->setMinimumHeight(36);
|
||||
m_replaceSkipButton = new QPushButton(tr("Skip"));
|
||||
// m_replaceSkipButton->setMinimumWidth(66);
|
||||
// m_replaceSkipButton->setMinimumHeight(36);
|
||||
m_replaceRestButton = new QPushButton(tr("Replace Rest"));
|
||||
// m_replaceRestButton->setMinimumWidth(80);
|
||||
// m_replaceRestButton->setMinimumHeight(36);
|
||||
m_replaceAllButton = new QPushButton(tr("Replace All"));
|
||||
|
@ -65,7 +62,6 @@ ReplaceBar::ReplaceBar(QWidget *parent) : DFloatingWidget(parent) {
|
|||
m_layout->addWidget(m_withLine);
|
||||
m_layout->addWidget(m_replaceButton);
|
||||
m_layout->addWidget(m_replaceSkipButton);
|
||||
m_layout->addWidget(m_replaceRestButton);
|
||||
m_layout->addWidget(m_replaceAllButton);
|
||||
m_layout->addWidget(m_closeButton);
|
||||
this->setLayout(m_layout);
|
||||
|
@ -90,17 +86,10 @@ ReplaceBar::ReplaceBar(QWidget *parent) : DFloatingWidget(parent) {
|
|||
connect(m_withLine, &LineBar::returnPressed, this,
|
||||
&ReplaceBar::handleReplaceNext, Qt::QueuedConnection);
|
||||
|
||||
connect(m_replaceLine, &LineBar::pressCtrlEnter, this, [=]() {
|
||||
emit replaceSkip(m_replaceFile, m_replaceLine->lineEdit()->text());
|
||||
});
|
||||
connect(m_withLine, &LineBar::pressCtrlEnter, this, [=]() {
|
||||
emit replaceSkip(m_replaceFile, m_replaceLine->lineEdit()->text());
|
||||
});
|
||||
|
||||
connect(m_replaceLine, &LineBar::pressAltEnter, this,
|
||||
&ReplaceBar::handleReplaceRest, Qt::QueuedConnection);
|
||||
connect(m_withLine, &LineBar::pressAltEnter, this,
|
||||
&ReplaceBar::handleReplaceRest, Qt::QueuedConnection);
|
||||
connect(m_replaceLine, &LineBar::pressCtrlEnter, this,
|
||||
[=]() { emit replaceSkip(m_replaceLine->lineEdit()->text()); });
|
||||
connect(m_withLine, &LineBar::pressCtrlEnter, this,
|
||||
[=]() { emit replaceSkip(m_replaceLine->lineEdit()->text()); });
|
||||
|
||||
connect(m_replaceLine, &LineBar::pressMetaEnter, this,
|
||||
&ReplaceBar::handleReplaceAll, Qt::QueuedConnection);
|
||||
|
@ -112,11 +101,8 @@ ReplaceBar::ReplaceBar(QWidget *parent) : DFloatingWidget(parent) {
|
|||
|
||||
connect(m_replaceButton, &QPushButton::clicked, this,
|
||||
&ReplaceBar::handleReplaceNext, Qt::QueuedConnection);
|
||||
connect(m_replaceSkipButton, &QPushButton::clicked, this, [=]() {
|
||||
emit replaceSkip(m_replaceFile, m_replaceLine->lineEdit()->text());
|
||||
});
|
||||
connect(m_replaceRestButton, &QPushButton::clicked, this,
|
||||
&ReplaceBar::handleReplaceRest, Qt::QueuedConnection);
|
||||
connect(m_replaceSkipButton, &QPushButton::clicked, this,
|
||||
[=]() { emit replaceSkip(m_replaceLine->lineEdit()->text()); });
|
||||
connect(m_replaceAllButton, &QPushButton::clicked, this,
|
||||
&ReplaceBar::handleReplaceAll, Qt::QueuedConnection);
|
||||
|
||||
|
@ -128,7 +114,7 @@ bool ReplaceBar::isFocus() { return m_replaceLine->hasFocus(); }
|
|||
|
||||
void ReplaceBar::focus() { m_replaceLine->lineEdit()->setFocus(); }
|
||||
|
||||
void ReplaceBar::activeInput(QString text, QString file, int row, int column,
|
||||
void ReplaceBar::activeInput(QString text, int row, int column,
|
||||
int scrollOffset) {
|
||||
// Try fill keyword with select text.
|
||||
m_withLine->lineEdit()->clear();
|
||||
|
@ -140,7 +126,6 @@ void ReplaceBar::activeInput(QString text, QString file, int row, int column,
|
|||
show();
|
||||
|
||||
// Save file info for back to position.
|
||||
m_replaceFile = file;
|
||||
m_replaceFileRow = row;
|
||||
m_replaceFileColumn = column;
|
||||
m_replaceFileSrollOffset = scrollOffset;
|
||||
|
@ -156,24 +141,18 @@ void ReplaceBar::replaceClose() {
|
|||
}
|
||||
|
||||
void ReplaceBar::handleContentChanged() {
|
||||
updateSearchKeyword(m_replaceFile, m_replaceLine->lineEdit()->text());
|
||||
updateSearchKeyword(m_replaceLine->lineEdit()->text());
|
||||
}
|
||||
|
||||
void ReplaceBar::handleReplaceNext() {
|
||||
if (!searched) {
|
||||
emit removeSearchKeyword();
|
||||
emit beforeReplace(m_replaceLine->lineEdit()->text());
|
||||
}
|
||||
replaceNext(m_replaceFile, m_replaceLine->lineEdit()->text(),
|
||||
replaceNext(m_replaceLine->lineEdit()->text(),
|
||||
m_withLine->lineEdit()->text());
|
||||
searched = true;
|
||||
}
|
||||
|
||||
void ReplaceBar::handleReplaceRest() {
|
||||
replaceRest(m_replaceLine->lineEdit()->text(),
|
||||
m_withLine->lineEdit()->text());
|
||||
}
|
||||
|
||||
void ReplaceBar::handleReplaceAll() {
|
||||
replaceAll(m_replaceLine->lineEdit()->text(), m_withLine->lineEdit()->text());
|
||||
}
|
||||
|
@ -221,9 +200,6 @@ void ReplaceBar::keyPressEvent(QKeyEvent *e) {
|
|||
if (m_replaceButton->hasFocus()) {
|
||||
m_replaceButton->click();
|
||||
}
|
||||
if (m_replaceRestButton->hasFocus()) {
|
||||
m_replaceRestButton->click();
|
||||
}
|
||||
if (m_replaceSkipButton->hasFocus()) {
|
||||
m_replaceSkipButton->click();
|
||||
}
|
||||
|
|
17
replacebar.h
17
replacebar.h
|
@ -46,23 +46,19 @@ public:
|
|||
bool isFocus();
|
||||
void focus();
|
||||
|
||||
void activeInput(QString text, QString file, int row, int column,
|
||||
int scrollOffset);
|
||||
void activeInput(QString text, int row, int column, int scrollOffset);
|
||||
void setMismatchAlert(bool isAlert);
|
||||
void setsearched(bool _);
|
||||
|
||||
signals:
|
||||
void pressEsc();
|
||||
void replaceNext(QString file, QString replaceText, QString withText);
|
||||
void replaceSkip(QString file, QString keyword);
|
||||
void replaceRest(QString replaceText, QString withText);
|
||||
void replaceNext(QString replaceText, QString withText);
|
||||
void replaceSkip(QString keyword);
|
||||
void replaceAll(QString replaceText, QString withText);
|
||||
void beforeReplace(QString _);
|
||||
|
||||
void backToPosition(QString file, int row, int column, int scrollOffset);
|
||||
void backToPosition(int row, int column, int scrollOffset);
|
||||
|
||||
void removeSearchKeyword();
|
||||
void updateSearchKeyword(QString file, QString keyword);
|
||||
void updateSearchKeyword(QString keyword);
|
||||
|
||||
void sigReplacebarClose();
|
||||
|
||||
|
@ -72,7 +68,6 @@ public slots:
|
|||
void handleContentChanged();
|
||||
void handleReplaceAll();
|
||||
void handleReplaceNext();
|
||||
void handleReplaceRest();
|
||||
|
||||
protected:
|
||||
void hideEvent(QHideEvent *event);
|
||||
|
@ -82,7 +77,6 @@ protected:
|
|||
private:
|
||||
QPushButton *m_replaceAllButton;
|
||||
QPushButton *m_replaceButton;
|
||||
QPushButton *m_replaceRestButton;
|
||||
QPushButton *m_replaceSkipButton;
|
||||
DIconButton *m_closeButton;
|
||||
LineBar *m_replaceLine;
|
||||
|
@ -90,7 +84,6 @@ private:
|
|||
QHBoxLayout *m_layout;
|
||||
QLabel *m_replaceLabel;
|
||||
QLabel *m_withLabel;
|
||||
QString m_replaceFile;
|
||||
int m_replaceFileColumn;
|
||||
int m_replaceFileRow;
|
||||
int m_replaceFileSrollOffset;
|
||||
|
|
|
@ -30,5 +30,6 @@
|
|||
<file>img/replace.png</file>
|
||||
<file>sponsor.png</file>
|
||||
<file>img/README.md</file>
|
||||
<file>img/infolist.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
243
scriptwindow.cpp
243
scriptwindow.cpp
|
@ -5,9 +5,15 @@
|
|||
#include "plginterface.h"
|
||||
#include "sponsordialog.h"
|
||||
#include <DFileDialog>
|
||||
#include <DMessageManager>
|
||||
#include <DTitlebar>
|
||||
#include <DWidgetUtil>
|
||||
#include <Python.h>
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QScrollBar>
|
||||
#include <QShortcut>
|
||||
#include <QTextDocumentFragment>
|
||||
|
||||
#define ICONRES(name) QIcon(":/img/" name ".png")
|
||||
|
||||
|
@ -24,7 +30,7 @@ ScriptWindow::ScriptWindow(DMainWindow *parent) : DMainWindow(parent) {
|
|||
setMinimumSize(QSize(800, 600));
|
||||
|
||||
auto _title = titlebar();
|
||||
auto picon = ICONRES("pys");
|
||||
picon = ICONRES("pys");
|
||||
setWindowIcon(picon);
|
||||
_title->setIcon(picon);
|
||||
_title->setTitle(tr("WingHexPyScriptWindow"));
|
||||
|
@ -55,6 +61,10 @@ ScriptWindow::ScriptWindow(DMainWindow *parent) : DMainWindow(parent) {
|
|||
|
||||
vlayout->addWidget(editor);
|
||||
|
||||
auto scrun = QKeySequence(Qt::Key_F5);
|
||||
auto scrunf =
|
||||
QKeySequence(Qt::KeyboardModifier::ControlModifier | Qt::Key_F5);
|
||||
|
||||
PluginMenuInitBegin(menu, "") {
|
||||
Q_UNUSED(a);
|
||||
QMenu *m;
|
||||
|
@ -62,12 +72,20 @@ ScriptWindow::ScriptWindow(DMainWindow *parent) : DMainWindow(parent) {
|
|||
m->setIcon(ICONRES("file"));
|
||||
PluginMenuAddItemIconAction(m, tr("New"), ICONRES("new"),
|
||||
ScriptWindow::on_new);
|
||||
a->setShortcut(QKeySequence::New);
|
||||
a->setShortcutVisibleInContextMenu(true);
|
||||
PluginMenuAddItemIconAction(m, tr("Open"), ICONRES("open"),
|
||||
ScriptWindow::on_open);
|
||||
a->setShortcut(QKeySequence::Open);
|
||||
a->setShortcutVisibleInContextMenu(true);
|
||||
PluginMenuAddItemIconAction(m, tr("Save"), ICONRES("save"),
|
||||
ScriptWindow::on_save);
|
||||
a->setShortcut(QKeySequence::Save);
|
||||
a->setShortcutVisibleInContextMenu(true);
|
||||
PluginMenuAddItemIconAction(m, tr("SaveAs"), ICONRES("saveas"),
|
||||
ScriptWindow::on_saveas);
|
||||
a->setShortcut(QKeySequence::SaveAs);
|
||||
a->setShortcutVisibleInContextMenu(true);
|
||||
auto rm = new QMenu(menu);
|
||||
rm->setTitle(tr("RecentFile"));
|
||||
recentmanager = new RecentFileManager(rm, this);
|
||||
|
@ -83,24 +101,38 @@ ScriptWindow::ScriptWindow(DMainWindow *parent) : DMainWindow(parent) {
|
|||
m->setIcon(ICONRES("edit"));
|
||||
PluginMenuAddItemIconAction(m, tr("Undo"), ICONRES("undo"),
|
||||
ScriptWindow::on_undo);
|
||||
a->setShortcut(QKeySequence::Undo);
|
||||
a->setShortcutVisibleInContextMenu(true);
|
||||
a->setEnabled(false);
|
||||
mundo = a;
|
||||
PluginMenuAddItemIconAction(m, tr("Redo"), ICONRES("redo"),
|
||||
ScriptWindow::on_redo);
|
||||
a->setShortcut(QKeySequence::Redo);
|
||||
a->setShortcutVisibleInContextMenu(true);
|
||||
a->setEnabled(false);
|
||||
mredo = a;
|
||||
m->addSeparator();
|
||||
PluginMenuAddItemIconAction(m, tr("Cut"), ICONRES("cut"),
|
||||
ScriptWindow::on_cut);
|
||||
a->setShortcut(QKeySequence::Cut);
|
||||
a->setShortcutVisibleInContextMenu(true);
|
||||
PluginMenuAddItemIconAction(m, tr("Copy"), ICONRES("copy"),
|
||||
ScriptWindow::on_copy);
|
||||
a->setShortcut(QKeySequence::Copy);
|
||||
a->setShortcutVisibleInContextMenu(true);
|
||||
PluginMenuAddItemIconAction(m, tr("Paste"), ICONRES("paste"),
|
||||
ScriptWindow::on_paste);
|
||||
a->setShortcut(QKeySequence::Paste);
|
||||
a->setShortcutVisibleInContextMenu(true);
|
||||
m->addSeparator();
|
||||
PluginMenuAddItemIconAction(m, tr("Find"), ICONRES("find"),
|
||||
ScriptWindow::on_find);
|
||||
a->setShortcut(QKeySequence::Find);
|
||||
a->setShortcutVisibleInContextMenu(true);
|
||||
PluginMenuAddItemIconAction(m, tr("Replace"), ICONRES("replace"),
|
||||
ScriptWindow::on_replace);
|
||||
a->setShortcut(QKeySequence::Replace);
|
||||
a->setShortcutVisibleInContextMenu(true);
|
||||
}
|
||||
PluginMenuInitEnd();
|
||||
menu->addMenu(m);
|
||||
|
@ -108,8 +140,12 @@ ScriptWindow::ScriptWindow(DMainWindow *parent) : DMainWindow(parent) {
|
|||
m->setIcon(ICONRES("icon"));
|
||||
PluginMenuAddItemIconAction(m, tr("Run"), ICONRES("run"),
|
||||
ScriptWindow::on_run);
|
||||
a->setShortcut(scrun);
|
||||
a->setShortcutVisibleInContextMenu(true);
|
||||
PluginMenuAddItemIconAction(m, tr("RunFile"), ICONRES("runf"),
|
||||
ScriptWindow::on_runfile);
|
||||
a->setShortcut(scrunf);
|
||||
a->setShortcutVisibleInContextMenu(true);
|
||||
}
|
||||
PluginMenuInitEnd();
|
||||
menu->addMenu(m);
|
||||
|
@ -187,15 +223,144 @@ ScriptWindow::ScriptWindow(DMainWindow *parent) : DMainWindow(parent) {
|
|||
});
|
||||
|
||||
findbar = new FindBar(this);
|
||||
connect(findbar, &FindBar::findNext, this, [=](const QString &keyword) {
|
||||
if (!editor->find(keyword)) {
|
||||
auto cur = editor->textCursor();
|
||||
cur.movePosition(QTextCursor::Start);
|
||||
editor->setTextCursor(cur);
|
||||
DMessageManager::instance()->sendMessage(this, picon,
|
||||
tr("FindReachTheEnd"));
|
||||
editor->find(keyword);
|
||||
}
|
||||
editor->setFocus();
|
||||
});
|
||||
connect(findbar, &FindBar::findPrev, this, [=](const QString &keyword) {
|
||||
if (!editor->find(keyword, QTextDocument::FindFlag::FindBackward)) {
|
||||
auto cur = editor->textCursor();
|
||||
cur.movePosition(QTextCursor::End);
|
||||
editor->setTextCursor(cur);
|
||||
DMessageManager::instance()->sendMessage(this, picon,
|
||||
tr("FindReachTheStart"));
|
||||
editor->find(keyword, QTextDocument::FindFlag::FindBackward);
|
||||
}
|
||||
editor->setFocus();
|
||||
});
|
||||
connect(findbar, &FindBar::removeSearchKeyword, this, [=] {
|
||||
auto cur = editor->textCursor();
|
||||
cur.clearSelection();
|
||||
editor->setTextCursor(cur);
|
||||
editor->setFocus();
|
||||
});
|
||||
connect(findbar, &FindBar::updateSearchKeyword, this, [=](QString keyword) {
|
||||
if (!editor->find(keyword)) {
|
||||
auto cur = editor->textCursor();
|
||||
cur.movePosition(QTextCursor::Start);
|
||||
editor->setTextCursor(cur);
|
||||
editor->find(keyword);
|
||||
}
|
||||
editor->setFocus();
|
||||
});
|
||||
connect(findbar, &FindBar::sigFindbarClose, this, [=] {
|
||||
auto cur = editor->textCursor();
|
||||
cur.clearSelection();
|
||||
editor->setTextCursor(cur);
|
||||
editor->setFocus();
|
||||
});
|
||||
vlayout->addWidget(findbar);
|
||||
replacebar = new ReplaceBar(this);
|
||||
connect(replacebar, &ReplaceBar::replaceAll, this,
|
||||
[=](QString replaceText, QString withText) {
|
||||
auto cur = editor->textCursor();
|
||||
auto oldpos = cur.position();
|
||||
cur.movePosition(QTextCursor::Start);
|
||||
editor->setTextCursor(cur);
|
||||
cur.beginEditBlock();
|
||||
while (editor->find(replaceText)) {
|
||||
cur = editor->textCursor();
|
||||
cur.removeSelectedText();
|
||||
cur.insertText(withText);
|
||||
}
|
||||
cur.endEditBlock();
|
||||
cur.setPosition(oldpos);
|
||||
editor->setTextCursor(cur);
|
||||
editor->setFocus();
|
||||
});
|
||||
connect(replacebar, &ReplaceBar::replaceNext, this,
|
||||
[=](QString replaceText, QString withText) {
|
||||
auto cur = editor->textCursor();
|
||||
if (cur.selectedText().length()) {
|
||||
cur.beginEditBlock();
|
||||
cur.removeSelectedText();
|
||||
cur.insertText(withText);
|
||||
cur.endEditBlock();
|
||||
}
|
||||
if (!editor->find(replaceText)) {
|
||||
cur.movePosition(QTextCursor::Start);
|
||||
editor->setTextCursor(cur);
|
||||
DMessageManager::instance()->sendMessage(
|
||||
this, picon, tr("ReplaceReachTheStart"));
|
||||
}
|
||||
editor->setFocus();
|
||||
});
|
||||
connect(replacebar, &ReplaceBar::replaceSkip, this, [=](QString keyword) {
|
||||
if (!editor->find(keyword)) {
|
||||
auto cur = editor->textCursor();
|
||||
cur.movePosition(QTextCursor::Start);
|
||||
editor->setTextCursor(cur);
|
||||
editor->find(keyword);
|
||||
}
|
||||
editor->setFocus();
|
||||
});
|
||||
connect(replacebar, &ReplaceBar::updateSearchKeyword, this,
|
||||
[=](QString keyword) {
|
||||
if (!editor->find(keyword)) {
|
||||
auto cur = editor->textCursor();
|
||||
cur.movePosition(QTextCursor::Start);
|
||||
editor->setTextCursor(cur);
|
||||
editor->find(keyword);
|
||||
}
|
||||
editor->setFocus();
|
||||
});
|
||||
connect(replacebar, &ReplaceBar::sigReplacebarClose, this, [=] {
|
||||
auto cur = editor->textCursor();
|
||||
cur.clearSelection();
|
||||
editor->setTextCursor(cur);
|
||||
editor->setFocus();
|
||||
});
|
||||
vlayout->addWidget(replacebar);
|
||||
|
||||
connect(editor, &QCodeEditor::textChanged, this, [=] { isSaved = false; });
|
||||
|
||||
QShortcut *s;
|
||||
|
||||
#define ConnectShortCut(ShortCut, Slot) \
|
||||
s = new QShortcut(ShortCut, this); \
|
||||
connect(s, &QShortcut::activated, this, &Slot);
|
||||
|
||||
ConnectShortCut(QKeySequence::Undo, ScriptWindow::on_undo);
|
||||
ConnectShortCut(QKeySequence::Copy, ScriptWindow::on_copy);
|
||||
ConnectShortCut(QKeySequence::Cut, ScriptWindow::on_cut);
|
||||
ConnectShortCut(QKeySequence::Paste, ScriptWindow::on_paste);
|
||||
ConnectShortCut(QKeySequence::Redo, ScriptWindow::on_redo);
|
||||
ConnectShortCut(QKeySequence::Find, ScriptWindow::on_find);
|
||||
ConnectShortCut(QKeySequence::New, ScriptWindow::on_new);
|
||||
ConnectShortCut(QKeySequence::Open, ScriptWindow::on_open);
|
||||
ConnectShortCut(QKeySequence::Save, ScriptWindow::on_save);
|
||||
ConnectShortCut(QKeySequence::SaveAs, ScriptWindow::on_saveas);
|
||||
ConnectShortCut(QKeySequence::Replace, ScriptWindow::on_replace);
|
||||
ConnectShortCut(scrun, ScriptWindow::on_run);
|
||||
ConnectShortCut(scrunf, ScriptWindow::on_runfile);
|
||||
|
||||
QSettings settings(QApplication::organizationName(), "WingHexPy");
|
||||
lastusedpath = settings.value("curpath").toString();
|
||||
|
||||
Dtk::Widget::moveToCenter(this);
|
||||
}
|
||||
|
||||
ScriptWindow::~ScriptWindow() {
|
||||
QSettings settings(QApplication::organizationName(), "WingHexPy");
|
||||
settings.setValue("curpath", lastusedpath);
|
||||
}
|
||||
|
||||
void ScriptWindow::setTheme(DGuiApplicationHelper::ColorType theme) {
|
||||
if (theme == DGuiApplicationHelper::LightType) {
|
||||
editor->setSyntaxStyle(m_styles[0]);
|
||||
|
@ -205,17 +370,62 @@ void ScriptWindow::setTheme(DGuiApplicationHelper::ColorType theme) {
|
|||
}
|
||||
|
||||
void ScriptWindow::on_new() {
|
||||
if (!isSaved) {
|
||||
if (!isSaved && QMessageBox::question(this, tr("CloseConfirm"),
|
||||
tr("NotSaved")) == QMessageBox::No) {
|
||||
return;
|
||||
}
|
||||
editor->clear();
|
||||
currentfilename.clear();
|
||||
}
|
||||
|
||||
void ScriptWindow::on_open() {}
|
||||
void ScriptWindow::on_open() {
|
||||
auto filename =
|
||||
QFileDialog::getOpenFileName(this, tr("ChooseFile"), lastusedpath);
|
||||
if (!filename.isEmpty()) {
|
||||
QFileInfo finfo(filename);
|
||||
lastusedpath = finfo.absoluteDir().absolutePath();
|
||||
QFile f(filename);
|
||||
if (f.open(QFile::ReadOnly)) {
|
||||
editor->setText(f.readAll());
|
||||
currentfilename = filename;
|
||||
f.close();
|
||||
} else {
|
||||
DMessageManager::instance()->sendMessage(this, ICONRES("open"),
|
||||
tr("OpenFail"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptWindow::on_save() {}
|
||||
void ScriptWindow::on_save() {
|
||||
if (currentfilename.isEmpty()) {
|
||||
on_saveas();
|
||||
return;
|
||||
}
|
||||
QFile f(currentfilename);
|
||||
if (f.open(QFile::WriteOnly)) {
|
||||
f.write(editor->toPlainText().toUtf8());
|
||||
f.close();
|
||||
} else {
|
||||
DMessageManager::instance()->sendMessage(this, ICONRES("save"),
|
||||
tr("SaveFail"));
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptWindow::on_saveas() {}
|
||||
void ScriptWindow::on_saveas() {
|
||||
auto filename =
|
||||
QFileDialog::getSaveFileName(this, tr("ChooseSaveFile"), lastusedpath);
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
lastusedpath = QFileInfo(filename).absoluteDir().absolutePath();
|
||||
QFile f(filename);
|
||||
if (f.open(QFile::WriteOnly)) {
|
||||
f.write(editor->toPlainText().toUtf8());
|
||||
f.close();
|
||||
} else {
|
||||
DMessageManager::instance()->sendMessage(this, ICONRES("saveas"),
|
||||
tr("SaveAsFail"));
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptWindow::on_close() { close(); }
|
||||
|
||||
|
@ -230,27 +440,38 @@ void ScriptWindow::on_cut() { editor->cut(); }
|
|||
void ScriptWindow::on_paste() { editor->paste(); }
|
||||
|
||||
void ScriptWindow::on_run() {
|
||||
PlgInterface::instance()->RunPyText(editor->toPlainText());
|
||||
if (!PlgInterface::instance()->RunPyText(editor->toPlainText())) {
|
||||
DMessageManager::instance()->sendMessage(this, ICONRES("run"),
|
||||
tr("OtherScriptRunning"));
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptWindow::on_runfile() {
|
||||
auto filename = DFileDialog::getOpenFileName(this, tr("ChoosePyScript"),
|
||||
QString(), "Python (*.py)");
|
||||
lastusedpath, "Python (*.py)");
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
PlgInterface::instance()->RunPyFile(filename);
|
||||
|
||||
if (!PlgInterface::instance()->RunPyFile(filename)) {
|
||||
DMessageManager::instance()->sendMessage(this, ICONRES("runf"),
|
||||
tr("OtherScriptRunning"));
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptWindow::on_find() {
|
||||
replacebar->close();
|
||||
auto cur = editor->textCursor();
|
||||
findbar->activeInput("", "", cur.blockNumber(), cur.positionInBlock(), 0);
|
||||
findbar->activeInput(cur.selectedText(), cur.blockNumber(),
|
||||
cur.positionInBlock(),
|
||||
editor->verticalScrollBar()->value());
|
||||
}
|
||||
|
||||
void ScriptWindow::on_replace() {
|
||||
findbar->close();
|
||||
auto cur = editor->textCursor();
|
||||
replacebar->activeInput("", "", cur.blockNumber(), cur.positionInBlock(), 0);
|
||||
replacebar->activeInput(cur.selectedText(), cur.blockNumber(),
|
||||
cur.positionInBlock(),
|
||||
editor->verticalScrollBar()->value());
|
||||
}
|
||||
|
||||
void ScriptWindow::on_about() {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "QCodeEditor/QCodeEditor.hpp"
|
||||
#include "QCodeEditor/QSyntaxStyle.hpp"
|
||||
#include "findbar.h"
|
||||
#include "jumplinebar.h"
|
||||
#include "recentfilemanager.h"
|
||||
#include "replacebar.h"
|
||||
#include <DGuiApplicationHelper>
|
||||
|
@ -18,6 +19,7 @@ class ScriptWindow : public DMainWindow {
|
|||
Q_OBJECT
|
||||
public:
|
||||
ScriptWindow(DMainWindow *parent = nullptr);
|
||||
~ScriptWindow();
|
||||
static ScriptWindow *instance();
|
||||
|
||||
private:
|
||||
|
@ -57,9 +59,13 @@ private:
|
|||
QVBoxLayout *vlayout;
|
||||
FindBar *findbar;
|
||||
ReplaceBar *replacebar;
|
||||
JumpLineBar *jmpbar;
|
||||
QIcon picon;
|
||||
|
||||
private:
|
||||
bool isSaved = true;
|
||||
QString lastusedpath;
|
||||
QString currentfilename;
|
||||
};
|
||||
|
||||
#endif // SCRIPTWINDOW_H
|
||||
|
|
|
@ -37,6 +37,16 @@ bool WingHexPy::init(QList<WingPluginInfo> loadedplugin) {
|
|||
txt = plgint->getScriptingConsole();
|
||||
PluginDockWidgetInit(dw, txt, tr("WingHexPyConsole"), "WingHexPyConsole");
|
||||
|
||||
infolist = new QListWidget;
|
||||
PluginDockWidgetInit(dlist, infolist, tr("InfoList"), "WingHexPyInfoList");
|
||||
infotree = new QTreeWidget;
|
||||
PluginDockWidgetInit(dtree, infotree, tr("InfoTree"), "WingHexPyInfoTree");
|
||||
infotable = new QTableWidget;
|
||||
PluginDockWidgetInit(dtable, infotable, tr("InfoTable"),
|
||||
"WingHexPyInfoTable");
|
||||
|
||||
plgint->initInfo(infolist, infotree, infotable);
|
||||
|
||||
PluginToolBarInitBegin(tb, "WingHexPy") {
|
||||
PluginToolBarAddLamba(
|
||||
tb, QIcon(":/img/pys.png"), [=] { ScriptWindow::instance()->show(); },
|
||||
|
@ -69,13 +79,15 @@ QString WingHexPy::pluginComment() {
|
|||
|
||||
uint WingHexPy::pluginVersion() { return 1; }
|
||||
|
||||
Qt::DockWidgetArea WingHexPy::registerDockWidgetDockArea() {
|
||||
return Qt::DockWidgetArea::BottomDockWidgetArea;
|
||||
}
|
||||
|
||||
QMenu *WingHexPy::registerMenu() { return menu; }
|
||||
|
||||
QDockWidget *WingHexPy::registerDockWidget() { return dw; }
|
||||
void WingHexPy::registerDockWidget(
|
||||
QMap<QDockWidget *, Qt::DockWidgetArea> &rdw) {
|
||||
rdw.insert(dw, Qt::DockWidgetArea::BottomDockWidgetArea);
|
||||
rdw.insert(dtree, Qt::DockWidgetArea::BottomDockWidgetArea);
|
||||
rdw.insert(dtable, Qt::DockWidgetArea::BottomDockWidgetArea);
|
||||
rdw.insert(dlist, Qt::DockWidgetArea::BottomDockWidgetArea);
|
||||
}
|
||||
|
||||
QToolBar *WingHexPy::registerToolBar() { return tb; }
|
||||
|
||||
|
|
13
winghexpy.h
13
winghexpy.h
|
@ -5,7 +5,10 @@
|
|||
#include "PythonQt/gui/PythonQtScriptingConsole.h"
|
||||
#include "plginterface.h"
|
||||
#include <Python.h>
|
||||
#include <QListWidget>
|
||||
#include <QTableWidget>
|
||||
#include <QTextBrowser>
|
||||
#include <QTreeWidget>
|
||||
|
||||
class WingHexPy : public IWingPlugin {
|
||||
Q_OBJECT
|
||||
|
@ -24,14 +27,14 @@ public:
|
|||
void unload() override;
|
||||
QMenu *registerMenu() override;
|
||||
QToolBar *registerToolBar() override;
|
||||
QDockWidget *registerDockWidget() override;
|
||||
void
|
||||
registerDockWidget(QMap<QDockWidget *, Qt::DockWidgetArea> &rdw) override;
|
||||
QString pluginName() override;
|
||||
QString pluginAuthor() override;
|
||||
uint pluginVersion() override;
|
||||
QString signature() override;
|
||||
QString pluginComment() override;
|
||||
void plugin2MessagePipe(WingPluginMessage type, QList<QVariant> msg) override;
|
||||
Qt::DockWidgetArea registerDockWidgetDockArea() override;
|
||||
|
||||
public:
|
||||
void log(QString message);
|
||||
|
@ -46,6 +49,12 @@ private:
|
|||
QToolBar *tb;
|
||||
QDockWidget *dw;
|
||||
PythonQtScriptingConsole *txt;
|
||||
|
||||
private:
|
||||
QDockWidget *dlist, *dtree, *dtable;
|
||||
QListWidget *infolist;
|
||||
QTreeWidget *infotree;
|
||||
QTableWidget *infotable;
|
||||
};
|
||||
|
||||
#endif // GENERICPLUGIN_H
|
||||
|
|
Loading…
Reference in New Issue