autostart.cpp
00001 /* 00002 * 00003 * This file is part of the KDE libraries 00004 * Copyright (c) 2001 Waldo Bastian <bastian@kde.org> 00005 * 00006 * $Id$ 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Library General Public 00010 * License version 2 as published by the Free Software Foundation. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Library General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Library General Public License 00018 * along with this library; see the file COPYING.LIB. If not, write to 00019 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 * Boston, MA 02110-1301, USA. 00021 **/ 00022 00023 #include "autostart.h" 00024 00025 #include <tdeconfig.h> 00026 #include <kdesktopfile.h> 00027 #include <tdeglobal.h> 00028 #include <kstandarddirs.h> 00029 00030 #include <stdlib.h> 00031 00032 class AutoStartItem 00033 { 00034 public: 00035 TQString name; 00036 TQString service; 00037 TQString startAfter; 00038 int phase; 00039 }; 00040 00041 class AutoStartList: public TQPtrList<AutoStartItem> 00042 { 00043 public: 00044 AutoStartList() { } 00045 }; 00046 00047 AutoStart::AutoStart( bool new_startup ) 00048 : m_newStartup( new_startup ), m_phase( new_startup ? -1 : 0), m_phasedone(false) 00049 { 00050 m_startList = new AutoStartList; 00051 m_startList->setAutoDelete(true); 00052 TDEGlobal::dirs()->addResourceType("autostart", "share/autostart"); 00053 TQString xdgdirs = getenv("XDG_CONFIG_DIRS"); 00054 if (xdgdirs.isEmpty()) 00055 xdgdirs = "/etc/xdg"; 00056 00057 TQStringList xdgdirslist = TQStringList::split( ':', xdgdirs ); 00058 for ( TQStringList::Iterator itr = xdgdirslist.begin(); itr != xdgdirslist.end(); ++itr ) { 00059 TDEGlobal::dirs()->addResourceDir("autostart", (*itr) +"/autostart"); 00060 } 00061 } 00062 00063 AutoStart::~AutoStart() 00064 { 00065 delete m_startList; 00066 } 00067 00068 void 00069 AutoStart::setPhase(int phase) 00070 { 00071 if (phase > m_phase) 00072 { 00073 m_phase = phase; 00074 m_phasedone = false; 00075 } 00076 } 00077 00078 void AutoStart::setPhaseDone() 00079 { 00080 m_phasedone = true; 00081 } 00082 00083 static TQString extractName(TQString path) 00084 { 00085 int i = path.findRev('/'); 00086 if (i >= 0) 00087 path = path.mid(i+1); 00088 i = path.findRev('.'); 00089 if (i >= 0) 00090 path = path.left(i); 00091 return path; 00092 } 00093 00094 static bool startCondition(const TQString &condition) 00095 { 00096 if (condition.isEmpty()) 00097 return true; 00098 00099 TQStringList list = TQStringList::split(':', condition, true); 00100 if (list.count() < 4) 00101 return true; 00102 if (list[0].isEmpty() || list[2].isEmpty()) 00103 return true; 00104 00105 TDEConfig config(list[0], true, false); 00106 if (!list[1].isEmpty()) 00107 config.setGroup(list[1]); 00108 00109 bool defaultValue = (list[3].lower() == "true"); 00110 00111 return config.readBoolEntry(list[2], defaultValue); 00112 } 00113 00114 void 00115 AutoStart::loadAutoStartList() 00116 { 00117 TQStringList files = TDEGlobal::dirs()->findAllResources("xdgconf-autostart", "*.desktop", false, true); 00118 TQStringList kdefiles = TDEGlobal::dirs()->findAllResources("autostart", "*.desktop", false, true); 00119 files += kdefiles; 00120 00121 for(TQStringList::ConstIterator it = files.begin(); 00122 it != files.end(); 00123 ++it) 00124 { 00125 KDesktopFile config(*it, true); 00126 if (config.hasKey("X-TDE-autostart-condition")) { 00127 if (!startCondition(config.readEntry("X-TDE-autostart-condition"))) 00128 continue; 00129 } 00130 else { 00131 if (!startCondition(config.readEntry("X-TDE-autostart-condition"))) 00132 continue; 00133 } 00134 if (!config.tryExec()) 00135 continue; 00136 if (config.readBoolEntry("Hidden", false)) 00137 continue; 00138 00139 // Check to see if the most important ( usually ~/.config/autostart or ~/.trinity/Autostart) XDG directory 00140 // has overridden the Hidden directive and honor it if set to True 00141 bool autostartOverriddenAndDisabled = false; 00142 for(TQStringList::ConstIterator localit = files.begin(); 00143 localit != files.end(); 00144 ++localit) 00145 { 00146 if (((*localit).startsWith(TDEGlobal::dirs()->localxdgconfdir()) == true) || ((*localit).startsWith(TDEGlobal::dirs()->localtdedir()) == true)) { 00147 // Same local file name? 00148 TQString localOuter; 00149 TQString localInner; 00150 int slashPos = (*it).findRev( '/', -1, TRUE ); 00151 if (slashPos == -1) { 00152 localOuter = (*it); 00153 } 00154 else { 00155 localOuter = (*it).mid(slashPos+1); 00156 } 00157 slashPos = (*localit).findRev( '/', -1, TRUE ); 00158 if (slashPos == -1) { 00159 localInner = (*localit); 00160 } 00161 else { 00162 localInner = (*localit).mid(slashPos+1); 00163 } 00164 if (localOuter == localInner) { 00165 // Overridden! 00166 // But is Hidden == True? 00167 KDesktopFile innerConfig(*localit, true); 00168 if (innerConfig.readBoolEntry("Hidden", false)) { 00169 // Override confirmed; exit speedily without autostarting 00170 autostartOverriddenAndDisabled = true; 00171 } 00172 } 00173 } 00174 } 00175 00176 if (autostartOverriddenAndDisabled == true) 00177 continue; 00178 00179 if (config.hasKey("OnlyShowIn")) 00180 { 00181 #ifdef WITH_OLD_XDG_STD 00182 if ((!config.readListEntry("OnlyShowIn", ';').contains("TDE")) && (!config.readListEntry("OnlyShowIn", ';').contains("KDE"))) 00183 continue; 00184 #else 00185 if (!config.readListEntry("OnlyShowIn", ';').contains("TDE")) 00186 continue; 00187 #endif 00188 } 00189 if (config.hasKey("NotShowIn")) 00190 { 00191 #ifdef WITH_OLD_XDG_STD 00192 if ((config.readListEntry("NotShowIn", ';').contains("TDE")) || (config.readListEntry("NotShowIn", ';').contains("KDE"))) 00193 continue; 00194 #else 00195 if (config.readListEntry("NotShowIn", ';').contains("TDE")) 00196 continue; 00197 #endif 00198 } 00199 00200 AutoStartItem *item = new AutoStartItem; 00201 item->name = extractName(*it); 00202 item->service = *it; 00203 if (config.hasKey("X-TDE-autostart-after")) 00204 item->startAfter = config.readEntry("X-TDE-autostart-after"); 00205 else 00206 item->startAfter = config.readEntry("X-TDE-autostart-after"); 00207 if( m_newStartup ) 00208 { 00209 if (config.hasKey("X-TDE-autostart-phase")) 00210 item->phase = config.readNumEntry("X-TDE-autostart-phase", 2); 00211 else 00212 item->phase = config.readNumEntry("X-TDE-autostart-phase", 2); 00213 if (item->phase < 0) 00214 item->phase = 0; 00215 } 00216 else 00217 { 00218 if (config.hasKey("X-TDE-autostart-phase")) 00219 item->phase = config.readNumEntry("X-TDE-autostart-phase", 1); 00220 else 00221 item->phase = config.readNumEntry("X-TDE-autostart-phase", 1); 00222 if (item->phase < 1) 00223 item->phase = 1; 00224 } 00225 m_startList->append(item); 00226 } 00227 00228 // Check for duplicate entries and remove if found 00229 TQPtrListIterator<AutoStartItem> it1(*m_startList); 00230 TQPtrListIterator<AutoStartItem> it2(*m_startList); 00231 AutoStartItem *item1; 00232 AutoStartItem *item2; 00233 while ((item1 = it1.current()) != 0) { 00234 bool dupfound1 = false; 00235 it2.toFirst(); 00236 while ((item2 = it2.current()) != 0) { 00237 bool dupfound2 = false; 00238 if (item2 != item1) { 00239 if (item1->service == item2->service) { 00240 m_startList->removeRef(item2); 00241 dupfound1 = true; 00242 dupfound2 = true; 00243 } 00244 } 00245 if (!dupfound2) { 00246 ++it2; 00247 } 00248 } 00249 if (!dupfound1) { 00250 ++it1; 00251 } 00252 } 00253 } 00254 00255 TQString 00256 AutoStart::startService() 00257 { 00258 if (m_startList->isEmpty()) 00259 return 0; 00260 00261 while(!m_started.isEmpty()) 00262 { 00263 00264 // Check for items that depend on previously started items 00265 TQString lastItem = m_started[0]; 00266 for(AutoStartItem *item = m_startList->first(); 00267 item; item = m_startList->next()) 00268 { 00269 if (item->phase == m_phase 00270 && item->startAfter == lastItem) 00271 { 00272 m_started.prepend(item->name); 00273 TQString service = item->service; 00274 m_startList->remove(); 00275 return service; 00276 } 00277 } 00278 m_started.remove(m_started.begin()); 00279 } 00280 00281 // Check for items that don't depend on anything 00282 AutoStartItem *item; 00283 for(item = m_startList->first(); 00284 item; item = m_startList->next()) 00285 { 00286 if (item->phase == m_phase 00287 && item->startAfter.isEmpty()) 00288 { 00289 m_started.prepend(item->name); 00290 TQString service = item->service; 00291 m_startList->remove(); 00292 return service; 00293 } 00294 } 00295 00296 // Just start something in this phase 00297 for(item = m_startList->first(); 00298 item; item = m_startList->next()) 00299 { 00300 if (item->phase == m_phase) 00301 { 00302 m_started.prepend(item->name); 00303 TQString service = item->service; 00304 m_startList->remove(); 00305 return service; 00306 } 00307 } 00308 00309 return 0; 00310 }