diff --git a/README.md b/README.md index 7bf9c168..40ce65f8 100644 --- a/README.md +++ b/README.md @@ -101,11 +101,26 @@ location by passing the option `-DCMAKE_INSTALL_PREFIX=/install/path` to cmake. Python Bindings ================ +Make sure you have pyside2, shiboken2 and shiboken2-generator installed. +As this time, you cannot get shiboken2-generator because the wheels are not on PyPi. +To use the wheels do this: + % pip3 install \ + --index-url=http://download.qt.io/official_releases/QtForPython/ \ + --trusted-host download.qt.io \ + shiboken2 pyside2 shiboken2_generator -To generate PySide2 bindings, pass `-DOPTION_BUILD_PYTHON_BINDINGS=ON` to CMake. -The bindings will be installed to the passed `-DCMAKE_INSTALL_PREFIX`. Which +For more info visit https://doc.qt.io/qtforpython/shiboken2/gettingstarted.html + +Once QtForPython is installed you are ready to generate the PySide bindings +for KDDockwWidgets. + +Next pass `-DOPTION_BUILD_PYTHON_BINDINGS=ON` to CMake, followed by the +make command. + +The bindings will be installed to the passed `-DCMAKE_INSTALL_PREFIX`, which might require setting the `PYTHONPATH` env variable to point to that path when -running applications. Alternatively, pass `-DPYTHON_BINDINGS_INSTALL_PREFIX=/usr/lib/python3.8/site-packages` +running applications. Alternatively, configure the bindings install location +by passing `-DPYTHON_BINDINGS_INSTALL_PREFIX=/usr/lib/python3.8/site-packages` to CMake (adjust to the python path on your system). To run the KDDW python example diff --git a/cmake/Python/FindShiboken2.cmake b/cmake/Python/FindShiboken2.cmake index d72f07e5..60920efd 100644 --- a/cmake/Python/FindShiboken2.cmake +++ b/cmake/Python/FindShiboken2.cmake @@ -16,7 +16,7 @@ # You can install Shiboken from Qt repository with # pip3 install --index-url=https://download.qt.io/snapshots/ci/pyside//latest/ shiboken2-generator --trusted-host download.qt.io -find_package(PkgConfig REQUIRED) +find_package(PkgConfig REQUIRED) pkg_check_modules(SHIBOKEN2_PRIV shiboken2 QUIET) set(SHIBOKEN_FOUND FALSE) @@ -92,13 +92,19 @@ else() SET(SHIBOKEN_LIBRARY_BASENAMES "") elseif(WIN32) SET(SHIBOKEN_LIBRARY_BASENAMES "libshiboken2.${PYSIDE2_SUFFIX}") + elseif(APPLE) + SET(SHIBOKEN_LIBRARY_BASENAMES + libshiboken2.abi3.dylib + libshiboken2.abi3.${SHIBOKEN_MACRO_VERSION}.dylib + libshiboken2.abi3.${SHIBOKEN_MACRO_VERSION}.${SHIBOKEN_MICRO_VERSION}.dylib + libshiboken2.abi3.${SHIBOKEN_VERSION}.dylib + ) else() SET(SHIBOKEN_LIBRARY_BASENAMES libshiboken2.abi3.so libshiboken2.abi3.so.${SHIBOKEN_MACRO_VERSION} libshiboken2.abi3.so.${SHIBOKEN_MACRO_VERSION}.${SHIBOKEN_MICRO_VERSION} libshiboken2.abi3.so.${SHIBOKEN_VERSION} - libshiboken2.abi3.so ) endif() @@ -108,7 +114,7 @@ else() set(SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_CUSTOM_PATH}) list(APPEND SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_BASEDIR}) list(APPEND SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_GENERATOR_BASEDIR}) - +message(STATUS "BOO: ${SHIBOKEN_SEARCH_PATHS}") find_file(SHIBOKEN_LIBRARY ${SHIBOKEN_LIBRARY_BASENAMES} PATHS ${SHIBOKEN_SEARCH_PATHS} @@ -167,13 +173,13 @@ if (SHIBOKEN_FOUND) INTERFACE_INCLUDE_DIRECTORIES ${SHIBOKEN_INCLUDE_DIR} ${Python3_INCLUDE_DIRS}) set_property(TARGET Shiboken2::libshiboken APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${PYTHON_LIMITED_LIBRARIES}) - + # Generator target add_executable(Shiboken2::shiboken IMPORTED GLOBAL) set_property(TARGET Shiboken2::shiboken PROPERTY IMPORTED_LOCATION ${SHIBOKEN_BINARY}) endif() - + find_package_handle_standard_args(Shiboken2 REQUIRED_VARS SHIBOKEN_BASEDIR SHIBOKEN_INCLUDE_DIR SHIBOKEN_LIBRARY SHIBOKEN_BINARY VERSION_VAR SHIBOKEN_VERSION diff --git a/src/DockWidgetBase.cpp b/src/DockWidgetBase.cpp index 8348ba6f..f81f8534 100644 --- a/src/DockWidgetBase.cpp +++ b/src/DockWidgetBase.cpp @@ -212,11 +212,19 @@ void DockWidgetBase::addDockWidgetToContainingWindow(DockWidgetBase *other, Loca void DockWidgetBase::setWidget(QWidgetOrQuick *w) { - Q_ASSERT(w && !d->widget); + Q_ASSERT(w); qCDebug(addwidget) << Q_FUNC_INFO << w; + if (w == d->widget) + return; + + if (d->widget) { + // Unparent the old widget, we're giving back ownership + d->widget->setParent(nullptr); + } d->widget = w; - setSizePolicy(w->sizePolicy()); + if (w) + setSizePolicy(w->sizePolicy()); Q_EMIT widgetChanged(w); setWindowTitle(uniqueName()); diff --git a/src/DockWidgetBase.h b/src/DockWidgetBase.h index 76b6a6b8..b244943f 100644 --- a/src/DockWidgetBase.h +++ b/src/DockWidgetBase.h @@ -130,7 +130,12 @@ public: /** * @brief sets the widget which this dock widget hosts. - * @param widget to show inside this dock widget + * @param widget widget to show inside this dock widget. Must not be null. + * + * Ownership for @p widget is transfered to DockWidgetBase. + * Ownsership for any previously existing widget is transfered back to the user. Meaning if you + * call setWidget(A) followed by setWidget(B) then A will have to be deleted by you, while B is + * owned by the dock widget. */ void setWidget(QWidgetOrQuick *widget); diff --git a/tests/tst_docks.cpp b/tests/tst_docks.cpp index 3696cbc6..d44a77f1 100644 --- a/tests/tst_docks.cpp +++ b/tests/tst_docks.cpp @@ -428,6 +428,7 @@ private Q_SLOTS: void tst_tabsNotClickable(); void tst_stuckSeparator(); void tst_isFocused(); + void tst_setWidget(); private: std::unique_ptr createMultiSplitterFromSetup(MultiSplitterSetup setup, QHash &frameMap) const; @@ -5809,6 +5810,18 @@ void TestDocks::tst_isFocused() delete dock2->window(); } +void TestDocks::tst_setWidget() +{ + EnsureTopLevelsDeleted e; + auto dw = new DockWidget(QStringLiteral("FOO")); + auto button1 = new QPushButton("button1"); + auto button2 = new QPushButton("button2"); + dw->setWidget(button1); + dw->setWidget(button2); + delete button1; + delete dw; +} + int main(int argc, char *argv[]) { if (!qpaPassedAsArgument(argc, argv)) {