1 /***************************************************************************
2 * Copyright (C) 2006-2007 by Stephen Leaf *
4 * Copyright (C) 2008 by Montel Laurent <montel@kde.org> *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *
20 ***************************************************************************/
22 #include "autostart.h"
23 #include "autostartitem.h"
24 #include "addscriptdialog.h"
25 #include "advanceddialog.h"
27 #include <KGenericFactory>
31 #include <KConfigGroup>
32 #include <KGlobalSettings>
33 #include <KStandardDirs>
34 #include <KUrlRequester>
35 #include <KOpenWithDialog>
36 #include <KPropertiesDialog>
37 #include <KDesktopFile>
38 #include <KMessageBox>
39 #include <KIO/NetAccess>
40 #include <KIO/DeleteJob>
41 #include <KIO/CopyJob>
44 #include <QHeaderView>
45 #include <QItemDelegate>
46 #include <QTreeWidget>
47 #include <QGridLayout>
48 #include <QStringList>
49 #include <QStandardItemModel>
52 K_PLUGIN_FACTORY(AutostartFactory
, registerPlugin
<Autostart
>();)
53 K_EXPORT_PLUGIN(AutostartFactory( "kcmautostart", "kcm_autostart" ))
55 Autostart::Autostart( QWidget
* parent
, const QVariantList
& )
56 : KCModule( AutostartFactory::componentData(), parent
)
58 widget
= new Ui_AutostartConfig();
59 widget
->setupUi(this);
60 QStringList lstHeader
;
61 lstHeader
<<i18n( "Name" )<< i18n( "Command" )<< i18n( "Status" )<<i18nc("@title:column The name of the column that decides if the program is run on kde startup, on kde shutdown, etc", "Run On" );
62 widget
->listCMD
->setHeaderLabels(lstHeader
);
64 connect( widget
->btnAddScript
, SIGNAL(clicked()), SLOT(slotAddCMD()) );
65 connect( widget
->btnAddProgram
, SIGNAL(clicked()), SLOT(slotAddProgram()) );
66 connect( widget
->btnRemove
, SIGNAL(clicked()), SLOT(slotRemoveCMD()) );
67 connect( widget
->btnAdvanced
, SIGNAL(clicked()), SLOT(slotAdvanced()) );
68 connect( widget
->listCMD
, SIGNAL(itemDoubleClicked(QTreeWidgetItem
*,int)), SLOT(slotEditCMD(QTreeWidgetItem
*)) );
69 connect( widget
->listCMD
, SIGNAL(itemClicked(QTreeWidgetItem
*, int) ),this,SLOT( slotItemClicked( QTreeWidgetItem
*, int) ) );
70 connect( widget
->btnProperties
, SIGNAL(clicked()), SLOT(slotEditCMD()) );
71 connect( widget
->listCMD
, SIGNAL(itemSelectionChanged()), SLOT(slotSelectionChanged()) );
73 widget
->listCMD
->setFocus();
76 KAboutData
* about
= new KAboutData("Autostart", 0, ki18n("KDE Autostart Manager"), "1.0",
77 ki18n("KDE Autostart Manager Control Panel Module"),
78 KAboutData::License_GPL
,
79 ki18n("(c) 2006-2007-2008 Autostart Manager team"));
80 about
->addAuthor(ki18n("Stephen Leaf"), KLocalizedString(), "smileaf@gmail.com");
81 about
->addAuthor(ki18n("Montel Laurent"), ki18n( "Maintainer" ), "montel@kde.org");
82 setAboutData( about
);
87 Autostart::~Autostart()
93 void Autostart::slotItemClicked( QTreeWidgetItem
*item
, int col
)
95 if ( item
&& col
== COL_STATUS
)
97 DesktopStartItem
*entry
= dynamic_cast<DesktopStartItem
*>( item
);
100 bool disable
= ( item
->checkState( col
) == Qt::Unchecked
);
101 KDesktopFile
kc(entry
->fileName().path());
102 KConfigGroup grp
= kc
.desktopGroup();
103 if ( grp
.hasKey( "Hidden" ) && !disable
)
105 grp
.deleteEntry( "Hidden" );
108 grp
.writeEntry("Hidden", disable
);
111 item
->setText( COL_STATUS
, i18nc( "The program won't be run", "Disabled" ) );
113 item
->setText( COL_STATUS
, i18nc( "The program will be run", "Enabled" ) );
118 void Autostart::addItem( DesktopStartItem
*item
, const QString
& name
, const QString
& run
, const QString
& command
, bool status
)
121 item
->setText( COL_NAME
, name
);
122 item
->setText( COL_RUN
, run
);
123 item
->setText( COL_COMMAND
, command
);
124 item
->setCheckState( COL_STATUS
, status
? Qt::Unchecked
: Qt::Checked
);
125 item
->setText( COL_STATUS
, status
? i18nc( "The program won't be run", "Disabled" ) : i18nc( "The program will be run", "Enabled" ));
128 void Autostart::addItem(ScriptStartItem
*item
, const QString
& name
, const QString
& command
, ScriptStartItem::ENV type
)
131 item
->setText( COL_NAME
, name
);
132 item
->setText( COL_COMMAND
, command
);
133 item
->changeStartup( type
);
137 void Autostart::load()
139 // share/autostart may *only* contain .desktop files
140 // shutdown and env may *only* contain scripts, links or binaries
141 // autostart on the otherhand may contain all of the above.
142 // share/autostart is special as it overrides entries found in $KDEDIR/share/autostart
143 m_paths
<< KGlobalSettings::autostartPath() // All new entries should go here
144 << componentData().dirs()->localkdedir() + "shutdown/"
145 << componentData().dirs()->localkdedir() + "env/"
146 << componentData().dirs()->localkdedir() + "share/autostart/" // For Importing purposes
147 << componentData().dirs()->localxdgconfdir() + "autostart/" ; //xdg-config autostart dir
148 //kDebug()<<" path "<<m_paths;
149 // share/autostart shouldn't be an option as this should be reserved for global autostart entries
150 m_pathName
<< i18n("Startup")
152 << i18n("Pre-KDE startup")
154 widget
->listCMD
->clear();
156 m_programItem
= new QTreeWidgetItem( widget
->listCMD
);
157 m_programItem
->setText( 0, i18n( "Desktop File" ));
158 m_programItem
->setFlags(m_programItem
->flags()^Qt::ItemIsSelectable
);
160 QFont boldFont
= m_programItem
->font(0);
161 boldFont
.setBold( true );
162 m_programItem
->setData ( 0, Qt::FontRole
, boldFont
);
163 m_scriptItem
= new QTreeWidgetItem( widget
->listCMD
);
164 m_scriptItem
->setText( 0, i18n( "Script File" ));
165 m_scriptItem
->setFlags(m_scriptItem
->flags()^Qt::ItemIsSelectable
);
166 m_scriptItem
->setData ( 0,Qt::FontRole
, boldFont
);
168 widget
->listCMD
->expandItem( m_programItem
);
169 widget
->listCMD
->expandItem( m_scriptItem
);
171 foreach (const QString
& path
, m_paths
) {
172 if (! KStandardDirs::exists(path
))
173 KStandardDirs::makeDir(path
);
175 QDir
autostartdir( path
);
176 autostartdir
.setFilter( QDir::Files
);
177 const QFileInfoList list
= autostartdir
.entryInfoList();
178 for (int i
= 0; i
< list
.size(); ++i
) {
179 QFileInfo fi
= list
.at(i
);
180 QString filename
= fi
.fileName();
181 bool desktopFile
= filename
.endsWith(".desktop");
184 DesktopStartItem
*item
= new DesktopStartItem( fi
.absoluteFilePath(), m_programItem
, this );
185 KDesktopFile
config(fi
.absoluteFilePath());
186 const KConfigGroup grp
= config
.desktopGroup();
187 bool status
= grp
.readEntry("Hidden", false);
188 int indexPath
= m_paths
.indexOf((item
->fileName().directory()+'/' ) );
190 indexPath
= 0; //.kde/share/autostart and .config/autostart load destkop at startup
191 addItem(item
, config
.readName(), m_pathName
.value(indexPath
), grp
.readEntry("Exec"),status
);
195 ScriptStartItem
*item
= new ScriptStartItem( fi
.absoluteFilePath(), m_scriptItem
,this );
196 int typeOfStartup
= m_paths
.indexOf((item
->fileName().directory()+'/') );
197 ScriptStartItem::ENV type
= ScriptStartItem::START
;
198 switch( typeOfStartup
)
201 type
=ScriptStartItem::START
;
204 type
= ScriptStartItem::SHUTDOWN
;
207 type
= ScriptStartItem::PRE_START
;
210 kDebug()<<" type is not defined :"<<type
;
213 if ( fi
.isSymLink() ) {
214 QString link
= fi
.readLink();
215 addItem(item
, filename
, link
, type
);
219 addItem( item
, filename
, filename
,type
);
225 slotSelectionChanged();
226 widget
->listCMD
->resizeColumnToContents(COL_NAME
);
227 //widget->listCMD->resizeColumnToContents(COL_COMMAND);
228 widget
->listCMD
->resizeColumnToContents(COL_STATUS
);
229 widget
->listCMD
->resizeColumnToContents(COL_RUN
);
232 void Autostart::slotAddProgram()
234 KService::Ptr service
;
235 KOpenWithDialog
owdlg( this );
236 if (owdlg
.exec() != QDialog::Accepted
)
238 service
= owdlg
.service();
243 return; // Don't crash if KOpenWith wasn't able to create service.
246 KUrl desktopTemplate
;
247 if ( service
->desktopEntryName().isEmpty() ) {
248 desktopTemplate
= KUrl( m_paths
[4] + service
->name() + ".desktop" );
249 KConfig
kc(desktopTemplate
.path(), KConfig::SimpleConfig
);
250 KConfigGroup kcg
= kc
.group("Desktop Entry");
251 kcg
.writeEntry("Exec",service
->exec());
252 kcg
.writeEntry("Icon","system-run");
253 kcg
.writeEntry("Path","");
254 kcg
.writeEntry("Terminal",false);
255 kcg
.writeEntry("Type","Application");
258 KPropertiesDialog
dlg( desktopTemplate
, this );
259 if ( dlg
.exec() != QDialog::Accepted
)
266 desktopTemplate
= KUrl( KStandardDirs::locate("apps", service
->entryPath()) );
268 KPropertiesDialog
dlg( desktopTemplate
, KUrl(m_paths
[4]), service
->name() + ".desktop", this );
269 if ( dlg
.exec() != QDialog::Accepted
)
272 DesktopStartItem
* item
= new DesktopStartItem( m_paths
[4] + service
->name() + ".desktop", m_programItem
,this );
273 addItem( item
, service
->name(), m_pathName
[0], service
->exec() , false);
276 void Autostart::slotAddCMD() {
277 AddScriptDialog
* addDialog
= new AddScriptDialog(this);
278 int result
= addDialog
->exec();
279 if (result
== QDialog::Accepted
) {
280 if (addDialog
->symLink())
281 KIO::link(addDialog
->importUrl(), m_paths
[0]);
283 KIO::copy(addDialog
->importUrl(), m_paths
[0]);
285 ScriptStartItem
* item
= new ScriptStartItem( m_paths
[0] + addDialog
->importUrl().fileName(), m_scriptItem
,this );
286 addItem( item
, addDialog
->importUrl().fileName(), addDialog
->importUrl().fileName(),ScriptStartItem::START
);
291 void Autostart::slotRemoveCMD() {
292 QTreeWidgetItem
* item
= widget
->listCMD
->currentItem();
295 DesktopStartItem
*startItem
= dynamic_cast<DesktopStartItem
*>( item
);
298 m_programItem
->takeChild( m_programItem
->indexOfChild( startItem
) );
299 KIO::del(startItem
->fileName().path() );
303 ScriptStartItem
* scriptItem
= dynamic_cast<ScriptStartItem
*>( item
);
306 m_scriptItem
->takeChild( m_scriptItem
->indexOfChild( scriptItem
) );
307 KIO::del(scriptItem
->fileName().path() );
312 void Autostart::slotEditCMD(QTreeWidgetItem
* ent
) {
314 AutoStartItem
*entry
= dynamic_cast<AutoStartItem
*>( ent
);
317 const KFileItem kfi
= KFileItem( KFileItem::Unknown
, KFileItem::Unknown
, KUrl( entry
->fileName() ), true );
318 if (! slotEditCMD( kfi
))
320 DesktopStartItem
*desktopEntry
= dynamic_cast<DesktopStartItem
*>( entry
);
322 KService
service(desktopEntry
->fileName().path());
323 addItem( desktopEntry
, service
.name(), m_pathName
.value(m_paths
.indexOf((desktopEntry
->fileName().directory()+'/') )), service
.exec(),false );
328 bool Autostart::slotEditCMD( const KFileItem
&item
) {
329 KPropertiesDialog
dlg( item
, this );
330 bool c
= ( dlg
.exec() == QDialog::Accepted
);
334 void Autostart::slotEditCMD() {
335 if ( widget
->listCMD
->currentItem() == 0 )
337 slotEditCMD( (AutoStartItem
*)widget
->listCMD
->currentItem() );
340 void Autostart::slotAdvanced() {
341 if ( widget
->listCMD
->currentItem() == 0 )
343 DesktopStartItem
*entry
= static_cast<DesktopStartItem
*>( widget
->listCMD
->currentItem() );
344 KDesktopFile
kc(entry
->fileName().path());
345 KConfigGroup grp
= kc
.desktopGroup();
347 QStringList lstEntry
;
348 if (grp
.hasKey("OnlyShowIn"))
350 lstEntry
= grp
.readXdgListEntry("OnlyShowIn");
351 status
= lstEntry
.contains("KDE");
353 AdvancedDialog
*dlg
= new AdvancedDialog( this,status
);
356 status
= dlg
->onlyInKde();
357 if ( lstEntry
.contains( "KDE" ) && !status
)
359 lstEntry
.removeAll( "KDE" );
360 grp
.writeXdgListEntry( "OnlyShowIn", lstEntry
);
362 else if ( !lstEntry
.contains( "KDE" ) && status
)
364 lstEntry
.append( "KDE" );
365 grp
.writeXdgListEntry( "OnlyShowIn", lstEntry
);
371 void Autostart::slotChangeStartup( int index
)
373 if ( widget
->listCMD
->currentItem() == 0 )
375 ScriptStartItem
* entry
= dynamic_cast<ScriptStartItem
*>( widget
->listCMD
->currentItem() );
378 entry
->setPath(m_paths
.value(index
));
379 if ( ( index
!= 0 ) && !entry
->fileName().path().endsWith( ".sh" ))
380 KMessageBox::information( this, i18n( "KDE only reads files with sh extensions for setting up the environment." ) );
384 void Autostart::slotSelectionChanged() {
385 bool hasItems
= ( dynamic_cast<AutoStartItem
*>( widget
->listCMD
->currentItem() )!=0 ) ;
386 widget
->btnRemove
->setEnabled(hasItems
);
387 widget
->btnProperties
->setEnabled(dynamic_cast<DesktopStartItem
*>( widget
->listCMD
->currentItem() )!=0);
388 widget
->btnAdvanced
->setEnabled( dynamic_cast<DesktopStartItem
*>( widget
->listCMD
->currentItem() )!=0 ) ;
391 void Autostart::defaults()
395 void Autostart::save()
399 #include "autostart.moc"