Commit 90bbdf83 authored by Henri Chain's avatar Henri Chain 🛰
Browse files

[kcms/autostart] move autostart kcm to plasma-workspace

parent 89404b23
......@@ -9,7 +9,6 @@ ecm_optional_add_subdirectory(splashscreen)
ecm_optional_add_subdirectory(cookies)
ecm_optional_add_subdirectory(baloo)
ecm_optional_add_subdirectory(autostart)
ecm_optional_add_subdirectory(cursortheme)
ecm_optional_add_subdirectory(fonts)
ecm_optional_add_subdirectory(fontinst)
......
########### install files ###############
#
kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol/autostart)
<?xml version="1.0" ?>
<!DOCTYPE article PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN"
"dtd/kdedbx45.dtd" [
<!ENTITY % addindex "IGNORE">
<!ENTITY % English "INCLUDE">
]>
<article id="autostart" lang="&language;">
<articleinfo>
<title>Autostart</title>
<authorgroup>
<author>&Anne-Marie.Mahfouf;</author>
<!-- TRANS:ROLES_OF_TRANSLATORS -->
</authorgroup>
<date>2021-04-05</date>
<releaseinfo>&plasma; 5.20</releaseinfo>
<keywordset>
<keyword>KDE</keyword>
<keyword>System Settings</keyword>
<keyword>autostart</keyword>
<keyword>desktop file</keyword>
<keyword>script file</keyword>
</keywordset>
</articleinfo>
<sect1 id="kcm_autostart">
<title>Autostart Manager</title>
<para>This module is a configuration tool for managing what programs start up with your personal &plasma;. It allows you to add programs or scripts so they automatically run during startup or shutdown of your &plasma; session and to manage them.</para>
<note><para>Please note that in this module all changes are immediately applied.</para></note>
<para>The program scans <filename>$HOME/.config/autostart/</filename>,
<filename class="directory">$HOME/.config/plasma-workspace/env</filename> and <filename class="directory">$HOME/.config/plasma-workspace/shutdown</filename> folders to check what programs and scripts are already there and displays them. It allows you to manage them easily.
</para>
<note><para>Note that you can change the location of your <filename class="directory">Autostart</filename>
folder in <menuchoice><guimenu>Applications</guimenu> <guimenuitem>Locations</guimenuitem></menuchoice>
in the <guilabel>Personalization</guilabel> category of the &systemsettings; and set a different folder
than <filename class="directory">$HOME/.config/autostart</filename>.</para></note>
<para>Please read also <ulink url="help:/kcontrol/kcmsmserver">Desktop Session</ulink> and <ulink url="help:/kcontrol/kded">Background Services</ulink> for information how to configure the startup behavior of your &plasma; session.</para>
<para>Some &kde; applications handle the autostart behavior on their own, &eg; you can enable or disable autostart of an application in the settings dialog (&kalarm;) or you have to use <menuchoice><guimenu>File</guimenu><guimenuitem>Quit</guimenuitem></menuchoice> (&konversation;, &kopete;), otherwise the application is still running in the systemtray and will be restarted on next login.
</para>
<sect2 id="migration">
<title>Migration from &kde; Workspaces 4</title>
<para>To migrate your personal autostart setting from &kde; Workspaces 4:</para>
<simplelist>
<member>Copy desktop files from <filename class="directory">$HOME/.kde/Autostart</filename> to <filename class="directory">$HOME/.config/autostart</filename></member>
<member>Copy pre startup script files from <filename class="directory">$HOME/.kde/Autostart</filename> to <filename class="directory">$HOME/.config/plasma-workspace/env</filename></member>
<member>Copy shutdown script files from <filename class="directory">$HOME/.kde/Autostart</filename> to <filename class="directory">$HOME/.config/plasma-workspace/shutdown</filename></member>
</simplelist>
</sect2>
<sect2 id="disabling_autostart">
<title>Disabling Autostart Files Provided by Your Distribution</title>
<para>The correct way to disable an autostart item, for example the printer-applet if you use printer from time to time, is to copy its <filename class="extension">.desktop</filename> file to your personal autostart folder. Anything of the same name in <filename class="directory">$HOME/.config/autostart</filename> overrides the <filename class="extension">.desktop</filename> file in the default package. Add the following line to the copied <filename class="extension">.desktop</filename> file:</para>
<programlisting>
Hidden=true
</programlisting>
</sect2>
<sect2 id="current">
<title>Files display</title>
<para>The main part of the module displays the programs that are loaded when &plasma; starts and scripts that are run when &plasma; starts or shutdowns.</para>
<variablelist>
<varlistentry><term><guilabel>Icon</guilabel></term>
<listitem>
<para>
This column shows the icon of the program or script you want to start with &plasma;. The icon is extracted from the Desktop file from the Icon key for a program and is the default icon for a script.
</para>
</listitem>
</varlistentry>
<varlistentry><term><guilabel>Name</guilabel></term>
<listitem>
<para>
This column shows the name of the program or script you want to start with &plasma;. The name is extracted from the <filename class="extension">.desktop</filename> file from the <literal>Name</literal> key for a program and is the filename for a script.
</para>
</listitem>
</varlistentry>
<varlistentry><term><guilabel>Properties</guilabel></term>
<listitem>
<para>
This button is only shown when you hover the item with the mouse pointer. The button (only enabled for programs &ie; <filename class="extension">.desktop</filename> files) allows you to change the properties of the program or script. You have general properties, permissions properties, a preview when applicable, and properties related to the application for programs. The default command is extracted from the <filename class="extension">.desktop</filename> file from the <literal>Exec</literal> key.
</para>
<para>
For a script, the command is the path to the script and can not be modified.
</para>
</listitem>
</varlistentry>
<varlistentry><term><guilabel>Remove</guilabel></term>
<listitem>
<para>
This button is only shown when you hover the item with the mouse pointer. Pressing the <guibutton>&minus;</guibutton> button will immediately remove the Desktop file for the program or the script or symbolic link in the <filename class="directory">Autostart</filename> folder.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect2>
<sect2 id="actions">
<title>Actions</title>
<para>
On the bottom, you have the combined <guibutton>Add...</guibutton> button to choose the type of item you want to add. You can add programs and login or logout scripts.
</para>
<variablelist>
<varlistentry><term><guimenuitem>Add Program</guimenuitem></term>
<listitem>
<para>
Clicking this item displays the standard &plasma; <guilabel>Choose Application</guilabel> dialog and allows you to choose which program you want to start. After choosing the program, clicking <guibutton>OK</guibutton> brings you the properties for this program.
</para>
<para>
This will copy the program <filename class="extension">.desktop</filename> file in your <filename class="directory">Autostart</filename> folder.
</para>
</listitem>
</varlistentry>
<varlistentry><term><guimenuitem>Add Login Script...</guimenuitem></term>
<listitem>
<para>
This item opens a dialog that asks you for the location of the script you want to add. Scripts set to run on login are copied or symlinked in <filename class="directory">$HOME/.config/autostart</filename> and will be run during Plasma startup.
</para>
</listitem>
</varlistentry>
<varlistentry><term><guimenuitem>Add Logout Script...</guimenuitem></term>
<listitem>
<para>
This item opens a dialog that asks you for the location of the script you want to add. Scripts set on to be run on logout are copied or symlinked in the <filename class="directory">$HOME/.config/plasma-workspace/shutdown</filename> directory and will be automatically run during &plasma; shutdown after the user has logged out.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect2>
</sect1>
</article>
<!--
Local Variables:
mode: xml
sgml-minimize-attributes:nil
sgml-general-insert-case:lower
sgml-indent-step:0
sgml-indent-data:nil
End:
vim:tabstop=2:shiftwidth=2:expandtab
kate: space-indent on; indent-width 2; tab-width 2; indent-mode none;
-->
......@@ -10,7 +10,6 @@ endif()
add_subdirectory( access )
add_subdirectory( dateandtime )
add_subdirectory( autostart )
add_subdirectory( ksplash )
add_subdirectory( launch )
......
Stephen Leaf <smileaf@gmail.com>
Montel Laurent <montel@kde.org>
Nicolas Fella <nicolas.fella@gmx.de>
# KI18N Translation Domain for this library
add_definitions(-DTRANSLATION_DOMAIN=\"kcm_autostart\")
set(kcm_autostart_PART_SRCS
autostartmodel.cpp
autostart.cpp )
add_library(kcm_autostart MODULE ${kcm_autostart_PART_SRCS})
target_link_libraries(kcm_autostart KF5::I18n KF5::KIOCore KF5::KIOWidgets KF5::QuickAddons)
kcoreaddons_desktop_to_json(kcm_autostart "package/metadata.desktop")
install(TARGETS kcm_autostart DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms )
install(FILES package/metadata.desktop RENAME autostart.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR})
kpackage_install_package(package kcm_autostart kcms)
#!/usr/bin/env bash
$XGETTEXT `find . -name '*.cpp' -o -name '*.qml'` -o $podir/kcm_autostart.pot
/***************************************************************************
* Copyright (C) 2006-2007 by Stephen Leaf *
* smileaf@gmail.com *
* Copyright (C) 2008 by Montel Laurent <montel@kde.org> *
* *
* 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 <KAboutData>
#include <KLocalizedString>
K_PLUGIN_CLASS_WITH_JSON(Autostart, "metadata.json")
Autostart::Autostart(QObject *parent, const QVariantList &)
: KQuickAddons::ConfigModule(parent)
, m_model(new AutostartModel(this))
{
setButtons(Help);
qmlRegisterUncreatableType<AutostartModel>("org.kde.plasma.kcm.autostart", 1, 0, "AutostartModel", QStringLiteral("Only for enums"));
KAboutData *about = new KAboutData(QStringLiteral("kcm_autostart"),
i18n("Autostart"),
QStringLiteral("1.0"),
i18n("Session Autostart Manager Control Panel Module"),
KAboutLicense::GPL,
i18n("Copyright © 2006–2020 Autostart Manager team"));
about->addAuthor(i18n("Stephen Leaf"), QString(), QStringLiteral("smileaf@gmail.com"));
about->addAuthor(i18n("Montel Laurent"), i18n("Maintainer"), QStringLiteral("montel@kde.org"));
about->addAuthor(i18n("Nicolas Fella"), QString(), QStringLiteral("nicolas.fella@gmx.de"));
setAboutData(about);
}
Autostart::~Autostart()
{
}
AutostartModel *Autostart::model() const
{
return m_model;
}
void Autostart::load()
{
m_model->load();
}
void Autostart::defaults()
{
}
void Autostart::save()
{
}
#include "autostart.moc"
/***************************************************************************
* Copyright (C) 2006-2007 by Stephen Leaf *
* smileaf@gmail.com *
* Copyright (C) 2008 by Montel Laurent <montel@kde.org> *
* *
* 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 AUTOSTART_H
#define AUTOSTART_H
#include <KQuickAddons/ConfigModule>
#include "autostartmodel.h"
class Autostart : public KQuickAddons::ConfigModule
{
Q_OBJECT
Q_PROPERTY(AutostartModel *model READ model CONSTANT)
public:
explicit Autostart(QObject *parent, const QVariantList &);
~Autostart() override;
void load() override;
void save() override;
void defaults() override;
AutostartModel *model() const;
private:
AutostartModel *m_model;
};
#endif
/***************************************************************************
* Copyright (C) 2020 by Méven Car <meven.car@enioka.com> *
* *
* 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 "autostartmodel.h"
#include <KConfigGroup>
#include <KDesktopFile>
#include <KShell>
#include <QDebug>
#include <QDir>
#include <QQuickItem>
#include <QQuickRenderControl>
#include <QStandardPaths>
#include <QWindow>
#include <KFileItem>
#include <KIO/CopyJob>
#include <KIO/DeleteJob>
#include <KLocalizedString>
#include <KOpenWithDialog>
#include <KPropertiesDialog>
#include <optional>
// 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
// share/autostart shouldn't be an option as this should be reserved for global autostart entries
static std::optional<AutostartEntry> loadDesktopEntry(const QString &fileName)
{
KDesktopFile config(fileName);
const KConfigGroup grp = config.desktopGroup();
const auto name = config.readName();
const bool hidden = grp.readEntry("Hidden", false);
if (hidden) {
return {};
}
const QStringList notShowList = grp.readXdgListEntry("NotShowIn");
const QStringList onlyShowList = grp.readXdgListEntry("OnlyShowIn");
const bool enabled = !(notShowList.contains(QLatin1String("KDE")) || (!onlyShowList.isEmpty() && !onlyShowList.contains(QLatin1String("KDE"))));
if (!enabled) {
return {};
}
const auto lstEntry = grp.readXdgListEntry("OnlyShowIn");
const bool onlyInPlasma = lstEntry.contains(QLatin1String("KDE"));
const QString iconName = config.readIcon();
const QString tryCommand = grp.readEntry("TryExec");
// Try to filter out entries that point to nonexistant programs
// If TryExec is either found in $PATH or is an absolute file path that exists
// This doesn't detect uninstalled Flatpaks for example though
if (!tryCommand.isEmpty() && QStandardPaths::findExecutable(tryCommand).isEmpty() && !QFile::exists(tryCommand)) {
return {};
}
return std::optional<AutostartEntry>({name,
AutostartModel::AutostartEntrySource::XdgAutoStart, // .config/autostart load desktop at startup
enabled,
fileName,
onlyInPlasma,
iconName});
}
AutostartModel::AutostartModel(QObject *parent)
: QAbstractListModel(parent)
{
}
QString AutostartModel::XdgAutoStartPath() const
{
return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1String("/autostart/");
}
void AutostartModel::load()
{
beginResetModel();
m_entries.clear();
QDir autostartdir(XdgAutoStartPath());
if (!autostartdir.exists()) {
autostartdir.mkpath(XdgAutoStartPath());
}
autostartdir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
const auto filesInfo = autostartdir.entryInfoList();
for (const QFileInfo &fi : filesInfo) {
if (!KDesktopFile::isDesktopFile(fi.fileName())) {
continue;
}
const std::optional<AutostartEntry> entry = loadDesktopEntry(fi.absoluteFilePath());
if (!entry) {
continue;
}
m_entries.push_back(entry.value());
}
loadScriptsFromDir(QStringLiteral("/autostart-scripts/"), AutostartModel::AutostartEntrySource::XdgScripts);
// Treat them as XdgScripts so they appear together in the UI
loadScriptsFromDir(QStringLiteral("/plasma-workspace/env/"), AutostartModel::AutostartEntrySource::XdgScripts);
loadScriptsFromDir(QStringLiteral("/plasma-workspace/shutdown/"), AutostartModel::AutostartEntrySource::PlasmaShutdown);
endResetModel();
}
void AutostartModel::loadScriptsFromDir(const QString &subDir, AutostartModel::AutostartEntrySource kind)
{
const QString path = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + subDir;
QDir dir(path);
if (!dir.exists()) {
dir.mkpath(path);
}
dir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
const auto autostartDirFilesInfo = dir.entryInfoList();
for (const QFileInfo &fi : autostartDirFilesInfo) {
QString fileName = fi.absoluteFilePath();
const bool isSymlink = fi.isSymLink();
if (isSymlink) {
fileName = fi.symLinkTarget();
}
m_entries.push_back({fileName, kind, true, fi.absoluteFilePath(), false, QStringLiteral("dialog-scripts")});
}
}
int AutostartModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid()) {
return 0;
}
return m_entries.count();
}
bool AutostartModel::reloadEntry(const QModelIndex &index, const QString &fileName)
{
if (!checkIndex(index)) {
return false;
}
const std::optional<AutostartEntry> newEntry = loadDesktopEntry(fileName);
if (!newEntry) {
return false;
}
m_entries.replace(index.row(), newEntry.value());
Q_EMIT dataChanged(index, index);
return true;
}
QVariant AutostartModel::data(const QModelIndex &index, int role) const
{
if (!checkIndex(index)) {
return QVariant();
}
const auto &entry = m_entries.at(index.row());
switch (role) {
case Qt::DisplayRole:
return entry.name;
case Enabled:
return entry.enabled;
case Source:
return entry.source;
case FileName:
return entry.fileName;
case OnlyInPlasma:
return entry.onlyInPlasma;
case IconName:
return entry.iconName;
}
return QVariant();
}
void AutostartModel::addApplication(const KService::Ptr &service)
{
QString desktopPath;
// 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
if (service->desktopEntryName().isEmpty() || service->entryPath().isEmpty()) {
// create a new desktop file in s_desktopPath
desktopPath = XdgAutoStartPath() + service->name() + QStringLiteral(".desktop");
KDesktopFile desktopFile(desktopPath);
KConfigGroup kcg = desktopFile.desktopGroup();
kcg.writeEntry("Name", service->name());
kcg.writeEntry("Exec", service->exec());
kcg.writeEntry("Icon", service->icon());
kcg.writeEntry("Path", "");
kcg.writeEntry("Terminal", service->terminal() ? "True" : "False");
kcg.writeEntry("Type", "Application");
desktopFile.sync();
} else {
desktopPath = XdgAutoStartPath() + service->desktopEntryName() + QStringLiteral(".desktop");
QFile::remove(desktopPath);
// copy original desktop file to new path
KDesktopFile desktopFile(service->entryPath());
auto newDeskTopFile = desktopFile.copyTo(desktopPath);
newDeskTopFile->sync();
}
const auto entry = AutostartEntry{service->name(),
AutostartModel::AutostartEntrySource::XdgAutoStart, // .config/autostart load desktop at startup
true,
desktopPath,
false,
service->icon()};
int lastApplication = -1;
for (const AutostartEntry &e : qAsConst(m_entries)) {
if (e.source == AutostartModel::AutostartEntrySource::XdgScripts) {
break;
}
++lastApplication;
}
// push before the script items
const int index = lastApplication + 1;
beginInsertRows(QModelIndex(), index, index);
m_entries.insert(index, entry);
endInsertRows();
}
void AutostartModel::showApplicationDialog(QQuickItem *context)
{
KOpenWithDialog *owdlg = new KOpenWithDialog();
owdlg->setAttribute(Qt::WA_DeleteOnClose);
if (context && context->window()) {
if (QWindow *actualWindow = QQuickRenderControl::renderWindowFor(context->window())) {
owdlg->winId(); // so it creates windowHandle
owdlg->windowHandle()->setTransientParent(actualWindow);
owdlg->setModal(true);
}
}
connect(