Changeset View
Changeset View
Standalone View
Standalone View
src/widgets/krun.cpp
Show First 20 Lines • Show All 118 Lines • ▼ Show 20 Line(s) | |||||
119 | 119 | | |||
120 | static bool checkNeedPortalSupport() | 120 | static bool checkNeedPortalSupport() | ||
121 | { | 121 | { | ||
122 | return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, | 122 | return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, | ||
123 | QLatin1String("flatpak-info")).isEmpty() || | 123 | QLatin1String("flatpak-info")).isEmpty() || | ||
124 | qEnvironmentVariableIsSet("SNAP"); | 124 | qEnvironmentVariableIsSet("SNAP"); | ||
125 | } | 125 | } | ||
126 | 126 | | |||
127 | static qint64 runProcessRunner(KProcess *p, const QString &executable, const KStartupInfoId &id, QWidget *widget) | ||||
128 | { | ||||
129 | auto *processRunner = new KProcessRunner(p, executable, id); | ||||
130 | QObject::connect(processRunner, &KProcessRunner::error, widget, [widget](const QString &errorString) { | ||||
131 | QEventLoopLocker locker; | ||||
132 | KMessageBox::sorry(widget, errorString); | ||||
133 | }); | ||||
134 | return processRunner->pid(); | ||||
135 | } | ||||
136 | | ||||
127 | // --------------------------------------------------------------------------- | 137 | // --------------------------------------------------------------------------- | ||
128 | 138 | | |||
129 | bool KRun::isExecutableFile(const QUrl &url, const QString &mimetype) | 139 | bool KRun::isExecutableFile(const QUrl &url, const QString &mimetype) | ||
130 | { | 140 | { | ||
131 | if (!url.isLocalFile()) { | 141 | if (!url.isLocalFile()) { | ||
132 | return false; | 142 | return false; | ||
133 | } | 143 | } | ||
134 | QFileInfo file(url.toLocalFile()); | 144 | QFileInfo file(url.toLocalFile()); | ||
▲ Show 20 Lines • Show All 223 Lines • ▼ Show 20 Line(s) | 341 | if (startup_notify) { | |||
358 | if (window && window->window()) { | 368 | if (window && window->window()) { | ||
359 | data.setLaunchedBy(window->window()->winId()); | 369 | data.setLaunchedBy(window->window()->winId()); | ||
360 | } | 370 | } | ||
361 | if (service && !service->entryPath().isEmpty()) { | 371 | if (service && !service->entryPath().isEmpty()) { | ||
362 | data.setApplicationId(service->entryPath()); | 372 | data.setApplicationId(service->entryPath()); | ||
363 | } | 373 | } | ||
364 | KStartupInfo::sendStartup(id, data); | 374 | KStartupInfo::sendStartup(id, data); | ||
365 | } | 375 | } | ||
366 | qint64 pid = KProcessRunner::run(proc, executable, id); | 376 | const qint64 pid = runProcessRunner(proc, executable, id, window); | ||
367 | if (startup_notify && pid) { | 377 | if (startup_notify && pid) { | ||
368 | KStartupInfoData data; | 378 | KStartupInfoData data; | ||
369 | data.addPid(pid); | 379 | data.addPid(pid); | ||
370 | KStartupInfo::sendChange(id, data); | 380 | KStartupInfo::sendChange(id, data); | ||
371 | KStartupInfo::resetStartupEnv(); | 381 | KStartupInfo::resetStartupEnv(); | ||
372 | } | 382 | } | ||
373 | return pid; | 383 | return pid; | ||
374 | } | 384 | } | ||
375 | #else | 385 | #else | ||
376 | Q_UNUSED(userVisibleName); | 386 | Q_UNUSED(userVisibleName); | ||
377 | Q_UNUSED(iconName); | 387 | Q_UNUSED(iconName); | ||
378 | #endif | 388 | #endif | ||
379 | return KProcessRunner::run(proc, bin, KStartupInfoId()); | 389 | return runProcessRunner(proc, bin, KStartupInfoId(), window); | ||
380 | } | 390 | } | ||
381 | 391 | | |||
382 | // This code is also used in klauncher. | 392 | // This code is also used in klauncher. | ||
383 | bool KRun::checkStartupNotify(const QString & /*binName*/, const KService *service, bool *silent_arg, QByteArray *wmclass_arg) | 393 | bool KRun::checkStartupNotify(const QString & /*binName*/, const KService *service, bool *silent_arg, QByteArray *wmclass_arg) | ||
384 | { | 394 | { | ||
385 | bool silent = false; | 395 | bool silent = false; | ||
386 | QByteArray wmclass; | 396 | QByteArray wmclass; | ||
387 | if (service && service->property(QStringLiteral("StartupNotify")).isValid()) { | 397 | if (service && service->property(QStringLiteral("StartupNotify")).isValid()) { | ||
▲ Show 20 Lines • Show All 1198 Lines • ▼ Show 20 Line(s) | |||||
1586 | 1596 | | |||
1587 | bool KRun::isLocalFile() const | 1597 | bool KRun::isLocalFile() const | ||
1588 | { | 1598 | { | ||
1589 | return d->m_strURL.isLocalFile(); | 1599 | return d->m_strURL.isLocalFile(); | ||
1590 | } | 1600 | } | ||
1591 | 1601 | | |||
1592 | /****************/ | 1602 | /****************/ | ||
1593 | 1603 | | |||
1594 | qint64 KProcessRunner::run(KProcess *p, const QString &executable, const KStartupInfoId &id) | | |||
1595 | { | | |||
1596 | return (new KProcessRunner(p, executable, id))->pid(); | | |||
1597 | } | | |||
1598 | | ||||
1599 | KProcessRunner::KProcessRunner(KProcess *p, const QString &executable, const KStartupInfoId &id) : | 1604 | KProcessRunner::KProcessRunner(KProcess *p, const QString &executable, const KStartupInfoId &id) : | ||
1600 | id(id) | 1605 | id(id) | ||
1601 | { | 1606 | { | ||
1602 | m_pid = 0; | 1607 | m_pid = 0; | ||
1603 | process = p; | 1608 | process = p; | ||
1604 | m_executable = executable; | 1609 | m_executable = executable; | ||
1605 | connect(process, QOverload<int,QProcess::ExitStatus>::of(&QProcess::finished), | 1610 | connect(process, QOverload<int,QProcess::ExitStatus>::of(&QProcess::finished), | ||
1606 | this, &KProcessRunner::slotProcessExited); | 1611 | this, &KProcessRunner::slotProcessExited); | ||
1607 | 1612 | | |||
1608 | process->start(); | 1613 | process->start(); | ||
1609 | if (!process->waitForStarted()) { | 1614 | if (!process->waitForStarted()) { | ||
1610 | //qDebug() << "wait for started failed, exitCode=" << process->exitCode() | 1615 | //qDebug() << "wait for started failed, exitCode=" << process->exitCode() | ||
1611 | // << "exitStatus=" << process->exitStatus(); | 1616 | // << "exitStatus=" << process->exitStatus(); | ||
1612 | // Note that exitCode is 255 here (the first time), and 0 later on (bug?). | 1617 | // Note that exitCode is 255 here (the first time), and 0 later on (bug?). | ||
1618 | | ||||
1619 | // Use delayed invocation so the caller has time to connect to the signal | ||||
1620 | QMetaObject::invokeMethod(this, [this]() { | ||||
1613 | slotProcessExited(255, process->exitStatus()); | 1621 | slotProcessExited(255, process->exitStatus()); | ||
1622 | }, Qt::QueuedConnection); | ||||
1614 | } else { | 1623 | } else { | ||
1615 | m_pid = process->processId(); | 1624 | m_pid = process->processId(); | ||
1616 | } | 1625 | } | ||
1617 | } | 1626 | } | ||
1618 | 1627 | | |||
1619 | KProcessRunner::~KProcessRunner() | 1628 | KProcessRunner::~KProcessRunner() | ||
1620 | { | 1629 | { | ||
1621 | delete process; | 1630 | delete process; | ||
Show All 28 Lines | 1653 | { | |||
1650 | if (exitCode != 0 && !m_executable.isEmpty()) { | 1659 | if (exitCode != 0 && !m_executable.isEmpty()) { | ||
1651 | // Let's see if the error is because the exe doesn't exist. | 1660 | // Let's see if the error is because the exe doesn't exist. | ||
1652 | // When this happens, waitForStarted returns false, but not if kioexec | 1661 | // When this happens, waitForStarted returns false, but not if kioexec | ||
1653 | // was involved, then we come here, that's why the code is here. | 1662 | // was involved, then we come here, that's why the code is here. | ||
1654 | // | 1663 | // | ||
1655 | // We'll try to find the executable relatively to current directory, | 1664 | // We'll try to find the executable relatively to current directory, | ||
1656 | // (or with a full path, if m_executable is absolute), and then in the PATH. | 1665 | // (or with a full path, if m_executable is absolute), and then in the PATH. | ||
1657 | if (!QFile(m_executable).exists() && QStandardPaths::findExecutable(m_executable).isEmpty()) { | 1666 | if (!QFile(m_executable).exists() && QStandardPaths::findExecutable(m_executable).isEmpty()) { | ||
1658 | const QString &error = i18n("Could not find the program '%1'", m_executable); | 1667 | const QString &errorString = i18n("Could not find the program '%1'", m_executable); | ||
1659 | 1668 | qWarning() << errorString; | |||
1660 | if (qApp) { | 1669 | emit error(errorString); | ||
1661 | QTimer::singleShot(0, qApp, [=]() { | | |||
1662 | QEventLoopLocker locker; | | |||
1663 | KMessageBox::sorry(nullptr, error); | | |||
1664 | }); | | |||
1665 | } else { | | |||
1666 | qWarning() << error; | | |||
1667 | } | | |||
1668 | } else { | 1670 | } else { | ||
1669 | //qDebug() << process->readAllStandardError(); | 1671 | //qDebug() << process->readAllStandardError(); | ||
1670 | } | 1672 | } | ||
1671 | } | 1673 | } | ||
1672 | 1674 | | |||
1673 | deleteLater(); | 1675 | deleteLater(); | ||
1674 | } | 1676 | } | ||
1675 | 1677 | | |||
1676 | #include "moc_krun.cpp" | 1678 | #include "moc_krun.cpp" | ||
1677 | #include "moc_krun_p.cpp" | 1679 | #include "moc_krun_p.cpp" | ||
1678 | #include "krun.moc" | 1680 | #include "krun.moc" |