diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 91c7457..2f260f1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,169 +1,169 @@ set(KParts_LIB_SRCS partbase.cpp part.cpp partloader.cpp openurlarguments.cpp readonlypart.cpp readwritepart.cpp plugin.cpp partmanager.cpp mainwindow.cpp event.cpp guiactivateevent.cpp partactivateevent.cpp partselectevent.cpp browserextension.cpp browserhostextension.cpp browserarguments.cpp liveconnectextension.cpp openurlevent.cpp windowargs.cpp historyprovider.cpp browserinterface.cpp browserrun.cpp browseropenorsavequestion.cpp statusbarextension.cpp scriptableextension.cpp textextension.cpp htmlextension.cpp htmlsettingsinterface.cpp selectorinterface.cpp fileinfoextension.cpp listingfilterextension.cpp listingnotificationextension.cpp ) include(ECMGenerateHeaders) ecm_generate_headers(KParts_CamelCase_HEADERS HEADER_NAMES BrowserArguments BrowserExtension BrowserHostExtension BrowserInterface BrowserOpenOrSaveQuestion BrowserRun Event FileInfoExtension GUIActivateEvent HistoryProvider HtmlExtension HtmlSettingsInterface ListingFilterExtension ListingNotificationExtension LiveConnectExtension MainWindow OpenUrlArguments OpenUrlEvent Part PartActivateEvent PartBase PartLoader PartManager PartSelectEvent Plugin ReadOnlyPart ReadWritePart ScriptableExtension SelectorInterface StatusBarExtension TextExtension WindowArgs REQUIRED_HEADERS KParts_HEADERS PREFIX KParts ) install(FILES ${KParts_CamelCase_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KParts/KParts COMPONENT Devel) ecm_qt_declare_logging_category(KParts_LIB_SRCS - HEADER debug.h - IDENTIFIER KPartsLog + HEADER kparts_logging.h + IDENTIFIER KPARTSLOG CATEGORY_NAME kf.parts DESCRIPTION "KParts" - EXPORT KPartsLog + EXPORT KPARTSLOG ) add_library(KF5Parts ${KParts_LIB_SRCS}) add_library(KF5::Parts ALIAS KF5Parts) ecm_generate_export_header(KF5Parts EXPORT_FILE_NAME ${KParts_BINARY_DIR}/kparts/kparts_export.h BASE_NAME KParts GROUP_BASE_NAME KF VERSION ${KF5_VERSION} DEPRECATED_BASE_VERSION 0 DEPRECATION_VERSIONS 3.0 4.4 5.0 EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} ) set(KParts_BUILD_INCLUDE_DIRS ${KParts_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(KF5Parts PUBLIC "$") target_include_directories(KF5Parts INTERFACE "$" ) target_link_libraries(KF5Parts PUBLIC KF5::KIOWidgets #browserrun.h uses krun.h KF5::XmlGui # essential to the technology KF5::TextWidgets # needed for KFind, as interface PRIVATE KF5::I18n #few uses of i18n and i18nc, can be probably stripped down KF5::IconThemes #only used by KPart::iconLoader() ) set_target_properties(KF5Parts PROPERTIES VERSION ${KPARTS_VERSION_STRING} SOVERSION ${KPARTS_SOVERSION} EXPORT_NAME Parts ) install(TARGETS KF5Parts EXPORT KF5PartsTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES kpart.desktop krop.desktop krwp.desktop browserview.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR} ) install(FILES ${KParts_BINARY_DIR}/kparts/kparts_export.h ${KParts_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KParts/kparts COMPONENT Devel ) install(FILES kde_terminal_interface.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KParts ) ecm_qt_install_logging_categories( - EXPORT KPartsLog + EXPORT KPARTSLOG FILE kparts.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR} ) if(BUILD_QCH) ecm_add_qch( KF5Parts_QCH NAME KParts BASE_NAME KF5Parts VERSION ${KF5_VERSION} ORG_DOMAIN org.kde SOURCES # using only public headers, to cover only public API ${KParts_HEADERS} kde_terminal_interface.h MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md" LINK_QCHS KF5KIO_QCH KF5XmlGui_QCH KF5TextWidgets_QCH INCLUDE_DIRS ${KParts_BUILD_INCLUDE_DIRS} BLANK_MACROS KPARTS_EXPORT KPARTS_DEPRECATED KPARTS_DEPRECATED_EXPORT "KPARTS_DEPRECATED_VERSION(x, y, t)" PREDEFINED_MACROS "KIOWIDGETS_ENABLE_DEPRECATED_SINCE(x, y)=1" TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} COMPONENT Devel ) endif() include(ECMGeneratePriFile) ecm_generate_pri_file(BASE_NAME KParts LIB_NAME KF5Parts DEPS "KIOWidgets KXmlGui KTextWidgets" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/KParts) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) diff --git a/src/part.cpp b/src/part.cpp index 5a32bd8..15cfc99 100644 --- a/src/part.cpp +++ b/src/part.cpp @@ -1,214 +1,214 @@ /* This file is part of the KDE project Copyright (C) 1999 Simon Hausmann (C) 1999-2005 David Faure This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "part.h" #include "part_p.h" -#include "loggingcategory.h" +#include "kparts_logging.h" #include "partactivateevent.h" #include "partselectevent.h" #include "guiactivateevent.h" #include "partmanager.h" #include #include using namespace KParts; Part::Part(QObject *parent) : QObject(parent), PartBase(*new PartPrivate(this)) { PartBase::setPartObject(this); } Part::Part(PartPrivate &dd, QObject *parent) : QObject(parent), PartBase(dd) { PartBase::setPartObject(this); } Part::~Part() { Q_D(Part); - //qCDebug(KPartsLog) << this; + //qCDebug(KPARTSLOG) << this; if (d->m_widget) { // We need to disconnect first, to avoid calling it ! disconnect(d->m_widget.data(), &QWidget::destroyed, this, &Part::slotWidgetDestroyed); } if (d->m_manager) { d->m_manager->removePart(this); } if (d->m_widget && d->m_autoDeleteWidget) { - // qCDebug(KPartsLog) << "deleting widget" << d->m_widget << d->m_widget->objectName(); + // qCDebug(KPARTSLOG) << "deleting widget" << d->m_widget << d->m_widget->objectName(); delete static_cast(d->m_widget); } delete d->m_iconLoader; } void Part::embed(QWidget *parentWidget) { if (widget()) { widget()->setParent(parentWidget, Qt::WindowFlags()); widget()->setGeometry(0, 0, widget()->width(), widget()->height()); widget()->show(); } } QWidget *Part::widget() { Q_D(Part); return d->m_widget; } void Part::setAutoDeleteWidget(bool autoDeleteWidget) { Q_D(Part); d->m_autoDeleteWidget = autoDeleteWidget; } void Part::setAutoDeletePart(bool autoDeletePart) { Q_D(Part); d->m_autoDeletePart = autoDeletePart; } KIconLoader *Part::iconLoader() { Q_D(Part); if (!d->m_iconLoader) { d->m_iconLoader = new KIconLoader(componentName()); } return d->m_iconLoader; } void Part::setManager(PartManager *manager) { Q_D(Part); d->m_manager = manager; } PartManager *Part::manager() const { Q_D(const Part); return d->m_manager; } Part *Part::hitTest(QWidget *widget, const QPoint &) { Q_D(Part); if ((QWidget *)d->m_widget != widget) { return nullptr; } return this; } void Part::setWidget(QWidget *widget) { Q_D(Part); d->m_widget = widget; connect(d->m_widget.data(), &QWidget::destroyed, this, &Part::slotWidgetDestroyed, Qt::UniqueConnection); } void Part::setSelectable(bool selectable) { Q_D(Part); d->m_bSelectable = selectable; } bool Part::isSelectable() const { Q_D(const Part); return d->m_bSelectable; } void Part::customEvent(QEvent *ev) { if (PartActivateEvent::test(ev)) { partActivateEvent(static_cast(ev)); return; } if (PartSelectEvent::test(ev)) { partSelectEvent(static_cast(ev)); return; } if (GUIActivateEvent::test(ev)) { guiActivateEvent(static_cast(ev)); return; } QObject::customEvent(ev); } void Part::partActivateEvent(PartActivateEvent *) { } void Part::partSelectEvent(PartSelectEvent *) { } void Part::guiActivateEvent(GUIActivateEvent *) { } QWidget *Part::hostContainer(const QString &containerName) { if (!factory()) { return nullptr; } return factory()->container(containerName, this); } void Part::slotWidgetDestroyed() { Q_D(Part); d->m_widget = nullptr; if (d->m_autoDeletePart) { - // qCDebug(KPartsLog) << "deleting part" << objectName(); + // qCDebug(KPARTSLOG) << "deleting part" << objectName(); this->deleteLater(); } } void Part::loadPlugins() { PartBase::loadPlugins(this, this, componentData()); } #include "moc_part.cpp" diff --git a/src/partmanager.cpp b/src/partmanager.cpp index 3603514..5803440 100644 --- a/src/partmanager.cpp +++ b/src/partmanager.cpp @@ -1,584 +1,585 @@ /* This file is part of the KDE project Copyright (C) 1999 Simon Hausmann (C) 1999 David Faure This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "loggingcategory.h" #include "partmanager.h" + +#include "kparts_logging.h" #include "partactivateevent.h" #include "partselectevent.h" #include "guiactivateevent.h" #include "part.h" #include #include #include #include //#define DEBUG_PARTMANAGER using namespace KParts; namespace KParts { class PartManagerPrivate { public: PartManagerPrivate() { m_activeWidget = nullptr; m_activePart = nullptr; m_selectedPart = nullptr; m_selectedWidget = nullptr; m_bAllowNestedParts = false; m_bIgnoreScrollBars = false; m_activationButtonMask = Qt::LeftButton | Qt::MidButton | Qt::RightButton; m_reason = PartManager::NoReason; m_bIgnoreExplicitFocusRequest = false; } ~PartManagerPrivate() { } void setReason(QEvent *ev) { switch (ev->type()) { case QEvent::MouseButtonPress: case QEvent::MouseButtonDblClick: { QMouseEvent *mev = static_cast(ev); m_reason = mev->button() == Qt::LeftButton ? PartManager::ReasonLeftClick : (mev->button() == Qt::MidButton ? PartManager::ReasonMidClick : PartManager::ReasonRightClick); break; } case QEvent::FocusIn: m_reason = static_cast(ev)->reason(); break; default: qWarning() << "PartManagerPrivate::setReason got unexpected ev type " << ev->type(); break; } } bool allowExplicitFocusEvent(QEvent *ev) const { if (ev->type() == QEvent::FocusIn) { QFocusEvent *fev = static_cast(ev); return (!m_bIgnoreExplicitFocusRequest || fev->reason() != Qt::OtherFocusReason); } return true; } Part *m_activePart; QWidget *m_activeWidget; QList m_parts; PartManager::SelectionPolicy m_policy; Part *m_selectedPart; QWidget *m_selectedWidget; QList m_managedTopLevelWidgets; short int m_activationButtonMask; bool m_bIgnoreScrollBars; bool m_bAllowNestedParts; int m_reason; bool m_bIgnoreExplicitFocusRequest; }; } PartManager::PartManager(QWidget *parent) : QObject(parent), d(new PartManagerPrivate) { qApp->installEventFilter(this); d->m_policy = Direct; addManagedTopLevelWidget(parent); } PartManager::PartManager(QWidget *topLevel, QObject *parent) : QObject(parent), d(new PartManagerPrivate) { qApp->installEventFilter(this); d->m_policy = Direct; addManagedTopLevelWidget(topLevel); } PartManager::~PartManager() { for (const QWidget *w : qAsConst(d->m_managedTopLevelWidgets)) { disconnect(w, &QWidget::destroyed, this, &PartManager::slotManagedTopLevelWidgetDestroyed); } for (Part *it : qAsConst(d->m_parts)) { it->setManager(nullptr); } // core dumps ... setActivePart( 0 ); qApp->removeEventFilter(this); delete d; } void PartManager::setSelectionPolicy(SelectionPolicy policy) { d->m_policy = policy; } PartManager::SelectionPolicy PartManager::selectionPolicy() const { return d->m_policy; } void PartManager::setAllowNestedParts(bool allow) { d->m_bAllowNestedParts = allow; } bool PartManager::allowNestedParts() const { return d->m_bAllowNestedParts; } void PartManager::setIgnoreScrollBars(bool ignore) { d->m_bIgnoreScrollBars = ignore; } bool PartManager::ignoreScrollBars() const { return d->m_bIgnoreScrollBars; } void PartManager::setActivationButtonMask(short int buttonMask) { d->m_activationButtonMask = buttonMask; } short int PartManager::activationButtonMask() const { return d->m_activationButtonMask; } bool PartManager::eventFilter(QObject *obj, QEvent *ev) { if (ev->type() != QEvent::MouseButtonPress && ev->type() != QEvent::MouseButtonDblClick && ev->type() != QEvent::FocusIn) { return false; } if (!obj->isWidgetType()) { return false; } QWidget *w = static_cast(obj); if (((w->windowFlags().testFlag(Qt::Dialog)) && w->isModal()) || (w->windowFlags().testFlag(Qt::Popup)) || (w->windowFlags().testFlag(Qt::Tool))) { return false; } QMouseEvent *mev = nullptr; if (ev->type() == QEvent::MouseButtonPress || ev->type() == QEvent::MouseButtonDblClick) { mev = static_cast(ev); - qCDebug(KPartsLog) << "PartManager::eventFilter button:" << mev->button() << "d->m_activationButtonMask=" << d->m_activationButtonMask; + qCDebug(KPARTSLOG) << "PartManager::eventFilter button:" << mev->button() << "d->m_activationButtonMask=" << d->m_activationButtonMask; if ((mev->button() & d->m_activationButtonMask) == 0) { return false; // ignore this button } } Part *part; while (w) { QPoint pos; if (!d->m_managedTopLevelWidgets.contains(w->topLevelWidget())) { return false; } if (d->m_bIgnoreScrollBars && ::qobject_cast(w)) { return false; } if (mev) { // mouse press or mouse double-click event pos = mev->globalPos(); part = findPartFromWidget(w, pos); } else { part = findPartFromWidget(w); } const char *evType = (ev->type() == QEvent::MouseButtonPress) ? "MouseButtonPress" : (ev->type() == QEvent::MouseButtonDblClick) ? "MouseButtonDblClick" : (ev->type() == QEvent::FocusIn) ? "FocusIn" : "OTHER! ERROR!"; if (part) { // We found a part whose widget is w if (d->m_policy == PartManager::TriState) { if (ev->type() == QEvent::MouseButtonDblClick) { if (part == d->m_activePart && w == d->m_activeWidget) { return false; } - qCDebug(KPartsLog) << "PartManager::eventFilter dblclick -> setActivePart" << part; + qCDebug(KPARTSLOG) << "PartManager::eventFilter dblclick -> setActivePart" << part; d->setReason(ev); setActivePart(part, w); d->m_reason = NoReason; return true; } if ((d->m_selectedWidget != w || d->m_selectedPart != part) && (d->m_activeWidget != w || d->m_activePart != part)) { if (part->isSelectable()) { setSelectedPart(part, w); } else { - qCDebug(KPartsLog) << "Part" << part << "(non-selectable) made active because" << w->metaObject()->className() << "got event" << evType; + qCDebug(KPARTSLOG) << "Part" << part << "(non-selectable) made active because" << w->metaObject()->className() << "got event" << evType; d->setReason(ev); setActivePart(part, w); d->m_reason = NoReason; } return true; } else if (d->m_selectedWidget == w && d->m_selectedPart == part) { - qCDebug(KPartsLog) << "Part" << part << "made active (from selected) because" << w->metaObject()->className() << "got event" << evType; + qCDebug(KPARTSLOG) << "Part" << part << "made active (from selected) because" << w->metaObject()->className() << "got event" << evType; d->setReason(ev); setActivePart(part, w); d->m_reason = NoReason; return true; } else if (d->m_activeWidget == w && d->m_activePart == part) { setSelectedPart(nullptr); return false; } return false; } else if (part != d->m_activePart && d->allowExplicitFocusEvent(ev)) { - qCDebug(KPartsLog) << "Part" << part << "made active because" << w->metaObject()->className() << "got event" << evType; + qCDebug(KPARTSLOG) << "Part" << part << "made active because" << w->metaObject()->className() << "got event" << evType; d->setReason(ev); setActivePart(part, w); d->m_reason = NoReason; } return false; } w = w->parentWidget(); if (w && (((w->windowFlags() & Qt::Dialog) && w->isModal()) || (w->windowFlags() & Qt::Popup) || (w->windowFlags() & Qt::Tool))) { - qCDebug(KPartsLog) << "No part made active although" << obj->objectName() << "/" << obj->metaObject()->className() + qCDebug(KPARTSLOG) << "No part made active although" << obj->objectName() << "/" << obj->metaObject()->className() << "got event - loop aborted"; return false; } } - qCDebug(KPartsLog) << "No part made active although" << obj->objectName() << "/" << obj->metaObject()->className() + qCDebug(KPARTSLOG) << "No part made active although" << obj->objectName() << "/" << obj->metaObject()->className() << "got event - loop aborted"; return false; } Part *PartManager::findPartFromWidget(QWidget *widget, const QPoint &pos) { for (auto *p : qAsConst(d->m_parts)) { Part *part = p->hitTest(widget, pos); if (part && d->m_parts.contains(part)) { return part; } } return nullptr; } Part *PartManager::findPartFromWidget(QWidget *widget) { for (auto *part : qAsConst(d->m_parts)) { if (widget == part->widget()) { return part; } } return nullptr; } void PartManager::addPart(Part *part, bool setActive) { Q_ASSERT(part); // don't add parts more than once :) if (d->m_parts.contains(part)) { #ifdef DEBUG_PARTMANAGER qWarning() << part << " already added"; #endif return; } d->m_parts.append(part); part->setManager(this); if (setActive) { setActivePart(part); if (QWidget *w = part->widget()) { // Prevent focus problems if (w->focusPolicy() == Qt::NoFocus) { qWarning() << "Part '" << part->objectName() << "' has a widget " << w->objectName() << " with a focus policy of NoFocus. It should have at least a" << "ClickFocus policy, for part activation to work well."; } if (part->widget() && part->widget()->focusPolicy() == Qt::TabFocus) { qWarning() << "Part '" << part->objectName() << "' has a widget " << w->objectName() << " with a focus policy of TabFocus. It should have at least a" << "ClickFocus policy, for part activation to work well."; } w->setFocus(); w->show(); } } emit partAdded(part); } void PartManager::removePart(Part *part) { if (!d->m_parts.contains(part)) { return; } const int nb = d->m_parts.removeAll(part); Q_ASSERT(nb == 1); Q_UNUSED(nb); // no warning in release mode part->setManager(nullptr); emit partRemoved(part); if (part == d->m_activePart) { setActivePart(nullptr); } if (part == d->m_selectedPart) { setSelectedPart(nullptr); } } void PartManager::replacePart(Part *oldPart, Part *newPart, bool setActive) { - //qCDebug(KPartsLog) << "replacePart" << oldPart->name() << "->" << newPart->name() << "setActive=" << setActive; + //qCDebug(KPARTSLOG) << "replacePart" << oldPart->name() << "->" << newPart->name() << "setActive=" << setActive; // This methods does exactly removePart + addPart but without calling setActivePart(0) in between if (!d->m_parts.contains(oldPart)) { qFatal("Can't remove part %s, not in KPartManager's list.", oldPart->objectName().toLocal8Bit().constData()); return; } d->m_parts.removeAll(oldPart); oldPart->setManager(nullptr); emit partRemoved(oldPart); addPart(newPart, setActive); } void PartManager::setActivePart(Part *part, QWidget *widget) { if (part && !d->m_parts.contains(part)) { qWarning() << "trying to activate a non-registered part!" << part->objectName(); return; // don't allow someone call setActivePart with a part we don't know about } //check whether nested parts are disallowed and activate the top parent part then, by traversing the //tree recursively (Simon) if (part && !d->m_bAllowNestedParts) { QObject *parentPart = part->parent(); // ### this relies on people using KParts::Factory! KParts::Part *parPart = ::qobject_cast(parentPart); if (parPart) { setActivePart(parPart, parPart->widget()); return; } } - qCDebug(KPartsLog) << "PartManager::setActivePart d->m_activePart=" << d->m_activePart << "<->part=" << part + qCDebug(KPARTSLOG) << "PartManager::setActivePart d->m_activePart=" << d->m_activePart << "<->part=" << part << "d->m_activeWidget=" << d->m_activeWidget << "<->widget=" << widget; // don't activate twice if (d->m_activePart && part && d->m_activePart == part && (!widget || d->m_activeWidget == widget)) { return; } KParts::Part *oldActivePart = d->m_activePart; QWidget *oldActiveWidget = d->m_activeWidget; setSelectedPart(nullptr); d->m_activePart = part; d->m_activeWidget = widget; if (oldActivePart) { KParts::Part *savedActivePart = part; QWidget *savedActiveWidget = widget; PartActivateEvent ev(false, oldActivePart, oldActiveWidget); QApplication::sendEvent(oldActivePart, &ev); if (oldActiveWidget) { disconnect(oldActiveWidget, &QWidget::destroyed, this, &PartManager::slotWidgetDestroyed); QApplication::sendEvent(oldActiveWidget, &ev); } d->m_activePart = savedActivePart; d->m_activeWidget = savedActiveWidget; } if (d->m_activePart) { if (!widget) { d->m_activeWidget = part->widget(); } PartActivateEvent ev(true, d->m_activePart, d->m_activeWidget); QApplication::sendEvent(d->m_activePart, &ev); if (d->m_activeWidget) { connect(d->m_activeWidget, &QWidget::destroyed, this, &PartManager::slotWidgetDestroyed); QApplication::sendEvent(d->m_activeWidget, &ev); } } // Set the new active instance //setActiveComponent(d->m_activePart ? d->m_activePart->componentData() : KComponentData::mainComponent()); - qCDebug(KPartsLog) << this << "emitting activePartChanged" << d->m_activePart; + qCDebug(KPARTSLOG) << this << "emitting activePartChanged" << d->m_activePart; emit activePartChanged(d->m_activePart); } Part *PartManager::activePart() const { return d->m_activePart; } QWidget *PartManager::activeWidget() const { return d->m_activeWidget; } void PartManager::setSelectedPart(Part *part, QWidget *widget) { if (part == d->m_selectedPart && widget == d->m_selectedWidget) { return; } Part *oldPart = d->m_selectedPart; QWidget *oldWidget = d->m_selectedWidget; d->m_selectedPart = part; d->m_selectedWidget = widget; if (part && !widget) { d->m_selectedWidget = part->widget(); } if (oldPart) { PartSelectEvent ev(false, oldPart, oldWidget); QApplication::sendEvent(oldPart, &ev); QApplication::sendEvent(oldWidget, &ev); } if (d->m_selectedPart) { PartSelectEvent ev(true, d->m_selectedPart, d->m_selectedWidget); QApplication::sendEvent(d->m_selectedPart, &ev); QApplication::sendEvent(d->m_selectedWidget, &ev); } } Part *PartManager::selectedPart() const { return d->m_selectedPart; } QWidget *PartManager::selectedWidget() const { return d->m_selectedWidget; } void PartManager::slotObjectDestroyed() { // qDebug(); removePart(const_cast(static_cast(sender()))); } void PartManager::slotWidgetDestroyed() { // qDebug(); if (static_cast(sender()) == d->m_activeWidget) { setActivePart(nullptr); //do not remove the part because if the part's widget dies, then the } //part will delete itself anyway, invoking removePart() in its destructor } const QList PartManager::parts() const { return d->m_parts; } void PartManager::addManagedTopLevelWidget(const QWidget *topLevel) { if (!topLevel->isTopLevel()) { return; } if (d->m_managedTopLevelWidgets.contains(topLevel)) { return; } d->m_managedTopLevelWidgets.append(topLevel); connect(topLevel, &QWidget::destroyed, this, &PartManager::slotManagedTopLevelWidgetDestroyed); } void PartManager::removeManagedTopLevelWidget(const QWidget *topLevel) { d->m_managedTopLevelWidgets.removeAll(topLevel); } void PartManager::slotManagedTopLevelWidgetDestroyed() { const QWidget *widget = static_cast(sender()); removeManagedTopLevelWidget(widget); } int PartManager::reason() const { return d->m_reason; } void PartManager::setIgnoreExplictFocusRequests(bool ignore) { d->m_bIgnoreExplicitFocusRequest = ignore; }