diff --git a/CMakeLists.txt b/CMakeLists.txt index e1de82d..a1ecb9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,100 +1,100 @@ cmake_minimum_required(VERSION 3.5) set(KF5_VERSION "5.71.0") # handled by release scripts set(KF5_DEP_VERSION "5.70.0") # handled by release scripts project(KParts VERSION ${KF5_VERSION}) include(FeatureSummary) find_package(ECM 5.70.0 NO_MODULE) set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://commits.kde.org/extra-cmake-modules") feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) include(KDEInstallDirs) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(KDECMakeSettings) include(KDEPackageAppTemplates) include(ECMAddQch) include(ECMGenerateExportHeader) - +include(ECMQtDeclareLoggingCategory) include(ECMSetupVersion) set(EXCLUDE_DEPRECATED_BEFORE_AND_AT 0 CACHE STRING "Control how much of deprecated API is build [default=0].") option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)" OFF) add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)") ecm_setup_version(PROJECT VARIABLE_PREFIX KPARTS VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kparts_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5PartsConfigVersion.cmake" SOVERSION 5) set(REQUIRED_QT_VERSION 5.12.0) find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Core Widgets Xml) find_package(KF5Config ${KF5_DEP_VERSION} REQUIRED) find_package(KF5CoreAddons ${KF5_DEP_VERSION} REQUIRED) find_package(KF5I18n ${KF5_DEP_VERSION} REQUIRED) find_package(KF5IconThemes ${KF5_DEP_VERSION} REQUIRED) find_package(KF5KIO ${KF5_DEP_VERSION} REQUIRED) find_package(KF5JobWidgets ${KF5_DEP_VERSION} REQUIRED) find_package(KF5Service ${KF5_DEP_VERSION} REQUIRED) find_package(KF5TextWidgets ${KF5_DEP_VERSION} REQUIRED) find_package(KF5WidgetsAddons ${KF5_DEP_VERSION} REQUIRED) find_package(KF5XmlGui ${KF5_DEP_VERSION} REQUIRED) if(BUILD_TESTING) add_subdirectory( tests ) add_subdirectory( autotests ) endif() add_definitions(-DTRANSLATION_DOMAIN=\"kparts5\") if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po") ki18n_install(po) endif() add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050d00) add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x054700) add_definitions(-DKIOWIDGETS_DISABLE_DEPRECATED_BEFORE_AND_AT=0x054600) # We need KRun for BrowserRun add_definitions(-DQT_NO_FOREACH) add_subdirectory( src ) add_subdirectory(templates) # create a Config.cmake and a ConfigVersion.cmake file and install them set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5Parts") if (BUILD_QCH) ecm_install_qch_export( TARGETS KF5Parts_QCH FILE KF5PartsQchTargets.cmake DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) set(PACKAGE_INCLUDE_QCHTARGETS "include(\"\${CMAKE_CURRENT_LIST_DIR}/KF5PartsQchTargets.cmake\")") endif() include(CMakePackageConfigHelpers) configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/KF5PartsConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KF5PartsConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KF5PartsConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KF5PartsConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) install(EXPORT KF5PartsTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5PartsTargets.cmake NAMESPACE KF5:: ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kparts_version.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5} COMPONENT Devel ) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 38c7fa7..91c7457 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,156 +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 + CATEGORY_NAME kf.parts + DESCRIPTION "KParts" + 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 + 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 a355ee0..5a32bd8 100644 --- a/src/part.cpp +++ b/src/part.cpp @@ -1,213 +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 "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); - //qDebug() << 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) { - // qDebug() << "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) { - // qDebug() << "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 2965ad9..3603514 100644 --- a/src/partmanager.cpp +++ b/src/partmanager.cpp @@ -1,591 +1,584 @@ /* 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 "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); -#ifdef DEBUG_PARTMANAGER - qDebug() << "PartManager::eventFilter button: " << mev->button() << " " << "d->m_activationButtonMask=" << d->m_activationButtonMask; -#endif + + 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); } -#ifdef DEBUG_PARTMANAGER const char *evType = (ev->type() == QEvent::MouseButtonPress) ? "MouseButtonPress" : (ev->type() == QEvent::MouseButtonDblClick) ? "MouseButtonDblClick" : (ev->type() == QEvent::FocusIn) ? "FocusIn" : "OTHER! ERROR!"; -#endif + 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; } -#ifdef DEBUG_PARTMANAGER - qDebug() << "PartManager::eventFilter dblclick -> setActivePart" << part; -#endif + 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 { -#ifdef DEBUG_PARTMANAGER - qDebug() << "Part " << part << " (non-selectable) made active because " << w->metaObject()->className() << " got event" << " " << evType; -#endif + 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) { -#ifdef DEBUG_PARTMANAGER - qDebug() << "Part " << part << " made active (from selected) because " << w->metaObject()->className() << " got event" << " " << evType; -#endif + 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)) { -#ifdef DEBUG_PARTMANAGER - qDebug() << "Part " << part << " made active because " << w->metaObject()->className() << " got event" << " " << evType; -#endif + 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))) { -#ifdef DEBUG_PARTMANAGER - qDebug() << QString("No part made active although %1/%2 got event - loop aborted").arg(obj->objectName()).arg(obj->metaObject()->className()); -#endif + + qCDebug(KPartsLog) << "No part made active although" << obj->objectName() << "/" << obj->metaObject()->className() + << "got event - loop aborted"; + return false; } } -#ifdef DEBUG_PARTMANAGER - qDebug() << QString("No part made active although %1/%2 got event").arg(obj->objectName()).arg(obj->metaObject()->className()); -#endif + 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) { - //qDebug() << "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; } } -#ifdef DEBUG_PARTMANAGER - qDebug() << "PartManager::setActivePart d->m_activePart=" << d->m_activePart << "<->part=" << part - << " d->m_activeWidget=" << d->m_activeWidget << "<->widget=" << widget; -#endif + 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()); -#ifdef DEBUG_PARTMANAGER - qDebug() << this << " emitting activePartChanged " << d->m_activePart; -#endif + 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; }