diff --git a/kcms/autostart/autostart.cpp b/kcms/autostart/autostart.cpp index 33213641f..ea86e2f8e 100644 --- a/kcms/autostart/autostart.cpp +++ b/kcms/autostart/autostart.cpp @@ -1,470 +1,470 @@ /*************************************************************************** * Copyright (C) 2006-2007 by Stephen Leaf * * smileaf@gmail.com * * Copyright (C) 2008 by Montel Laurent * * * * 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 "autostart.h" #include "autostartitem.h" #include "addscriptdialog.h" #include "advanceddialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include K_PLUGIN_FACTORY(AutostartFactory, registerPlugin();) Autostart::Autostart( QWidget* parent, const QVariantList& ) : KCModule(parent ) { widget = new Ui_AutostartConfig(); widget->setupUi(this); QStringList lstHeader; lstHeader << i18n( "Name" ) << i18n( "Command" ) << i18n( "Status" ) << i18nc("@title:column The name of the column that decides if the program is run on session startup, on session shutdown, etc", "Run On" ); widget->listCMD->setHeaderLabels(lstHeader); widget->listCMD->setFocus(); setButtons(Help); connect( widget->btnProperties, SIGNAL(clicked()), SLOT(slotEditCMD()) ); connect( widget->listCMD, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), SLOT(slotEditCMD(QTreeWidgetItem*)) ); connect(widget->btnAddScript, &QPushButton::clicked, this, &Autostart::slotAddScript); connect(widget->btnAddProgram, &QPushButton::clicked, this, &Autostart::slotAddProgram); connect(widget->btnRemove, &QPushButton::clicked, this, &Autostart::slotRemoveCMD); connect(widget->btnAdvanced, &QPushButton::clicked, this, &Autostart::slotAdvanced); connect(widget->listCMD, &QTreeWidget::itemClicked, this, &Autostart::slotItemClicked); connect(widget->listCMD, &QTreeWidget::itemSelectionChanged, this, &Autostart::slotSelectionChanged); KAboutData* about = new KAboutData(QStringLiteral("Autostart"), i18n("Session Autostart Manager"), QStringLiteral("1.0"), i18n("Session Autostart Manager Control Panel Module"), KAboutLicense::GPL, i18n("Copyright © 2006–2010 Autostart Manager team")); about->addAuthor(i18n("Stephen Leaf"), QString(), QStringLiteral("smileaf@gmail.com")); about->addAuthor(i18n("Montel Laurent"), i18n( "Maintainer" ), QStringLiteral("montel@kde.org")); setAboutData( about ); } Autostart::~Autostart() { delete widget; } void Autostart::slotItemClicked( QTreeWidgetItem *item, int col) { if ( item && col == COL_STATUS ) { DesktopStartItem *entry = dynamic_cast( item ); if ( entry ) { bool disable = ( item->checkState( col ) == Qt::Unchecked ); KDesktopFile kc(entry->fileName().path()); KConfigGroup grp = kc.desktopGroup(); if ( grp.hasKey( "Hidden" ) && !disable) { grp.deleteEntry( "Hidden" ); } else grp.writeEntry("Hidden", disable); kc.sync(); if ( disable ) item->setText( COL_STATUS, i18nc( "The program won't be run", "Disabled" ) ); else item->setText( COL_STATUS, i18nc( "The program will be run", "Enabled" ) ); } } } void Autostart::addItem( DesktopStartItem* item, const QString& name, const QString& run, const QString& command, bool disabled ) { Q_ASSERT( item ); item->setText( COL_NAME, name ); item->setText( COL_RUN, run ); item->setText( COL_COMMAND, command ); item->setCheckState( COL_STATUS, disabled ? Qt::Unchecked : Qt::Checked ); item->setText( COL_STATUS, disabled ? i18nc( "The program won't be run", "Disabled" ) : i18nc( "The program will be run", "Enabled" )); } void Autostart::addItem(ScriptStartItem* item, const QString& name, const QString& command, ScriptStartItem::ENV type ) { Q_ASSERT( item ); item->setText( COL_NAME, name ); item->setText( COL_COMMAND, command ); item->changeStartup( type ); } void Autostart::load() { // FDO user autostart directories are // .config/autostart which has .desktop files executed by klaunch //Then we have Plasma-specific locations which run scripts // .config/autostart-scripts which has scripts executed by ksmserver // .config/plasma-workspace/shutdown which has scripts executed by startkde // .config/plasma-workspace/env which has scripts executed by startkde //in the case of pre-startup they have to end in .sh //everywhere else it doesn't matter //the comment above describes how autostart *currently* works, it is not definitive documentation on how autostart *should* work m_desktopPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/autostart/"); m_paths << QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/autostart-scripts/") << QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/plasma-workspace/shutdown/") << QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/plasma-workspace/env/"); // share/autostart shouldn't be an option as this should be reserved for global autostart entries m_pathName << i18n("Startup") << i18n("Logout") << i18n("Before session startup") ; widget->listCMD->clear(); m_programItem = new QTreeWidgetItem( widget->listCMD ); m_programItem->setText( 0, i18n( "Desktop File" )); m_programItem->setFlags(m_programItem->flags()^Qt::ItemIsSelectable ); QFont boldFont = m_programItem->font(0); boldFont.setBold( true ); m_programItem->setData ( 0, Qt::FontRole, boldFont ); m_scriptItem = new QTreeWidgetItem( widget->listCMD ); m_scriptItem->setText( 0, i18n( "Script File" )); m_scriptItem->setFlags(m_scriptItem->flags()^Qt::ItemIsSelectable); m_scriptItem->setData ( 0, Qt::FontRole, boldFont); widget->listCMD->expandItem( m_programItem ); widget->listCMD->expandItem( m_scriptItem ); //add programs { QDir d(m_desktopPath); if (!d.exists()) d.mkpath(m_desktopPath); QDir autostartdir( m_desktopPath ); autostartdir.setFilter( QDir::Files ); const QFileInfoList list = autostartdir.entryInfoList(); for (int i = 0; i < list.size(); ++i) { QFileInfo fi = list.at(i); QString filename = fi.fileName(); bool desktopFile = filename.endsWith(QLatin1String(".desktop")); if ( desktopFile ) { KDesktopFile config(fi.absoluteFilePath()); //kDebug() << fi.absoluteFilePath() << "trying" << config.desktopGroup().readEntry("Exec"); QStringList commandLine = KShell::splitArgs(config.desktopGroup().readEntry("Exec")); if (commandLine.isEmpty()) { continue; } const QString exe = commandLine.first(); if (exe.isEmpty() || QStandardPaths::findExecutable(exe).isEmpty()) { continue; } DesktopStartItem *item = new DesktopStartItem( fi.absoluteFilePath(), m_programItem, this ); const KConfigGroup grp = config.desktopGroup(); const bool hidden = grp.readEntry("Hidden", false); const QStringList notShowList = grp.readXdgListEntry("NotShowIn"); const QStringList onlyShowList = grp.readXdgListEntry("OnlyShowIn"); const bool disabled = hidden || notShowList.contains(QLatin1String("KDE")) || (!onlyShowList.isEmpty() && !onlyShowList.contains(QLatin1String("KDE"))); int indexPath = m_paths.indexOf((item->fileName().adjusted(QUrl::RemoveFilename).toString() ) ); if ( indexPath > 2 ) indexPath = 0; //.kde/share/autostart and .config/autostart load desktop at startup addItem(item, config.readName(), m_pathName.value(indexPath), grp.readEntry("Exec"), disabled ); } } } //add scripts - foreach (const QString& path, m_paths) { + for (const QString& path : qAsConst(m_paths)) { QDir d(path); if (!d.exists()) d.mkpath(path); QDir autostartdir( path ); autostartdir.setFilter( QDir::Files ); const QFileInfoList list = autostartdir.entryInfoList(); for (int i = 0; i < list.size(); ++i) { QFileInfo fi = list.at(i); ScriptStartItem *item = new ScriptStartItem( fi.absoluteFilePath(), m_scriptItem,this ); int typeOfStartup = m_paths.indexOf((item->fileName().adjusted(QUrl::RemoveScheme | QUrl::RemoveFilename).toString()) ); ScriptStartItem::ENV type = ScriptStartItem::START; switch( typeOfStartup ) { case 0: type =ScriptStartItem::START; break; case 1: type = ScriptStartItem::SHUTDOWN; break; case 2: type = ScriptStartItem::PRE_START; break; default: qDebug()<<" type is not defined :"<listCMD->resizeColumnToContents(COL_NAME); //widget->listCMD->resizeColumnToContents(COL_COMMAND); widget->listCMD->resizeColumnToContents(COL_STATUS); widget->listCMD->resizeColumnToContents(COL_RUN); } void Autostart::slotAddProgram() { KOpenWithDialog owdlg( this ); if (owdlg.exec() != QDialog::Accepted) return; KService::Ptr service = owdlg.service(); Q_ASSERT(service); if (!service) { return; // Don't crash if KOpenWith wasn't able to create service. } // It is important to ensure that we make an exact copy of an existing // desktop file (if selected) to enable users to override global autostarts. // Also see // https://bugs.launchpad.net/ubuntu/+source/kde-workspace/+bug/923360 QString desktopPath; QUrl desktopTemplate; if ( service->desktopEntryName().isEmpty() || service->entryPath().isEmpty()) { // Build custom desktop file (e.g. when the user entered an executable // name in the OpenWithDialog). desktopPath = m_desktopPath + service->name() + QStringLiteral(".desktop"); desktopTemplate = QUrl::fromLocalFile( desktopPath ); KConfig kc(desktopTemplate.path(), KConfig::SimpleConfig); KConfigGroup kcg = kc.group("Desktop Entry"); kcg.writeEntry("Exec",service->exec()); kcg.writeEntry("Icon","system-run"); kcg.writeEntry("Path",""); kcg.writeEntry("Terminal",false); kcg.writeEntry("Type","Application"); kc.sync(); KPropertiesDialog dlg( desktopTemplate, this ); if ( dlg.exec() != QDialog::Accepted ) { return; } } else { // Use existing desktop file and use same file name to enable overrides. desktopPath = m_desktopPath + service->desktopEntryName() + QStringLiteral(".desktop"); desktopTemplate = QUrl::fromLocalFile( QStandardPaths::locate(QStandardPaths::ApplicationsLocation, service->entryPath()) ); KPropertiesDialog dlg( QUrl::fromLocalFile(service->entryPath()), QUrl::fromLocalFile(m_desktopPath), service->desktopEntryName() + QStringLiteral(".desktop"), this ); if ( dlg.exec() != QDialog::Accepted ) return; } KDesktopFile newConf(desktopTemplate.path()); DesktopStartItem * item = new DesktopStartItem( desktopPath, m_programItem,this ); addItem( item, service->name(), m_pathName[0], newConf.desktopGroup().readEntry("Exec") , false); } void Autostart::slotAddScript() { AddScriptDialog * addDialog = new AddScriptDialog(this); int result = addDialog->exec(); if (result == QDialog::Accepted) { if (addDialog->symLink()) KIO::link(addDialog->importUrl(), QUrl::fromLocalFile(m_paths[0])); else KIO::copy(addDialog->importUrl(), QUrl::fromLocalFile(m_paths[0])); ScriptStartItem * item = new ScriptStartItem( m_paths[0] + addDialog->importUrl().fileName(), m_scriptItem,this ); addItem( item, addDialog->importUrl().fileName(), addDialog->importUrl().fileName(),ScriptStartItem::START ); } delete addDialog; } void Autostart::slotRemoveCMD() { QTreeWidgetItem* item = widget->listCMD->currentItem(); if (!item) return; DesktopStartItem *startItem = dynamic_cast( item ); if ( startItem ) { QUrl path(startItem->fileName()); path.setScheme(QStringLiteral("file")); m_programItem->takeChild( m_programItem->indexOfChild( startItem ) ); KIO::del(path); delete item; } else { ScriptStartItem * scriptItem = dynamic_cast( item ); if ( scriptItem ) { QUrl path(scriptItem->fileName()); path.setScheme(QStringLiteral("file")); m_scriptItem->takeChild( m_scriptItem->indexOfChild( scriptItem ) ); KIO::del(path); delete item; } } } void Autostart::slotEditCMD(QTreeWidgetItem* ent) { if (!ent) return; DesktopStartItem *desktopEntry = dynamic_cast( ent ); if ( desktopEntry ) { KFileItem kfi = KFileItem(QUrl(desktopEntry->fileName())); kfi.setDelayedMimeTypes(true); if (! slotEditCMD( kfi )) return; if (desktopEntry) { KService service(desktopEntry->fileName().path()); addItem( desktopEntry, service.name(), m_pathName.value(m_paths.indexOf(desktopEntry->fileName().adjusted(QUrl::RemoveFilename).toString())), service.exec(),false ); } } } bool Autostart::slotEditCMD( const KFileItem &item) { KPropertiesDialog dlg( item, this ); bool c = ( dlg.exec() == QDialog::Accepted ); return c; } void Autostart::slotEditCMD() { if ( widget->listCMD->currentItem() == nullptr ) return; slotEditCMD( (AutoStartItem*)widget->listCMD->currentItem() ); } void Autostart::slotAdvanced() { if ( widget->listCMD->currentItem() == nullptr ) return; DesktopStartItem *entry = static_cast( widget->listCMD->currentItem() ); KDesktopFile kc(entry->fileName().path()); KConfigGroup grp = kc.desktopGroup(); bool status = false; QStringList lstEntry; if (grp.hasKey("OnlyShowIn")) { lstEntry = grp.readXdgListEntry("OnlyShowIn"); status = lstEntry.contains(QLatin1String("KDE")); } AdvancedDialog *dlg = new AdvancedDialog( this,status ); if ( dlg->exec() ) { status = dlg->onlyInKde(); if ( lstEntry.contains(QLatin1String("KDE") ) && !status ) { lstEntry.removeAll( QStringLiteral("KDE") ); grp.writeXdgListEntry( "OnlyShowIn", lstEntry ); } else if ( !lstEntry.contains(QLatin1String("KDE") ) && status ) { lstEntry.append( QStringLiteral("KDE") ); grp.writeXdgListEntry( "OnlyShowIn", lstEntry ); } } delete dlg; } void Autostart::slotChangeStartup( ScriptStartItem* item, int index ) { Q_ASSERT(item); if ( item ) { item->setPath(m_paths.value(index)); widget->listCMD->setCurrentItem( item ); if ( ( index == 2 ) && !item->fileName().path().endsWith( QLatin1String(".sh") )) KMessageBox::information( this, i18n( "Only files with “.sh” extensions are allowed for setting up the environment." ) ); } } void Autostart::slotSelectionChanged() { const bool hasItems = ( dynamic_cast( widget->listCMD->currentItem() )!=nullptr ) ; widget->btnRemove->setEnabled(hasItems); const bool isDesktopItem = (dynamic_cast(widget->listCMD->currentItem() ) != nullptr) ; widget->btnProperties->setEnabled(isDesktopItem); widget->btnAdvanced->setEnabled(isDesktopItem) ; } void Autostart::defaults() { } void Autostart::save() { } #include "autostart.moc"