diff --git a/startkde/kcminit/main.cpp b/startkde/kcminit/main.cpp index e4f42d5ce..5b0912b25 100644 --- a/startkde/kcminit/main.cpp +++ b/startkde/kcminit/main.cpp @@ -1,252 +1,252 @@ /* Copyright (c) 1999 Matthias Hoelzer-Kluepfel This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include "main.h" #include "klauncher_iface.h" #ifdef XCB_FOUND #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int ready[ 2 ]; static bool startup = false; static void sendReady() { if( ready[ 1 ] == -1 ) return; char c = 0; write( ready[ 1 ], &c, 1 ); close( ready[ 1 ] ); ready[ 1 ] = -1; } static void waitForReady() { char c = 1; close( ready[ 1 ] ); read( ready[ 0 ], &c, 1 ); close( ready[ 0 ] ); } bool KCMInit::runModule(const QString &libName, KService::Ptr service) { QString KCMINIT_PREFIX=QStringLiteral("kcminit_"); const QVariant tmp = service->property(QStringLiteral("X-KDE-Init-Symbol"), QVariant::String); QString kcminit; if( tmp.isValid() ) { kcminit = tmp.toString(); if( !kcminit.startsWith( KCMINIT_PREFIX ) ) kcminit = KCMINIT_PREFIX + kcminit; } else kcminit = KCMINIT_PREFIX + libName; QString path = KPluginLoader::findPlugin(libName); if (path.isEmpty()) { path = KPluginLoader::findPlugin(QStringLiteral("kcms/") + libName); } if (path.isEmpty()) { qWarning() << "Module" << libName << "was not found"; return false; } // get the kcminit_ function QFunctionPointer init = QLibrary::resolve(path, kcminit.toUtf8().constData()); if (!init) { qWarning() << "Module" << libName << "does not actually have a kcminit function"; return false; } // initialize the module qDebug() << "Initializing " << libName << ": " << kcminit; init(); return true; } void KCMInit::runModules( int phase ) { QString KCMINIT_PREFIX=QStringLiteral("kcminit_"); - foreach (const KService::Ptr & service, list) { + for (const KService::Ptr & service : qAsConst(m_list)) { const QVariant tmp = service->property(QStringLiteral("X-KDE-Init-Library"), QVariant::String); QString library; if( tmp.isValid() ) { library = tmp.toString(); if( !library.startsWith( KCMINIT_PREFIX ) ) library = KCMINIT_PREFIX + library; } else { library = service->library(); } if (library.isEmpty()) { qWarning() << Q_FUNC_INFO << "library is empty, skipping"; continue; // Skip } // see ksmserver's README for the description of the phases const QVariant vphase = service->property(QStringLiteral("X-KDE-Init-Phase"), QVariant::Int ); int libphase = 1; if( vphase.isValid() ) libphase = vphase.toInt(); if( phase != -1 && libphase != phase ) continue; // try to load the library - if (!alreadyInitialized.contains(library)) { + if (!m_alreadyInitialized.contains(library)) { runModule(library, service); - alreadyInitialized.insert(library); + m_alreadyInitialized.insert(library); } } } KCMInit::KCMInit( const QCommandLineParser& args ) { QString arg; if (args.positionalArguments().size() == 1) { arg = args.positionalArguments().first(); } if (args.isSet(QStringLiteral("list"))) { - list = KServiceTypeTrader::self()->query( QStringLiteral("KCModuleInit") ); + m_list = KServiceTypeTrader::self()->query( QStringLiteral("KCModuleInit") ); - foreach (const KService::Ptr & service, list) { + for (const KService::Ptr &service : qAsConst(m_list)) { if (service->library().isEmpty()) continue; // Skip printf("%s\n", QFile::encodeName(service->desktopEntryName()).data()); } return; } if (!arg.isEmpty()) { QString module = arg; if (!module.endsWith(QLatin1String(".desktop"))) module += QLatin1String(".desktop"); KService::Ptr serv = KService::serviceByStorageId( module ); if ( !serv || serv->library().isEmpty() ) { qCritical() << i18n("Module %1 not found", module); return; } else { - list.append(serv); + m_list.append(serv); } } else { // locate the desktop files - list = KServiceTypeTrader::self()->query( QStringLiteral("KCModuleInit") ); + m_list = KServiceTypeTrader::self()->query( QStringLiteral("KCModuleInit") ); } if( startup ) { runModules( 0 ); // Tell KSplash that KCMInit has started QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"), QStringLiteral("/KSplash"), QStringLiteral("org.kde.KSplash"), QStringLiteral("setStage")); ksplashProgressMessage.setArguments(QList() << QStringLiteral("kcminit")); QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage); sendReady(); QTimer::singleShot( 300 * 1000, qApp, &QCoreApplication::quit); // just in case QDBusConnection::sessionBus().registerObject(QStringLiteral("/kcminit"), this, QDBusConnection::ExportScriptableContents); QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.kcminit")); qApp->exec(); // wait for runPhase1() and runPhase2() } else runModules( -1 ); // all phases } KCMInit::~KCMInit() { sendReady(); } void KCMInit::runPhase1() { runModules( 1 ); } void KCMInit::runPhase2() { runModules( 2 ); qApp->exit( 0 ); } extern "C" Q_DECL_EXPORT int kdemain(int argc, char *argv[]) { // kdeinit waits for kcminit to finish, but during KDE startup // only important kcm's are started very early in the login process, // the rest is delayed, so fork and make parent return after the initial phase pipe( ready ); if( fork() != 0 ) { waitForReady(); return 0; } close( ready[ 0 ] ); startup = ( strcmp( argv[ 0 ], "kcminit_startup" ) == 0 ); // started from startkde? KWorkSpace::detectPlatform(argc, argv); QGuiApplication::setDesktopSettingsAware(false); QGuiApplication app(argc, argv); //gui is needed for several modules KLocalizedString::setApplicationDomain("kcminit"); KAboutData about(QStringLiteral("kcminit"), i18n("KCMInit"), QString(), i18n("KCMInit - runs startup initialization for Control Modules."), KAboutLicense::GPL); KAboutData::setApplicationData(about); QCommandLineParser parser; about.setupCommandLine(&parser); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("list"), i18n("List modules that are run at startup"))); parser.addPositionalArgument(QStringLiteral("module"), i18n("Configuration module to run")); parser.process(app); about.processCommandLine(&parser); KCMInit kcminit( parser ); return 0; } diff --git a/startkde/kcminit/main.h b/startkde/kcminit/main.h index cafb303e8..4e341f62d 100644 --- a/startkde/kcminit/main.h +++ b/startkde/kcminit/main.h @@ -1,46 +1,46 @@ /* Copyright (c) 1999 Matthias Hoelzer-Kluepfel This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAIN_H #define MAIN_H #include #include #include class KCMInit : public QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.KCMInit") public Q_SLOTS: //dbus Q_SCRIPTABLE void runPhase1(); Q_SCRIPTABLE void runPhase2(); public: explicit KCMInit( const QCommandLineParser& args ); ~KCMInit() override; private: bool runModule(const QString &libName, KService::Ptr service); void runModules( int phase ); - KService::List list; - QSet alreadyInitialized; + KService::List m_list; + QSet m_alreadyInitialized; }; #endif // MAIN_H diff --git a/startkde/plasma-session/main.cpp b/startkde/plasma-session/main.cpp index 92932db81..9bea801e6 100644 --- a/startkde/plasma-session/main.cpp +++ b/startkde/plasma-session/main.cpp @@ -1,36 +1,36 @@ /* * Copyright © 2018 David Edmundson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License version 2 as * published by the Free Software Foundation * * This program 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 General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "startup.h" #include "shutdown.h" #include int main(int argc, char **argv) { QCoreApplication app(argc, argv); // This is needed with KJobs in a QCoreApplication as when they finish // the internal QEventLoopLocker expires and our app exits app.setQuitLockEnabled(false); - auto startup = new Startup(&app); - auto shutdown = new Shutdown(&app); + new Startup(&app); + new Shutdown(&app); app.exec(); } diff --git a/startkde/plasma-session/shutdown.cpp b/startkde/plasma-session/shutdown.cpp index 383d56081..2092c185a 100644 --- a/startkde/plasma-session/shutdown.cpp +++ b/startkde/plasma-session/shutdown.cpp @@ -1,97 +1,97 @@ #include "shutdown.h" #include "shutdownadaptor.h" #include #include #include #include #include #include "sessionmanagementbackend.h" #include "ksmserver_interface.h" #include "debug.h" Shutdown::Shutdown(QObject *parent): QObject(parent) { new ShutdownAdaptor(this); QDBusConnection::sessionBus().registerObject(QStringLiteral("/Shutdown"), QStringLiteral("org.kde.Shutdown"), this); //registered as a new service name for easy moving to new process QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.Shutdown")); } void Shutdown::logout() { startLogout(KWorkSpace::ShutdownTypeNone); } void Shutdown::logoutAndShutdown() { startLogout(KWorkSpace::ShutdownTypeHalt); } void Shutdown::logoutAndReboot() { startLogout(KWorkSpace::ShutdownTypeReboot); } void Shutdown::startLogout(KWorkSpace::ShutdownType shutdownType) { m_shutdownType = shutdownType; OrgKdeKSMServerInterfaceInterface ksmserverIface(QStringLiteral("org.kde.ksmserver"), QStringLiteral("/KSMServer"), QDBusConnection::sessionBus()); auto closeSessionReply = ksmserverIface.closeSession(); auto watcher = new QDBusPendingCallWatcher(closeSessionReply, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, [closeSessionReply, watcher, this]() { watcher->deleteLater(); if (closeSessionReply.isError()) { qDebug() << "ksmserver failed to complete logout"; } if (closeSessionReply.value()) { logoutComplete(); } else { logoutCancelled(); } }); } void Shutdown::logoutCancelled() { m_shutdownType = KWorkSpace::ShutdownTypeNone; } void Shutdown::logoutComplete() { runShutdownScripts(); if (m_shutdownType == KWorkSpace::ShutdownTypeHalt) { SessionBackend::self()->shutdown(); } else if (m_shutdownType == KWorkSpace::ShutdownTypeReboot) { SessionBackend::self()->reboot(); } else { //logout qApp->quit(); } } void Shutdown::runShutdownScripts() { const QStringList shutdownFolders = QStandardPaths::locateAll(QStandardPaths::GenericConfigLocation, QStringLiteral("plasma-workspace/shutdown"), QStandardPaths::LocateDirectory); - foreach (const QString &shutDownFolder, shutdownFolders) { + for (const QString &shutDownFolder : shutdownFolders) { QDir dir(shutDownFolder); const QStringList entries = dir.entryList(QDir::Files); - foreach (const QString &file, entries) { + for (const QString &file : entries) { // Don't execute backup files if (!file.endsWith(QLatin1Char('~')) && !file.endsWith(QLatin1String(".bak")) && (file[0] != QLatin1Char('%') || !file.endsWith(QLatin1Char('%'))) && (file[0] != QLatin1Char('#') || !file.endsWith(QLatin1Char('#')))) { const QString fullPath = dir.absolutePath() + QLatin1Char('/') + file; qCDebug(PLASMA_SESSION) << "running shutdown script" << fullPath; QProcess::execute(fullPath, QStringList()); } } } } diff --git a/startkde/plasma-session/startup.cpp b/startkde/plasma-session/startup.cpp index b4fa188e4..232e37d04 100644 --- a/startkde/plasma-session/startup.cpp +++ b/startkde/plasma-session/startup.cpp @@ -1,432 +1,432 @@ /***************************************************************** Copyright 2000 Matthias Ettrich Copyright 2005 Lubos Lunak Copyright 2018 David Edmundson relatively small extensions by Oswald Buddenhagen some code taken from the dcopserver (part of the KDE libraries), which is Copyright 1999 Matthias Ettrich Copyright 1999 Preston Brown Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************/ #include "startup.h" #include "debug.h" #include "kcminit_interface.h" #include "kded_interface.h" #include #include "ksmserver_interface.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "startupadaptor.h" class Phase: public KCompositeJob { Q_OBJECT public: Phase(const AutoStart &autostart, QObject *parent) : KCompositeJob(parent) , m_autostart(autostart) {} bool addSubjob(KJob *job) override { bool rc = KCompositeJob::addSubjob(job); job->start(); return rc; } void slotResult(KJob *job) override { KCompositeJob::slotResult(job); if (!hasSubjobs()) { emitResult(); } } protected: const AutoStart m_autostart; }; class StartupPhase0: public Phase { Q_OBJECT public: StartupPhase0(const AutoStart& autostart, QObject *parent) : Phase(autostart, parent) {} void start() override { qCDebug(PLASMA_SESSION) << "Phase 0"; addSubjob(new AutoStartAppsJob(m_autostart, 0)); addSubjob(new KCMInitJob(1)); addSubjob(new SleepJob()); } }; class StartupPhase1: public Phase { Q_OBJECT public: StartupPhase1(const AutoStart& autostart, QObject *parent) : Phase(autostart, parent) {} void start() override { qCDebug(PLASMA_SESSION) << "Phase 1"; addSubjob(new AutoStartAppsJob(m_autostart, 1)); } }; class StartupPhase2: public Phase { Q_OBJECT public: StartupPhase2(const AutoStart& autostart, QObject *parent) : Phase(autostart, parent) {} void runUserAutostart(); bool migrateKDE4Autostart(const QString &folder); void start() override { qCDebug(PLASMA_SESSION) << "Phase 2"; addSubjob(new AutoStartAppsJob(m_autostart, 2)); addSubjob(new KDEDInitJob()); addSubjob(new KCMInitJob(2)); runUserAutostart(); } }; SleepJob::SleepJob() { } void SleepJob::start() { auto t = new QTimer(this); connect(t, &QTimer::timeout, this, [this]() {emitResult();}); t->start(100); } // Put the notification in its own thread as it can happen that // PulseAudio will start initializing with this, so let's not // block the main thread with waiting for PulseAudio to start class NotificationThread : public QThread { Q_OBJECT void run() override { // We cannot parent to the thread itself so let's create // a QObject on the stack and parent everythign to it QObject parent; KNotifyConfig notifyConfig(QStringLiteral("plasma_workspace"), QList< QPair >(), QStringLiteral("startkde")); const QString action = notifyConfig.readEntry(QStringLiteral("Action")); if (action.isEmpty() || !action.split(QLatin1Char('|')).contains(QLatin1String("Sound"))) { // no startup sound configured return; } Phonon::AudioOutput *m_audioOutput = new Phonon::AudioOutput(Phonon::NotificationCategory, &parent); QString soundFilename = notifyConfig.readEntry(QStringLiteral("Sound")); if (soundFilename.isEmpty()) { qCWarning(PLASMA_SESSION) << "Audio notification requested, but no sound file provided in notifyrc file, aborting audio notification"; return; } QUrl soundURL; const auto dataLocations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); for (const QString &dataLocation: dataLocations) { soundURL = QUrl::fromUserInput(soundFilename, dataLocation + QStringLiteral("/sounds"), QUrl::AssumeLocalFile); if (soundURL.isLocalFile() && QFile::exists(soundURL.toLocalFile())) { break; } else if (!soundURL.isLocalFile() && soundURL.isValid()) { break; } soundURL.clear(); } if (soundURL.isEmpty()) { qCWarning(PLASMA_SESSION) << "Audio notification requested, but sound file from notifyrc file was not found, aborting audio notification"; return; } Phonon::MediaObject *m = new Phonon::MediaObject(&parent); connect(m, &Phonon::MediaObject::finished, this, &NotificationThread::quit); Phonon::createPath(m, m_audioOutput); m->setCurrentSource(soundURL); m->play(); exec(); } }; Startup::Startup(QObject *parent): QObject(parent) { new StartupAdaptor(this); QDBusConnection::sessionBus().registerObject(QStringLiteral("/Startup"), QStringLiteral("org.kde.Startup"), this); QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.Startup")); const AutoStart autostart; auto phase0 = new StartupPhase0(autostart, this); auto phase1 = new StartupPhase1(autostart, this); auto phase2 = new StartupPhase2(autostart, this); auto restoreSession = new RestoreSessionJob(); // this includes starting kwin (currently) // forward our arguments into ksmserver to match startplasma expectations QStringList arguments = qApp->arguments(); arguments.removeFirst(); auto ksmserverJob = new StartServiceJob(QStringLiteral("ksmserver"), arguments, QStringLiteral("org.kde.ksmserver")); connect(ksmserverJob, &KJob::finished, phase0, &KJob::start); connect(phase0, &KJob::finished, phase1, &KJob::start); connect(phase1, &KJob::finished, restoreSession, &KJob::start); connect(restoreSession, &KJob::finished, phase2, &KJob::start); upAndRunning(QStringLiteral("ksmserver")); connect(phase1, &KJob::finished, this, []() { NotificationThread *loginSound = new NotificationThread(); connect(loginSound, &NotificationThread::finished, loginSound, &NotificationThread::deleteLater); loginSound->start();}); connect(phase2, &KJob::finished, this, &Startup::finishStartup); ksmserverJob->start(); } void Startup::upAndRunning( const QString& msg ) { QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"), QStringLiteral("/KSplash"), QStringLiteral("org.kde.KSplash"), QStringLiteral("setStage")); ksplashProgressMessage.setArguments(QList() << msg); QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage); } void Startup::finishStartup() { qCDebug(PLASMA_SESSION) << "Finished"; upAndRunning(QStringLiteral("ready")); } void Startup::updateLaunchEnv(const QString &key, const QString &value) { qputenv(key.toLatin1(), value.toLatin1()); } KCMInitJob::KCMInitJob(int phase) :m_phase(phase) { } void KCMInitJob::start() { org::kde::KCMInit kcminit(QStringLiteral("org.kde.kcminit"), QStringLiteral("/kcminit"), QDBusConnection::sessionBus()); kcminit.setTimeout(10 * 1000); QDBusPendingReply pending; if (m_phase == 1) { pending = kcminit.runPhase1(); } else { pending = kcminit.runPhase2(); } QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pending, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, [this]() {emitResult();}); connect(watcher, &QDBusPendingCallWatcher::finished, watcher, &QObject::deleteLater); } KDEDInitJob::KDEDInitJob() { } void KDEDInitJob::start() { qCDebug(PLASMA_SESSION()); org::kde::kded5 kded( QStringLiteral("org.kde.kded5"), QStringLiteral("/kded"), QDBusConnection::sessionBus()); auto pending = kded.loadSecondPhase(); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pending, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, [this]() {emitResult();}); connect(watcher, &QDBusPendingCallWatcher::finished, watcher, &QObject::deleteLater); } RestoreSessionJob::RestoreSessionJob(): KJob() {} void RestoreSessionJob::start() { OrgKdeKSMServerInterfaceInterface ksmserverIface(QStringLiteral("org.kde.ksmserver"), QStringLiteral("/KSMServer"), QDBusConnection::sessionBus()); auto pending = ksmserverIface.restoreSession(); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pending, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, [this]() {emitResult();}); connect(watcher, &QDBusPendingCallWatcher::finished, watcher, &QObject::deleteLater); } void StartupPhase2::runUserAutostart() { // Now let's execute the scripts in the KDE-specific autostart-scripts folder. const QString autostartFolder = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QDir::separator() + QStringLiteral("autostart-scripts"); QDir dir(autostartFolder); if (!dir.exists()) { // Create dir in all cases, so that users can find it :-) dir.mkpath(QStringLiteral(".")); if (!migrateKDE4Autostart(autostartFolder)) { return; } } const QStringList entries = dir.entryList(QDir::Files); - foreach (const QString &file, entries) { + for (const QString &file : entries) { // Don't execute backup files if (!file.endsWith(QLatin1Char('~')) && !file.endsWith(QLatin1String(".bak")) && (file[0] != QLatin1Char('%') || !file.endsWith(QLatin1Char('%'))) && (file[0] != QLatin1Char('#') || !file.endsWith(QLatin1Char('#')))) { const QString fullPath = dir.absolutePath() + QLatin1Char('/') + file; qCInfo(PLASMA_SESSION) << "Starting autostart script " << fullPath; auto p = new KProcess; //deleted in onFinished lambda p->setProgram(fullPath); p->start(); connect(p, static_cast(&QProcess::finished), [p](int exitCode) { qCInfo(PLASMA_SESSION) << "autostart script" << p->program() << "finished with exit code " << exitCode; p->deleteLater(); }); } } } bool StartupPhase2::migrateKDE4Autostart(const QString &autostartFolder) { // Migrate user autostart from kde4 Kdelibs4Migration migration; if (!migration.kdeHomeFound()) { return false; } // KDEHOME/Autostart was the default value for KGlobalSettings::autostart() QString oldAutostart = migration.kdeHome() + QStringLiteral("/Autostart"); // That path could be customized in kdeglobals const QString oldKdeGlobals = migration.locateLocal("config", QStringLiteral("kdeglobals")); if (!oldKdeGlobals.isEmpty()) { oldAutostart = KConfig(oldKdeGlobals).group("Paths").readEntry("Autostart", oldAutostart); } const QDir oldFolder(oldAutostart); qCDebug(PLASMA_SESSION) << "Copying autostart files from" << oldFolder.path(); const QStringList entries = oldFolder.entryList(QDir::Files); - foreach (const QString &file, entries) { + for (const QString &file : entries) { const QString src = oldFolder.absolutePath() + QLatin1Char('/') + file; const QString dest = autostartFolder + QLatin1Char('/') + file; QFileInfo info(src); bool success; if (info.isSymLink()) { // This will only work with absolute symlink targets success = QFile::link(info.symLinkTarget(), dest); } else { success = QFile::copy(src, dest); } if (!success) { qCWarning(PLASMA_SESSION) << "Error copying" << src << "to" << dest; } } return true; } AutoStartAppsJob::AutoStartAppsJob(const AutoStart & autostart, int phase) : m_autoStart(autostart) { m_autoStart.setPhase(phase); } void AutoStartAppsJob::start() { qCDebug(PLASMA_SESSION); QTimer::singleShot(0, this, [=]() { do { QString serviceName = m_autoStart.startService(); if (serviceName.isEmpty()) { // Done if (!m_autoStart.phaseDone()) { m_autoStart.setPhaseDone(); } emitResult(); return; } KService service(serviceName); auto arguments = KIO::DesktopExecParser(service, QList()).resultingArguments(); if (arguments.isEmpty()) { qCWarning(PLASMA_SESSION) << "failed to parse" << serviceName << "for autostart"; continue; } qCInfo(PLASMA_SESSION) << "Starting autostart service " << serviceName << arguments; auto program = arguments.takeFirst(); if (!QProcess::startDetached(program, arguments)) qCWarning(PLASMA_SESSION) << "could not start" << serviceName << ":" << program << arguments; } while (true); }); } StartServiceJob::StartServiceJob(const QString &process, const QStringList &args, const QString &serviceId): KJob(), m_process(process), m_args(args) { auto watcher = new QDBusServiceWatcher(serviceId, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration, this); connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, &StartServiceJob::emitResult); } void StartServiceJob::start() { QProcess::startDetached(m_process, m_args); } #include "startup.moc"