diff --git a/src/core/kprotocolinfofactory.cpp b/src/core/kprotocolinfofactory.cpp --- a/src/core/kprotocolinfofactory.cpp +++ b/src/core/kprotocolinfofactory.cpp @@ -75,6 +75,7 @@ fillCache(); KProtocolInfoPrivate *info = m_cache.value(protocol); if (!info) { + qDebug() << "wiping cache" << protocol; // Unknown protocol! Maybe it just got installed and our cache is out of date? qCDebug(KIO_CORE) << "Refilling KProtocolInfoFactory cache in the hope to find" << protocol; m_allProtocolsLoaded = false; diff --git a/src/widgets/jobuidelegate.h b/src/widgets/jobuidelegate.h --- a/src/widgets/jobuidelegate.h +++ b/src/widgets/jobuidelegate.h @@ -29,6 +29,8 @@ #include #include +class QWindow; + class KJob; namespace KIO { @@ -55,23 +57,70 @@ virtual ~JobUiDelegate(); public: + /** + * Associate this job with a widget given by @p widget. The + * widget should be a top-level widget (i.e. a window). + * @param widget the window to associate to + * @see widget() + * @since 5.43 + */ + void setWidget(QWidget *widget) Q_DECL_OVERRIDE; + + /** + * Unregister the given widget from kded. The widget should be a + * top-level widget (i.e. a window). + * This is normally done automatically when the window is destroyed. + * + * This method is useful for instance when keeping a hidden window + * around to make it faster to reuse later. + * @since 5.43 + */ + static void unregisterWidget(QWidget *widget); + + /** + * Associate this job with a window given by @p window. + * @param window the window to associate to + * @see qWindow() + * @since 5.43 + * TODO KF6: Rename to setWindow + */ + void setQWindow(QWindow *window) Q_DECL_OVERRIDE; + + /** + * Unregister the given window from kded. + * This is normally done automatically when the window is destroyed. + * + * This method is useful for instance when keeping a hidden window + * around to make it faster to reuse later. + * @since 5.43 + * TODO KF6: Rename to unregisterWindow + */ + static void unregisterQWindow(QWindow *window); /** * Associate this job with a window given by @p window. * @param window the window to associate to * @see window() + * @deprecated Use JobUiDelegate::setWidget or JobUiDelegate::setQWindow instead + * TODO KF6: Remove */ +#ifndef KIOWIDGETS_NO_DEPRECATED void setWindow(QWidget *window) Q_DECL_OVERRIDE; +#endif /** * Unregister the given window from kded. * This is normally done automatically when the window is destroyed. * * This method is useful for instance when keeping a hidden window * around to make it faster to reuse later. * @since 5.2 + * @deprecated Use JobUiDelegate::unregisterWidget or JobUiDelegate::unregisterQWindow instead + * TODO KF6: Remove */ +#ifndef KIOWIDGETS_NO_DEPRECATED static void unregisterWindow(QWidget *window); +#endif /** * \relates KIO::RenameDialog diff --git a/src/widgets/jobuidelegate.cpp b/src/widgets/jobuidelegate.cpp --- a/src/widgets/jobuidelegate.cpp +++ b/src/widgets/jobuidelegate.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -70,53 +71,53 @@ file dialog it encountered since it is the "next ancestor widget that has (or could have) a window-system frame". */ -static QWidget *topLevelWindow(QWidget *widget) +static QWindow *topLevelWindow(QWindow *window) { - QWidget *w = widget; - while (w && w->parentWidget()) { - w = w->parentWidget(); + QWindow *w = window; + while (w && w->parent()) { + w = w->parent(); } - return (w ? w->window() : nullptr); + return w; } class JobUiDelegateStatic : public QObject { Q_OBJECT public: - void registerWindow(QWidget *wid) + void registerQWindow(QWindow *wid) { if (!wid) { return; } - QWidget *window = topLevelWindow(wid); + QWindow *window = topLevelWindow(wid); QObject *obj = static_cast(window); if (!m_windowList.contains(obj)) { // We must store the window Id because by the time // the destroyed signal is emitted we can no longer // access QWidget::winId() (already destructed) WId windowId = window->winId(); m_windowList.insert(obj, windowId); connect(window, SIGNAL(destroyed(QObject*)), - this, SLOT(slotUnregisterWindow(QObject*))); + this, SLOT(slotUnregisterQWindow(QObject*))); QDBusInterface(QStringLiteral("org.kde.kded5"), QStringLiteral("/kded"), QStringLiteral("org.kde.kded5")). call(QDBus::NoBlock, QStringLiteral("registerWindowId"), qlonglong(windowId)); } } public Q_SLOTS: - void slotUnregisterWindow(QObject *obj) + void slotUnregisterQWindow(QWindow *window) { - if (!obj) { + if (!window) { return; } - QMap::Iterator it = m_windowList.find(obj); + QMap::Iterator it = m_windowList.find(window); if (it == m_windowList.end()) { return; } WId windowId = it.value(); disconnect(it.key(), SIGNAL(destroyed(QObject*)), - this, SLOT(slotUnregisterWindow(QObject*))); + this, SLOT(slotUnregisterQWindow(QObject*))); m_windowList.erase(it); QDBusInterface(QStringLiteral("org.kde.kded5"), QStringLiteral("/kded"), QStringLiteral("org.kde.kded5")). call(QDBus::NoBlock, QStringLiteral("unregisterWindowId"), qlonglong(windowId)); @@ -127,16 +128,38 @@ Q_GLOBAL_STATIC(JobUiDelegateStatic, s_static) +void KIO::JobUiDelegate::setWidget(QWidget *widget) +{ + setQWindow(widget->windowHandle()); +} + +void KIO::JobUiDelegate::unregisterWidget(QWidget *widget) +{ + s_static()->slotUnregisterQWindow(widget->windowHandle()); +} + +void KIO::JobUiDelegate::setQWindow(QWindow *window) +{ + KDialogJobUiDelegate::setQWindow(window); + s_static()->registerQWindow(window); +} + +void KIO::JobUiDelegate::unregisterQWindow(QWindow *window) +{ + s_static()->slotUnregisterQWindow(window); +} + +#ifndef KIOWIDGETS_NO_DEPRECATED void KIO::JobUiDelegate::setWindow(QWidget *window) { - KDialogJobUiDelegate::setWindow(window); - s_static()->registerWindow(window); + setWidget(window); } void KIO::JobUiDelegate::unregisterWindow(QWidget *window) { - s_static()->slotUnregisterWindow(window); + unregisterWidget(window); } +#endif KIO::RenameDialog_Result KIO::JobUiDelegate::askFileRename(KJob *job, const QString &caption, @@ -154,6 +177,7 @@ //qDebug() << "job=" << job; // We now do it in process, so that opening the rename dialog // doesn't start uiserver for nothing if progressId=0 (e.g. F2 in konq) + // FIXME KF6: RenameDialog doesn't take a QWindow; KJobWidgets::window may not have a widget to return KIO::RenameDialog dlg(KJobWidgets::window(job), caption, src, dest, options, sizeSrc, sizeDest, ctimeSrc, ctimeDest, mtimeSrc, @@ -173,6 +197,7 @@ KIO::SkipDialog_Options options, const QString &error_text) { + // FIXME KF6: RenameDialog doesn't take a QWindow; KJobWidgets::window may not have a widget to return KIO::SkipDialog dlg(KJobWidgets::window(job), options, error_text); dlg.setWindowModality(Qt::WindowModal); connect(job, SIGNAL(finished(KJob*)), &dlg, SLOT(reject())); // #192976 @@ -219,23 +244,24 @@ } } + qDebug() << qWindow() << qWindow()->winId(); + int result; - QWidget *widget = window(); const KMessageBox::Options options(KMessageBox::Notify | KMessageBox::WindowModal); switch (deletionType) { case Delete: - result = KMessageBox::warningContinueCancelList( - widget, + result = KMessageBox::warningContinueCancelListWId( + qWindow()->winId(), i18np("Do you really want to delete this item?", "Do you really want to delete these %1 items?", prettyList.count()), prettyList, i18n("Delete Files"), KStandardGuiItem::del(), KStandardGuiItem::cancel(), keyName, options); break; case EmptyTrash: - result = KMessageBox::warningContinueCancel( - widget, + result = KMessageBox::warningContinueCancelWId( + qWindow()->winId(), i18nc("@info", "Do you want to permanently delete all items from Trash? This action cannot be undone."), QString(), KGuiItem(i18nc("@action:button", "Empty Trash"), @@ -245,8 +271,8 @@ break; case Trash: default: - result = KMessageBox::warningContinueCancelList( - widget, + result = KMessageBox::warningContinueCancelListWId( + qWindow()->winId(), i18np("Do you really want to move this item to the trash?", "Do you really want to move these %1 items to the trash?", prettyList.count()), prettyList, i18n("Move to Trash"), @@ -291,31 +317,32 @@ switch (type) { case QuestionYesNo: - result = KMessageBox::questionYesNo( - window(), text, caption, buttonYesGui, + result = KMessageBox::questionYesNoWId( + qWindow()->winId(), text, caption, buttonYesGui, buttonNoGui, dontAskAgainName, options); break; case WarningYesNo: - result = KMessageBox::warningYesNo( - window(), text, caption, buttonYesGui, + result = KMessageBox::warningYesNoWId( + qWindow()->winId(), text, caption, buttonYesGui, buttonNoGui, dontAskAgainName, options | KMessageBox::Dangerous); break; case WarningYesNoCancel: - result = KMessageBox::warningYesNoCancel( - window(), text, caption, buttonYesGui, buttonNoGui, + result = KMessageBox::warningYesNoCancelWId( + qWindow()->winId(), text, caption, buttonYesGui, buttonNoGui, KStandardGuiItem::cancel(), dontAskAgainName, options); break; case WarningContinueCancel: - result = KMessageBox::warningContinueCancel( - window(), text, caption, buttonYesGui, + result = KMessageBox::warningContinueCancelWId( + qWindow()->winId(), text, caption, buttonYesGui, KStandardGuiItem::cancel(), dontAskAgainName, options); break; case Information: - KMessageBox::information(window(), text, caption, dontAskAgainName, options); + KMessageBox::informationWId(qWindow()->winId(), text, caption, dontAskAgainName, options); result = 1; // whatever break; case SSLMessageBox: { + // FIXME KF6: KSslInfoDialog doesn't take a QWindow; window() might not have a widget to return QPointer kid(new KSslInfoDialog(window())); //### this is boilerplate code and appears in khtml_part.cpp almost unchanged! const QStringList sl = sslMetaData.value(QStringLiteral("ssl_peer_chain")).split('\x01', QString::SkipEmptyParts); @@ -342,7 +369,7 @@ kid->exec(); } else { result = -1; - KMessageBox::information(window(), + KMessageBox::informationWId(qWindow()->winId(), i18n("The peer SSL certificate chain appears to be corrupt."), i18n("SSL"), QString(), options); } diff --git a/src/widgets/krun.cpp b/src/widgets/krun.cpp --- a/src/widgets/krun.cpp +++ b/src/widgets/krun.cpp @@ -319,6 +319,14 @@ return 0; } + // Don't proceed if we can't find the executable. + if (!QFile(executable).exists() && QStandardPaths::findExecutable(executable).isEmpty()) { + QEventLoopLocker locker; + KMessageBox::sorry(nullptr, i18n("Could not find the program '%1'", executable)); + delete proc; + return 0; + } + QString bin = KIO::DesktopExecParser::executableName(executable); #if HAVE_X11 // Startup notification doesn't work with QT/E, service isn't needed without Startup notification static bool isX11 = QGuiApplication::platformName() == QStringLiteral("xcb"); @@ -1602,23 +1610,11 @@ KProcessRunner::slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus) { //qDebug() << m_executable << "exitCode=" << exitCode << "exitStatus=" << exitStatus; - Q_UNUSED(exitStatus); + Q_UNUSED(exitCode) + Q_UNUSED(exitStatus) terminateStartupNotification(); // do this before the messagebox - if (exitCode != 0 && !m_executable.isEmpty()) { - // Let's see if the error is because the exe doesn't exist. - // When this happens, waitForStarted returns false, but not if kioexec - // was involved, then we come here, that's why the code is here. - // - // We'll try to find the executable relatively to current directory, - // (or with a full path, if m_executable is absolute), and then in the PATH. - if (!QFile(m_executable).exists() && QStandardPaths::findExecutable(m_executable).isEmpty()) { - QEventLoopLocker locker; - KMessageBox::sorry(nullptr, i18n("Could not find the program '%1'", m_executable)); - } else { - //qDebug() << process->readAllStandardError(); - } - } + deleteLater(); }