|
MythTV
0.26-pre
|
00001 00002 // QT headers 00003 #include <QDir> 00004 #include <QFileInfo> 00005 #include <QString> 00006 #include <QStringList> 00007 #include <QApplication> 00008 00009 // MythTV headers 00010 #include <mythcontext.h> 00011 #include <mythdbcon.h> 00012 #include <mythdb.h> 00013 #include <mythprogressdialog.h> 00014 #include <mythdirs.h> 00015 00016 // MythWeather headers 00017 #include "weatherScreen.h" 00018 #include "weatherSource.h" 00019 #include "sourceManager.h" 00020 00021 #define LOC QString("SourceManager: ") 00022 #define LOC_ERR QString("SourceManager Error: ") 00023 00024 SourceManager::SourceManager() 00025 { 00026 findScriptsDB(); 00027 setupSources(); 00028 } 00029 00030 SourceManager::~SourceManager() 00031 { 00032 clearSources(); 00033 } 00034 00035 bool SourceManager::findScriptsDB() 00036 { 00037 MSqlQuery db(MSqlQuery::InitCon()); 00038 QString query = 00039 "SELECT DISTINCT wss.sourceid, source_name, update_timeout, " 00040 "retrieve_timeout, path, author, version, email, types " 00041 "FROM weathersourcesettings wss " 00042 "LEFT JOIN weatherdatalayout wdl " 00043 "ON wss.sourceid = wdl.weathersourcesettings_sourceid " 00044 "WHERE hostname = :HOST;"; 00045 00046 db.prepare(query); 00047 db.bindValue(":HOST", gCoreContext->GetHostName()); 00048 if (!db.exec()) 00049 { 00050 MythDB::DBError("Finding weather source scripts for host", db); 00051 return false; 00052 } 00053 00054 while (db.next()) 00055 { 00056 QFileInfo fi(db.value(4).toString()); 00057 00058 if (!fi.isExecutable()) 00059 { 00060 // scripts will be deleted from db in the more robust (i.e. slower) 00061 // findScripts() -- run when entering setup 00062 continue; 00063 } 00064 ScriptInfo *si = new ScriptInfo; 00065 si->id = db.value(0).toInt(); 00066 si->name = db.value(1).toString(); 00067 si->updateTimeout = db.value(2).toUInt() * 1000; 00068 si->scriptTimeout = db.value(3).toUInt(); 00069 si->path = fi.absolutePath(); 00070 si->program = fi.absoluteFilePath(); 00071 si->author = db.value(5).toString(); 00072 si->version = db.value(6).toString(); 00073 si->email = db.value(7).toString(); 00074 si->types = db.value(8).toString().split(","); 00075 m_scripts.append(si); 00076 } 00077 00078 return true; 00079 } 00080 00081 bool SourceManager::findScripts() 00082 { 00083 QString path = GetShareDir() + "mythweather/scripts/"; 00084 QDir dir(path); 00085 dir.setFilter(QDir::Executable | QDir::Files | QDir::Dirs); 00086 00087 if (!dir.exists()) 00088 { 00089 LOG(VB_GENERAL, LOG_ERR, "MythWeather: Scripts directory not found"); 00090 return false; 00091 } 00092 QString busymessage = tr("Searching for scripts"); 00093 00094 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("weather stack"); 00095 if (popupStack == NULL) 00096 popupStack = GetMythMainWindow()->GetStack("popup stack"); 00097 00098 MythUIBusyDialog *busyPopup = new MythUIBusyDialog(busymessage, popupStack, 00099 "mythweatherbusydialog"); 00100 00101 if (busyPopup->Create()) 00102 { 00103 popupStack->AddScreen(busyPopup, false); 00104 } 00105 else 00106 { 00107 delete busyPopup; 00108 busyPopup = NULL; 00109 } 00110 00111 qApp->processEvents(); 00112 00113 recurseDirs(dir); 00114 00115 // run through and see if any scripts have been deleted 00116 MSqlQuery db(MSqlQuery::InitCon()); 00117 00118 db.prepare("SELECT sourceid, path FROM weathersourcesettings " 00119 "WHERE hostname = :HOST;"); 00120 db.bindValue(":HOST", gCoreContext->GetHostName()); 00121 if (!db.exec()) 00122 MythDB::DBError("SourceManager::findScripts - select", db); 00123 QStringList toRemove; 00124 while (db.next()) 00125 { 00126 QFileInfo fi(db.value(1).toString()); 00127 if (!fi.isExecutable()) 00128 { 00129 toRemove << db.value(0).toString(); 00130 LOG(VB_GENERAL, LOG_ERR, QString("'%1' no longer exists") 00131 .arg(fi.absoluteFilePath())); 00132 } 00133 } 00134 00135 db.prepare("DELETE FROM weathersourcesettings WHERE sourceid = :ID;"); 00136 for (int i = 0; i < toRemove.count(); ++i) 00137 { 00138 db.bindValue(":ID", toRemove[i]); 00139 if (!db.exec()) 00140 { 00141 // MythDB::DBError("Deleting weather source settings", db); 00142 } 00143 } 00144 00145 if (busyPopup) 00146 { 00147 busyPopup->Close(); 00148 busyPopup = NULL; 00149 } 00150 00151 return m_scripts.count() > 0; 00152 } 00153 00154 void SourceManager::clearSources() 00155 { 00156 while (!m_scripts.isEmpty()) 00157 delete m_scripts.takeFirst(); 00158 m_scripts.clear(); 00159 00160 while (!m_sources.isEmpty()) 00161 delete m_sources.takeFirst(); 00162 m_sources.clear(); 00163 } 00164 00165 void SourceManager::setupSources() 00166 { 00167 MSqlQuery db(MSqlQuery::InitCon()); 00168 00169 db.prepare( 00170 "SELECT DISTINCT location, weathersourcesettings_sourceid, " 00171 " weatherscreens.units, weatherscreens.screen_id " 00172 "FROM weatherdatalayout,weatherscreens " 00173 "WHERE weatherscreens.screen_id = weatherscreens_screen_id AND " 00174 " weatherscreens.hostname = :HOST"); 00175 db.bindValue(":HOST", gCoreContext->GetHostName()); 00176 if (!db.exec()) 00177 { 00178 MythDB::DBError("Finding weather sources for this host", db); 00179 return; 00180 } 00181 00182 m_sourcemap.clear(); 00183 00184 while (db.next()) 00185 { 00186 QString loc = db.value(0).toString(); 00187 uint sourceid = db.value(1).toUInt(); 00188 units_t units = db.value(2).toUInt(); 00189 uint screen = db.value(3).toUInt(); 00190 const WeatherSource *src = needSourceFor(sourceid, loc, units); 00191 if (src) 00192 m_sourcemap.insert((long)screen, src); 00193 } 00194 } 00195 00196 ScriptInfo *SourceManager::getSourceByName(const QString &name) 00197 { 00198 ScriptInfo *src = 0; 00199 for (int x = 0; x < m_scripts.size(); x++) 00200 { 00201 src = m_scripts.at(x); 00202 if (src->name == name) 00203 { 00204 return src; 00205 } 00206 } 00207 00208 if (!src) 00209 { 00210 LOG(VB_GENERAL, LOG_ERR, "No Source found for " + name); 00211 } 00212 00213 return NULL; 00214 } 00215 00216 QStringList SourceManager::getLocationList(ScriptInfo *si, const QString &str) 00217 { 00218 if (!m_scripts.contains(si)) 00219 return QStringList(); 00220 WeatherSource *ws = new WeatherSource(si); 00221 00222 QStringList locationList(ws->getLocationList(str)); 00223 00224 delete ws; 00225 00226 return locationList; 00227 } 00228 00229 WeatherSource *SourceManager::needSourceFor(int id, const QString &loc, 00230 units_t units) 00231 { 00232 // matching source exists? 00233 WeatherSource *src; 00234 for (int x = 0; x < m_sources.size(); x++) 00235 { 00236 src = m_sources.at(x); 00237 if (src->getId() == id && src->getLocale() == loc && 00238 src->getUnits() == units) 00239 { 00240 return src; 00241 } 00242 } 00243 00244 // no matching source, make one 00245 ScriptInfo *si; 00246 for (int x = 0; x < m_scripts.size(); x++) 00247 { 00248 si = m_scripts.at(x); 00249 if (si->id == id) 00250 { 00251 WeatherSource *ws = new WeatherSource(si); 00252 ws->setLocale(loc); 00253 ws->setUnits(units); 00254 m_sources.append(ws); 00255 return ws; 00256 } 00257 } 00258 00259 LOG(VB_GENERAL, LOG_ERR, LOC + 00260 QString("NeedSourceFor: Unable to find source for %1, %2, %3") 00261 .arg(id).arg(loc).arg(units)); 00262 return NULL; 00263 } 00264 00265 void SourceManager::startTimers() 00266 { 00267 WeatherSource *src; 00268 for (int x = 0; x < m_sources.size(); x++) 00269 { 00270 src = m_sources.at(x); 00271 src->startUpdateTimer(); 00272 } 00273 } 00274 00275 void SourceManager::stopTimers() 00276 { 00277 WeatherSource *src; 00278 for (int x = 0; x < m_sources.size(); x++) 00279 { 00280 src = m_sources.at(x); 00281 src->stopUpdateTimer(); 00282 } 00283 } 00284 00285 void SourceManager::doUpdate(bool forceUpdate) 00286 { 00287 WeatherSource *src; 00288 for (int x = 0; x < m_sources.size(); x++) 00289 { 00290 src = m_sources.at(x); 00291 if (src->inUse()) 00292 src->startUpdate(forceUpdate); 00293 } 00294 } 00295 00296 bool SourceManager::findPossibleSources(QStringList types, 00297 QList<ScriptInfo *> &sources) 00298 { 00299 ScriptInfo *si; 00300 bool handled; 00301 for (int x = 0; x < m_scripts.size(); x++) 00302 { 00303 si = m_scripts.at(x); 00304 QStringList stypes = si->types; 00305 handled = true; 00306 int i; 00307 for (i = 0; i < types.count() && handled; ++i) 00308 { 00309 handled = stypes.contains(types[i]); 00310 } 00311 if (handled) 00312 sources.append(si); 00313 } 00314 00315 if (sources.count()) 00316 return true; 00317 00318 return false; 00319 } 00320 00321 bool SourceManager::connectScreen(uint id, WeatherScreen *screen) 00322 { 00323 if (!screen) 00324 { 00325 LOG(VB_GENERAL, LOG_ERR, LOC + 00326 QString("Cannot connect nonexistent screen 0x%1") 00327 .arg((uint64_t)screen,0,16)); 00328 00329 return false; 00330 } 00331 00332 SourceMap::iterator it = m_sourcemap.find(id); 00333 if (it == m_sourcemap.end()) 00334 { 00335 LOG(VB_GENERAL, LOG_ERR, LOC + 00336 QString("Cannot connect nonexistent source '%1'").arg(id)); 00337 00338 return false; 00339 } 00340 00341 (const_cast<WeatherSource*>(*it))->connectScreen(screen); 00342 00343 return true; 00344 } 00345 00346 bool SourceManager::disconnectScreen(WeatherScreen *screen) 00347 { 00348 if (!screen) 00349 { 00350 LOG(VB_GENERAL, LOG_ERR, LOC + 00351 QString("Cannot disconnect nonexistent screen 0x%1") 00352 .arg((uint64_t)screen,0,16)); 00353 00354 return false; 00355 } 00356 00357 SourceMap::iterator it = m_sourcemap.find(screen->getId()); 00358 if (it == m_sourcemap.end()) 00359 { 00360 LOG(VB_GENERAL, LOG_ERR, LOC + 00361 QString("Cannot disconnect nonexistent source %1") 00362 .arg(screen->getId())); 00363 00364 return false; 00365 } 00366 00367 (const_cast<WeatherSource*>(*it))->disconnectScreen(screen); 00368 00369 return true; 00370 } 00371 00372 // Recurses dir for script files 00373 void SourceManager::recurseDirs( QDir dir ) 00374 { 00375 if (!dir.exists()) 00376 return; 00377 00378 dir.setFilter(QDir::Executable | QDir::Files | QDir::Dirs); 00379 QFileInfoList files = dir.entryInfoList(); 00380 QFileInfo file; 00381 00382 for (int x = 0; x < files.size(); x++) 00383 { 00384 qApp->processEvents(); 00385 file = files.at(x); 00386 if (file.isDir()) 00387 { 00388 if (file.fileName() == QString("..")) continue; 00389 if (file.fileName() == QString(".")) continue; 00390 QDir recurseTo(file.filePath()); 00391 recurseDirs(recurseTo); 00392 } 00393 00394 if (file.isExecutable() && !(file.isDir())) 00395 { 00396 ScriptInfo *info = WeatherSource::ProbeScript(file); 00397 if (info) 00398 { 00399 m_scripts.append(info); 00400 LOG(VB_FILE, LOG_INFO, QString("Found Script '%1'") 00401 .arg(file.absoluteFilePath())); 00402 } 00403 } 00404 } 00405 00406 return; 00407 }
1.7.6.1