initial commit

Signed-off-by: Peter Siegmund <mars3142@noreply.mars3142.dev>
This commit is contained in:
2025-10-31 23:37:30 +01:00
commit bf6b52fd94
9654 changed files with 4035664 additions and 0 deletions

View File

@@ -0,0 +1,216 @@
# wxQt Architecture {#plat_qt_architecture}
## Internals
wxQT uses the same techniques like other ports to wrap the Qt toolkit classes inside the wxWidget hierarchy (especially similar to wxGTK).
### Current (original) Approach
An internal pointer `m_qtWindow` in wxWindow holds the reference to the QWidget (or derived) counterpart, and is accessible through the virtual method `GetHandle`.
This pointer and other window styles are set up in the `PostCreation` method that must be called by the derived classes (mostly controls) to initialize the widget correctly.
Not doing so will cause painting and deletion issues, as the base class will not know how to handle the Qt widget.
wxControl even provides a protected method `QtCreateControl` that will do the common initialization (including post creation step, moving, sizing, etc., and calling the base to add the child to the parent).
**Warning**: Take care of not calling any function that can raise an assertion before `PostCreation`, for example wxFAIL_MSG, as it will interrupt the normal initialization, hence the later cleanup will crash.
For example, this issue was caused by WXValidateStyle in wxCheckBox::Create, that was "failing silently" in unit tests, and then raising segmentation faults when the object was later deleted (as Qt checkbox counterpart was never being deleted due the aborted initialization).
Many controls have also other pointers to allow to map different sub-widgets and other features.
### New (tentative) Approach
In the other end, Top Level Windows (frames and dialogs) uses directly the internal window pointer, doing a static cast to return the correct type for GetHandle, avoiding multilevel pointer hierarchies.
This would be the ideal solution, but not all classes could be mapped 1:1 and that could introduce potential issues (i.e. invalid static casts) and more boilerplate due to additional specific accessor methods.
For a longer discussion of pro and cons, see [PR#43 comments](https://github.com/reingart/wxWidgets/pull/43)
Note that some special cases are not real windows like the `wxTabFrame` (AUI), so they don't set the internal pointer and hence drawing methods should not be used at all.
### Scroll Areas
In both approaches, special care should be taken with scrolling areas, as Qt manages this ones slightly different to wxWidgets.
`QtGetScrollBarsContainer` should be reimplemented to return the QScrollArea widget or similar (where the scroll bars are places).
That widget should implement a `viewport()` (Qt idiom to differentiate the draw-able area).
Attempts to paint directly to the scroll area itself will fail.
This is already handled in the QtHandlePaintEvent wxWindowQt method.
### wxWidgets to Qt symmetries
Many wxWidgets classes maps 1:1 to Qt ones, but there are some exceptions are (1:N or N:1):
* wxAnyButton (wxButton, wxBitmapButton, wxToggleButton): QPushButton
* wxFrame: QMainWindow with a QWidget inside as central widget
* wxRadioBox: QGroupBox with a QButtonGroup inside
* wxStaticText & wxStaticBitmap: QLabel
* wxTextCtrl: QLineEdit or QTextEdit (multiline)
* wxWindow (wxPanel): QWidget or QScrollArea
### Private helpers
Qt objects needs to be sub-classed to re-implement events and connect signals (more info in [wx-dev forum](https://groups.google.com/d/msg/wx-dev/UpkJMnT3V2o/hIoJwT3qpw4J)):
* Qt events are just virtual methods that needs to be overridden by the derived classes to handle them
* Qt signals can be connected to QObject members or simple functions (thanks to Qt5 new signal slot syntax)
The approach chosen was to use templates to help inherit QObject's (QWidget), providing a common base to handle events and signal infrastructure:
* `wxQtSignalHandler< wxWindow >`: allows emitting wx events for Qt events & signals. This should be used for all QObjects derivatives that are not widgets, for example QAction (used for shortcut / accelerators).
* `wxQtEventSignalHandler< QWidget, wxWindow >`: derived from `wxQtSignalHandler`, also handles basic events (change, focus, mouse, keyboard, paint, close, etc.). This should be used for all QWidget derivatives (controls, top level windows, etc.)
### Delete later
Both templates also have some safety checks to avoid invalid spurious access to deleted wx objects (using a special pointer to the wx instance stored in the Qt object, that is reset to @NULL when the wx counterpart is marked to deletion).
This is due that in some situations, Qt object could still be referenced in the Qt event queue, so it cannot be removed immediately.
**Important**: Currently wxQT is using Qt's `deleteLater` method to avoid this kind of issues.
Please, don't use delete directly except you're confident it will not cause faults or other issues.
Note that no public wxWidget class should be derived directly from QWidget as they could have different lifespans and other implications to run time type systems (RTTI).
Some QObjects are even owned by Qt (for example: menubar, statusbar) and some parents (ie. `QTabWidget`) cannot be deleted immediately in some circumstances (they would cause segmentation faults due spurious events / signals caused by the children destruction if not correctly handled as explained previously)
For more information about the deletion issues, see [deleteLater](https://github.com/reingart/wxWidgets/wiki/WxQtDeleteLaterNotes ) notes and [wx-dev thread](https://groups.google.com/d/msg/wx-dev/H0Xc9aQzaH4/crjFDPsEA0cJ) discussion.
### Files Structure
wxQT follows the same conventions used in other wxWidgets ports:
* Source code is inside src/qt folder
* Headers are inside include/qt folder
There are also some `__WXQT__` guards to enable special features in common / generic code (i.e. event loop, graphic renders, grid)
Although some Qt headers are included in public wx headers, this dependencies should be avoided as this could change in the future (decoupling completely the public wxQT headers from Qt).
Private headers should be include/qt/private, currently they hold:
* converter.h: conversion functions between Qt and wxWidgets for point, rect, size, string, date, orientation and keycodes
* winevent.h: common templates for window event/signal handling (wxQtSignalHandler and wxQtEventSignalHandler)
* utils.h: debug functions and common event utilities
### Adding files
To add a Qt derived class simply put it in a .h file and add the corresponding .cpp file to the build/bakefiles/files.bkl e.g.:
<set var="QT_LOWLEVEL_HDR" hints="files">
wx/qt/menuitem.h
</set>
<set var="QT_LOWLEVEL_SRC" hints="files">
src/qt/menuitem.cpp
</set>
From within of the bakefiles directory, regenerate the autoconf files with:
bakefile_gen --formats autoconf
Generate the 'configure' script in your wxQt root directory with:
autoconf
**IMPORTANT NOTE**: The precompilation step (Qt's moc) is no more needed so the build rule was removed. There is no need to use `Q_OBJECT` nor `Q_SLOTS` macros.
// include/wx/qt/menuitem.h
class wxMenuItem : public wxMenuItemBase
{
// ...
};
class wxQtAction : public QAction
{
public:
wxQtAction( wxMenuItem *menuItem, const QString &text, QObject *parent );
private:
void OnActionTriggered( bool checked );
private:
wxMenuItem *m_menuItem;
};
### Coding guidelines
* If you leave out an implementation for whatever reason, then mark it with the wxMISSING_IMPLEMENTATION() macro from wx/qt/utils.h i.e.:
void wxSomeClass::SomeMethod()
{
wxMISSING_IMPLEMENTATION( __func__ );
}
or if only some implementation is missing like evaluating flags:
void wxSomeClass::SomeMethod( unsigned methodFlags )
{
wxMISSING_IMPLEMENTATION( "methodFlags" );
}
* To avoid name clashes with a 3rd party library like boost, and due precompilation step was removed, don't use the internal moc keywords `signals` and `slots` nor `SIGNAL` / `SLOT` macros for `connect`. Instead, use the "New Signal Slot Qt syntax":
class wxQtClass : public QObject
{
wxQtClass(): QObject()
{
connect(this, &QObject::objectNameChanged, this, &wxQtClass::objectNameChanged);
}
private: // "signal slots":
void objectNameChanged();
};
### Naming conventions
* Global helper classes and global functions should be prefixed with `wxQt` i.e.:
class wxQtButton : public QPushButton
{
}
QRect wxQtConvertRect( const wxRect & );
* Public wxWidgets Qt classes should not use any prefix or suffix, except for special cases, for example:
// no prefix/suffix in most clases:
class wxButton : public wxButtonBase;
// suffix for consistency with other ports:
class wxWindowQt : public wxWindowBase;
class wxTopLevelWindowQt : public wxTopLevelWindowBase; // (BTW: avoid using Native)
// special case (to avoid ambiguity with wxQtSpinBoxBase helper
class wxSpinCtrlQt : public wxSpinCtrlBase; // (not a wxQt helper)
// prefix for consistency with other ports:
class wxQtDCImpl : public wxDCImpl; // with wxMSWDCImpl, wxGTKDCImpl
* Internal methods in publicly visible classes (like wxWindowQt) should be prefixed with `Qt` i.e.:
class wxWindowQt : public wxWindowBase
{
public:
QWidget *QtGetContainer() const;
};
* Internal private instance variables (like in wxWindowQt) should be prefixed with `'m_qt` i.e.:
class wxWindow : public wxWindowBase
{
private:
QWidget *m_qtWindow;
QScrollArea *m_qtContainer;
QPicture *m_qtPicture;
QPainter *m_qtPainter;
};
* Qt derived names should use mixedCase (in helper methods, for example for `clicked` signal, following the original Qt name), but wx methods should be CamelCase (i.e. `Emit`):
void wxQtPushButton::clicked( bool WXUNUSED(checked) )
{
wxAnyButton *handler = GetHandler();
if ( handler )
{
wxCommandEvent event( wxEVT_BUTTON, handler->GetId() );
EmitEvent( event );
}
}

View File

@@ -0,0 +1,209 @@
wxWidgets for Qt installation {#plat_qt_install}
-----------------------------
[TOC]
IMPORTANT NOTE:
If you experience problems installing, please re-read these
instructions and other related files (todo.txt, bugs.txt and
osname.txt for your platform if it exists) carefully before
mailing wxwin-users or the author. Preferably, try to fix the
problem first and then send a patch to the author.
When sending bug reports tell us what version of wxWidgets you are
using (including the beta) and what compiler on what system. One
example: wxQt 3.1.0, GCC 4.8.1, Ubuntu 14.04
Installation {#qt_install}
============
The simplest case {#qt_simple}
-------------------
If you compile wxWidgets on Linux for the first time and don't like to read
install instructions just do (in the base dir):
> mkdir buildqt
> cd buildqt
> ../configure --with-qt
> make
> su <type root password>
> make install
> ldconfig
[if you get "ldconfig: command not found", try using "/sbin/ldconfig"]
If you don't do the 'make install' part, you can still use the libraries from
the buildgtk directory, but they may not be available to other users.
If you want to remove wxWidgets on Unix you can do this:
> su <type root password>
> make uninstall
> ldconfig
The simplest errors {#qt_error_simple}
---------------------
For any configure errors: please look at config.log file which was generated
during configure run, it usually contains some useful information.
configure reports, that you don't have Qt installed although you are very
sure you have. Well, you have installed it, but you also have another
version of the Qt installed, which you may need to remove. Or maybe you
installed it in a non-default location and configure can't find it there,
so please check that your PATH variable includes the path to the correct
qtconfig/pkg-config. Also check that your LD_LIBRARY_PATH or equivalent
variable contains the path to Qt libraries if they were installed in a
non-default location.
The simplest program {#qt_simple_app}
----------------------
Now create your super-application myfoo.cpp and compile anywhere with
g++ myfoo.cpp `wx-config --libs --cxxflags` -o myfoo
GUI libraries {#qt_libs_ui}
---------------
wxWidgets/Qt requires the Qt library to be installed on your system. It has
to be a stable version, preferably Qt 5.2.1 or later.
Building wxQT on Ubuntu {#qt_build_ubuntu}
-------------------------
Install latest Qt5 packages (qt5-default). To build unit tests, libcppunit-dev
is required. You will need to install other dependencies to compile wxWidgets
depending on the features you'll want to use (build-essential libjpeg-dev
libtiff-dev ubuntu-restricted-extras freeglut3 freeglut3-dev libsdl1.2-dev
libgstreamer-plugins-base0.10-dev)
Then create a build directory, configure and compile:
mkdir bldqt5
cd bldqt5
../configure --with-qt --enable-debug
make
make samples
If everything is ok, you can do the make install as specified before.
Optionally, you can build and run Unit Tests:
cd tests
make
./test_gui
Building wxQT, using qt-unified-XXX-online installer {#qt_build}
------------------------------------------------------
Download qt-unified-XXX-online installer from the qt website.
Install the Qt package of your choice (with the same minimum version
restriction as above).
The same build instructions apply, except that you need to explicitly pass
to configure the Qt dir of the build intended to use as QT5_CUSTOM_DIR, i.e.
for Linux:
../configure --with-qt --enable-debug QT5_CUSTOM_DIR=~/Qt/5.11.0/gcc_64
for Windows (ran from Git Bash, or any other Unix-like shell):
(the syntax for the drive in the path is required by ar and ld)
../configure --with-qt --enable-debug QT5_CUSTOM_DIR=c:/Qt/5.11.0/mingw53_32
Building wxQT using MSVC on Windows {#qt_build_windows_msvc}
-----------------------------------
To build wxQt using MSVC you need to use CMake, please see
[CMake build instructions](@ref overview_cmake) for all the details, but in
short you just need to pass `-DwxBUILD_TOOLKIT=qt` to it when configuring.
CMake uses `Qt5_Dir` variable to find Qt installation, so you need to set it
to something like `c:\Qt\5.14.2\5.14.2\msvc2017_64` before running
cmake -S . -B build/qt -DwxBUILD_TOOLKIT=qt -DwxBUILD_SAMPLES=SOME
(the last option is not required but recommended to allow you to build the
minimal sample to test your build).
Building wxQT on Android {#qt_android}
--------------------------
Download Android Native Development Kit (NDK), standalone Android Software
Development Kit (SDK), install them and perform the following instructions to
prepare the cross-compilation tool-chain to (change NDK and other paths):
NDK=~/src/android-ndk-r9d
SDK=~/src/android-sdk-linux
export ANDROID_NDK_ROOT=$NDK
$NDK/build/tools/make-standalone-toolchain.sh \
--toolchain=arm-linux-androideabi-4.8 --platform=android-9 \
--install-dir=/tmp/ndk
export PATH=/tmp/ndk/bin:$PATH
export CC=arm-linux-androideabi-gcc
export CXX=arm-linux-androideabi-g++
Also, you'll need to download the Qt library bundle that matches your operating
system installed package (5.2.1 in this case installed in ~/src/qt, you'll need
the android_armv5/ android_armv7/ android_x86/ pre-compiled folders to
cross-compile for that architectures)
Then, create a build directory (under the wxWidgets folder), configure for
Android (disable currently unsupported/unneeded features) and run make:
cd ~/src/wxWidgets
mkdir bldqt5droid
cd bldqt5droid
../configure --with-qt --enable-debug --build=x86_64-unknown-linux-gnu \
--host=arm-linux-androideabi --disable-compat30 --disable-shared \
--disable-arttango --enable-image --disable-dragimage --disable-sockets \
--with-libtiff=no --without-opengl --disable-baseevtloop --disable-utf8
make
You can now compile and link your app against this build, and finally
package it for Android using standard APK tools.
Create your configuration {#qt_config}
---------------------------
Usage:
./configure options
If you want to use system's C and C++ compiler,
set environment variables CC and CXX as
% setenv CC cc
% setenv CXX CC
% ./configure [options]
to see all the options please use:
./configure --help
It is recommended to build wxWidgets in another directory (maybe a
subdirectory of your wxWidgets installation) as this allows you to
have multiple configurations (for example, debug and release or GTK
and X11) simultaneously.
Feature Options {#qt_feature_options}
-----------------
When producing an executable that is linked statically with wxQt
you'll be surprised at its immense size. This can sometimes be
drastically reduced by removing features from wxWidgets that
are not used in your program.
Please see the output of "./configure --help" for comprehensive list
of all configurable options.
Apart from disabling certain features you can very often "strip"
the program of its debugging information resulting in a significant
reduction in size.

View File

@@ -0,0 +1,47 @@
Welcome to wxWidgets for Qt
---------------------------
You have downloaded the Qt port of the wxWidgets GUI library.
It is required to use at least Qt 5 and some features are
only available when using Qt 5.2 or higher.
More info about the wxWidgets project (including all the
other ports and version of wxWidgets) can be found at the
main wxWidgets homepage at:
https://www.wxwidgets.org/
More information on how to install can be found in the file
install.md in this directory, but this works in a Unix-like
environment, including Cygwin/MSYS2 under Windows:
mkdir build_qt
cd build_qt
../configure --with-qt
make
# Optionally
su <type root password>
make install
ldconfig
Please note that it is strongly advised to build the library in
a separate directory, as shown above, as it allows you to have
different builds of it (for example with and without debug) in
parallel. If you build in the source directory, don't forget to
do "make clean" before changing the configuration!
When you run into problems, please read the install.md and
follow those instructions. If you still don't have any success,
please send a bug report to one of our mailing list, INCLUDING
A DESCRIPTION OF YOUR SYSTEM AND YOUR PROBLEM, SUCH AS YOUR
VERSION OF QT, WXQT, WHAT DISTRIBUTION YOU USE AND WHAT ERROR
WAS REPORTED.
Please send problems concerning installation, feature requests,
bug reports or comments to the wxWidgets users list. These can
be found at https://www.wxwidgets.org/support/mailing-lists/
Regards,
The wxWidgets Team