not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kcontrol / autostart / autostart.cpp
blob792f2397fc34b7b4ef0ec9cb34afae329acbe0ba
1 /***************************************************************************
2 * Copyright (C) 2006-2007 by Stephen Leaf *
3 * smileaf@gmail.com *
4 * Copyright (C) 2008 by Montel Laurent <montel@kde.org> *
5 * *
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. *
10 * *
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. *
15 * *
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>
28 #include <KLocale>
29 #include <KGlobal>
30 #include <KConfig>
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>
43 #include <QDir>
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);
63 setButtons(Help);
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()
89 delete widget;
93 void Autostart::slotItemClicked( QTreeWidgetItem *item, int col)
95 if ( item && col == COL_STATUS )
97 DesktopStartItem *entry = dynamic_cast<DesktopStartItem*>( item );
98 if ( entry )
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" );
107 else
108 grp.writeEntry("Hidden", disable);
109 kc.sync();
110 if ( disable )
111 item->setText( COL_STATUS, i18nc( "The program won't be run", "Disabled" ) );
112 else
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 )
120 Q_ASSERT( item );
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 )
130 Q_ASSERT( item );
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")
151 << i18n("Shutdown")
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");
182 if ( desktopFile )
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()+'/' ) );
189 if ( indexPath > 2 )
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 );
193 else
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 )
200 case 0:
201 type =ScriptStartItem::START;
202 break;
203 case 1:
204 type = ScriptStartItem::SHUTDOWN;
205 break;
206 case 2:
207 type = ScriptStartItem::PRE_START;
208 break;
209 default:
210 kDebug()<<" type is not defined :"<<type;
211 break;
213 if ( fi.isSymLink() ) {
214 QString link = fi.readLink();
215 addItem(item, filename, link, type );
217 else
219 addItem( item, filename, filename,type );
224 //Update button
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)
237 return;
238 service = owdlg.service();
240 Q_ASSERT(service);
241 if (!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");
256 kc.sync();
258 KPropertiesDialog dlg( desktopTemplate, this );
259 if ( dlg.exec() != QDialog::Accepted )
261 return;
264 else
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 )
270 return;
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]);
282 else
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 );
288 delete addDialog;
291 void Autostart::slotRemoveCMD() {
292 QTreeWidgetItem* item = widget->listCMD->currentItem();
293 if (!item)
294 return;
295 DesktopStartItem *startItem = dynamic_cast<DesktopStartItem*>( item );
296 if ( startItem )
298 m_programItem->takeChild( m_programItem->indexOfChild( startItem ) );
299 KIO::del(startItem->fileName().path() );
301 else
303 ScriptStartItem * scriptItem = dynamic_cast<ScriptStartItem*>( item );
304 if ( scriptItem )
306 m_scriptItem->takeChild( m_scriptItem->indexOfChild( scriptItem ) );
307 KIO::del(scriptItem->fileName().path() );
312 void Autostart::slotEditCMD(QTreeWidgetItem* ent) {
313 if (!ent) return;
314 AutoStartItem *entry = dynamic_cast<AutoStartItem*>( ent );
315 if ( entry )
317 const KFileItem kfi = KFileItem( KFileItem::Unknown, KFileItem::Unknown, KUrl( entry->fileName() ), true );
318 if (! slotEditCMD( kfi ))
319 return;
320 DesktopStartItem *desktopEntry = dynamic_cast<DesktopStartItem*>( entry );
321 if (desktopEntry) {
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 );
331 return c;
334 void Autostart::slotEditCMD() {
335 if ( widget->listCMD->currentItem() == 0 )
336 return;
337 slotEditCMD( (AutoStartItem*)widget->listCMD->currentItem() );
340 void Autostart::slotAdvanced() {
341 if ( widget->listCMD->currentItem() == 0 )
342 return;
343 DesktopStartItem *entry = static_cast<DesktopStartItem *>( widget->listCMD->currentItem() );
344 KDesktopFile kc(entry->fileName().path());
345 KConfigGroup grp = kc.desktopGroup();
346 bool status = false;
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 );
354 if ( dlg->exec() )
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 );
368 delete dlg;
371 void Autostart::slotChangeStartup( int index )
373 if ( widget->listCMD->currentItem() == 0 )
374 return;
375 ScriptStartItem* entry = dynamic_cast<ScriptStartItem*>( widget->listCMD->currentItem() );
376 if ( entry )
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"