|
MythTV
0.26-pre
|
00001 00002 #include "custompriority.h" 00003 00004 // qt 00005 #include <QSqlError> 00006 00007 // libmythbase 00008 #include "mythdb.h" 00009 #include "mythlogging.h" 00010 00011 // libmyth 00012 #include "mythcorecontext.h" 00013 00014 // libmythtv 00015 #include "scheduledrecording.h" 00016 #include "channelutil.h" 00017 00018 // libmythui 00019 #include "mythuibuttonlist.h" 00020 #include "mythuispinbox.h" 00021 #include "mythuitextedit.h" 00022 #include "mythuibutton.h" 00023 #include "mythdialogbox.h" 00024 #include "mythmainwindow.h" 00025 00026 //mythfrontend 00027 #include "viewschedulediff.h" 00028 00029 CustomPriority::CustomPriority(MythScreenStack *parent, ProgramInfo *proginfo) 00030 : MythScreenType(parent, "CustomPriority") 00031 { 00032 if (proginfo) 00033 m_pginfo = new ProgramInfo(*proginfo); 00034 else 00035 m_pginfo = new ProgramInfo(); 00036 00037 gCoreContext->addListener(this); 00038 } 00039 00040 CustomPriority::~CustomPriority(void) 00041 { 00042 delete m_pginfo; 00043 00044 gCoreContext->removeListener(this); 00045 } 00046 00047 bool CustomPriority::Create() 00048 { 00049 if (!LoadWindowFromXML("schedule-ui.xml", "custompriority", this)) 00050 return false; 00051 00052 m_ruleList = dynamic_cast<MythUIButtonList *>(GetChild("rules")); 00053 m_clauseList = dynamic_cast<MythUIButtonList *>(GetChild("clauses")); 00054 00055 m_prioritySpin = dynamic_cast<MythUISpinBox *>(GetChild("priority")); 00056 00057 m_titleEdit = dynamic_cast<MythUITextEdit *>(GetChild("title")); 00058 m_descriptionEdit = dynamic_cast<MythUITextEdit *>(GetChild("description")); 00059 00060 m_addButton = dynamic_cast<MythUIButton *>(GetChild("add")); 00061 m_installButton = dynamic_cast<MythUIButton *>(GetChild("install")); 00062 m_testButton = dynamic_cast<MythUIButton *>(GetChild("test")); 00063 m_deleteButton = dynamic_cast<MythUIButton *>(GetChild("delete")); 00064 m_cancelButton = dynamic_cast<MythUIButton *>(GetChild("cancel")); 00065 00066 if (!m_ruleList || !m_clauseList || !m_prioritySpin || !m_titleEdit || 00067 !m_descriptionEdit || !m_addButton || !m_installButton || 00068 !m_testButton || !m_deleteButton || !m_cancelButton) 00069 { 00070 LOG(VB_GENERAL, LOG_ERR, 00071 "CustomPriority, theme is missing required elements"); 00072 return false; 00073 } 00074 00075 connect(m_ruleList, SIGNAL(itemSelected(MythUIButtonListItem *)), 00076 SLOT(ruleChanged(MythUIButtonListItem *))); 00077 00078 connect(m_titleEdit, SIGNAL(valueChanged()), SLOT(textChanged())); 00079 m_titleEdit->SetMaxLength(128); 00080 connect(m_descriptionEdit, SIGNAL(valueChanged()), SLOT(textChanged())); 00081 m_descriptionEdit->SetMaxLength(0); 00082 00083 connect(m_addButton, SIGNAL(Clicked()), SLOT(addClicked())); 00084 connect(m_testButton, SIGNAL(Clicked()), SLOT(testClicked())); 00085 connect(m_installButton, SIGNAL(Clicked()), SLOT(installClicked())); 00086 connect(m_deleteButton, SIGNAL(Clicked()), SLOT(deleteClicked())); 00087 connect(m_cancelButton, SIGNAL(Clicked()), SLOT(Close())); 00088 00089 loadData(); 00090 00091 BuildFocusList(); 00092 00093 return true; 00094 } 00095 00096 void CustomPriority::loadData() 00097 { 00098 QString baseTitle = m_pginfo->GetTitle(); 00099 baseTitle.remove(QRegExp(" \\(.*\\)$")); 00100 00101 QString quoteTitle = baseTitle; 00102 quoteTitle.replace("\'","\'\'"); 00103 00104 m_prioritySpin->SetRange(-99,99,1); 00105 m_prioritySpin->SetValue(1); 00106 00107 RuleInfo rule; 00108 rule.priority = QString().setNum(1); 00109 00110 new MythUIButtonListItem(m_ruleList, tr("<New priority rule>"), 00111 qVariantFromValue(rule)); 00112 00113 MSqlQuery result(MSqlQuery::InitCon()); 00114 result.prepare("SELECT priorityname, recpriority, selectclause " 00115 "FROM powerpriority ORDER BY priorityname;"); 00116 00117 if (result.exec()) 00118 { 00119 MythUIButtonListItem *item = NULL; 00120 while (result.next()) 00121 { 00122 QString trimTitle = result.value(0).toString(); 00123 trimTitle.remove(QRegExp(" \\(.*\\)$")); 00124 00125 rule.title = trimTitle; 00126 rule.priority = result.value(1).toString(); 00127 rule.description = result.value(2).toString(); 00128 00129 item = new MythUIButtonListItem(m_ruleList, rule.title, 00130 qVariantFromValue(rule)); 00131 00132 if (trimTitle == baseTitle) 00133 m_ruleList->SetItemCurrent(item); 00134 } 00135 } 00136 else 00137 MythDB::DBError("Get power search rules query", result); 00138 00139 loadExampleRules(); 00140 00141 if (!m_pginfo->GetTitle().isEmpty()) 00142 { 00143 m_titleEdit->SetText(baseTitle); 00144 m_descriptionEdit->SetText("program.title = '" + quoteTitle + "' "); 00145 textChanged(); 00146 } 00147 00148 if (m_titleEdit->GetText().isEmpty()) 00149 SetFocusWidget(m_ruleList); 00150 else 00151 SetFocusWidget(m_clauseList); 00152 } 00153 00154 void CustomPriority::loadExampleRules() 00155 { 00156 QMap<QString, QString> examples; 00157 examples.insert(tr("Modify priority for an input (Input priority)"), 00158 "cardinput.cardinputid = 1"); 00159 examples.insert(tr("Modify priority for all inputs on a card"), 00160 "cardinput.cardid = 2"); 00161 examples.insert(tr("Modify priority for every card on a host"), 00162 "capturecard.hostname = 'mythbox'"); 00163 examples.insert(tr("Only one specific channel ID (Channel priority)"), 00164 "channel.chanid = '1003' "); 00165 examples.insert(tr("Only a certain channel number"), 00166 "channel.channum = '3' "); 00167 examples.insert(tr("Only channels that carry a specific station"), 00168 "channel.callsign = 'ESPN' "); 00169 examples.insert(tr("Match related callsigns"), 00170 "channel.callsign LIKE 'HBO%' "); 00171 examples.insert(tr("Only channels marked as commercial free"), 00172 QString("channel.commmethod = %1 ") 00173 .arg(COMM_DETECT_COMMFREE)); 00174 examples.insert(tr("Modify priority for a station on an input"), 00175 "channel.callsign = 'ESPN' AND cardinput.cardinputid = 2"); 00176 examples.insert(tr("Priority for all matching titles"), 00177 "program.title LIKE 'CSI: %' "); 00178 examples.insert(tr("Only shows marked as HDTV"), 00179 "program.hdtv > 0 "); 00180 examples.insert(tr("Close Captioned priority"), 00181 "program.closecaptioned > 0 "); 00182 examples.insert(tr("New episodes only"), 00183 "program.previouslyshown = 0 "); 00184 examples.insert(tr("Modify unidentified episodes"), 00185 "program.generic = 0 "); 00186 examples.insert(tr("First showing of each episode"), 00187 "program.first > 0 "); 00188 examples.insert(tr("Last showing of each episode"), 00189 "program.last > 0 "); 00190 examples.insert(tr("Priority for any show with End Late time"), 00191 "RECTABLE.endoffset > 0 "); 00192 examples.insert(tr("Priority for a category"), 00193 "program.category = 'Reality' "); 00194 examples.insert(QString("%1 ('movie', 'series', 'sports', 'tvshow')") 00195 .arg(tr("Priority for a category type")), 00196 "program.category_type = 'sports' "); 00197 examples.insert(tr("Modify priority by star rating (0.0 to 1.0 for " 00198 "movies only)"), 00199 "program.stars >= 0.75 "); 00200 examples.insert(tr("Priority when shown once (complete example)"), 00201 "program.first > 0 AND program.last > 0"); 00202 examples.insert(tr("Prefer a host for a storage group (complete example)"), 00203 QString("RECTABLE.storagegroup = 'Archive' " 00204 "AND capturecard.hostname = 'mythbox' ")); 00205 examples.insert(tr("Priority for HD shows under two hours (complete " 00206 "example)"), 00207 "program.hdtv > 0 AND program.starttime > " 00208 "DATE_SUB(program.endtime, INTERVAL 2 HOUR) "); 00209 examples.insert(tr("Priority for movies by the year of release (complete " 00210 "example)"), 00211 "program.category_type = 'movie' " 00212 "AND program.airdate >= 2006 "); 00213 examples.insert(tr("Prefer movies when shown at night (complete example)"), 00214 "program.category_type = 'movie' " 00215 "AND HOUR(program.starttime) < 6 "); 00216 examples.insert(tr("Prefer a host for live sports with overtime (complete " 00217 "example)"), 00218 "RECTABLE.endoffset > 0 " 00219 "AND program.category = 'Sports event' " 00220 "AND capturecard.hostname = 'mythbox' "); 00221 examples.insert(tr("Avoid poor signal quality (complete example)"), 00222 "cardinput.cardinputid = 1 AND " 00223 "channel.channum IN (3, 5, 39, 66) "); 00224 00225 QMapIterator<QString, QString> it(examples); 00226 while (it.hasNext()) 00227 { 00228 it.next(); 00229 new MythUIButtonListItem(m_clauseList, it.key(), 00230 qVariantFromValue(it.value())); 00231 } 00232 } 00233 00234 void CustomPriority::ruleChanged(MythUIButtonListItem *item) 00235 { 00236 if (!item) 00237 return; 00238 00239 RuleInfo rule = qVariantValue<RuleInfo>(item->GetData()); 00240 00241 m_titleEdit->SetText(rule.title); 00242 00243 m_descriptionEdit->SetText(rule.description); 00244 m_prioritySpin->SetValue(rule.priority); 00245 m_deleteButton->SetEnabled((bool)m_ruleList->GetCurrentPos()); 00246 textChanged(); 00247 } 00248 00249 void CustomPriority::textChanged(void) 00250 { 00251 bool hastitle = !m_titleEdit->GetText().isEmpty(); 00252 bool hasdesc = !m_descriptionEdit->GetText().isEmpty(); 00253 00254 m_testButton->SetEnabled(hasdesc); 00255 m_installButton->SetEnabled(hastitle && hasdesc); 00256 } 00257 00258 void CustomPriority::addClicked(void) 00259 { 00260 MythUIButtonListItem *item = m_clauseList->GetItemCurrent(); 00261 00262 if (!item) 00263 return; 00264 00265 QString clause; 00266 00267 QString desc = m_descriptionEdit->GetText(); 00268 00269 if (desc.contains(QRegExp("\\S"))) 00270 clause = "AND "; 00271 clause = item->GetData().toString(); 00272 m_descriptionEdit->SetText(desc.append(clause)); 00273 } 00274 00275 void CustomPriority::testClicked(void) 00276 { 00277 if (!checkSyntax()) 00278 return; 00279 00280 testSchedule(); 00281 } 00282 00283 void CustomPriority::installClicked(void) 00284 { 00285 if (!checkSyntax()) 00286 return; 00287 00288 MythUIButtonListItem *item = m_prioritySpin->GetItemCurrent(); 00289 if (!item) 00290 return; 00291 00292 MSqlQuery query(MSqlQuery::InitCon()); 00293 query.prepare("DELETE FROM powerpriority WHERE priorityname = :NAME;"); 00294 query.bindValue(":NAME", m_titleEdit->GetText()); 00295 00296 if (!query.exec()) 00297 MythDB::DBError("Install power search delete", query); 00298 00299 query.prepare("INSERT INTO powerpriority " 00300 "(priorityname, recpriority, selectclause) " 00301 "VALUES(:NAME,:VALUE,:CLAUSE);"); 00302 query.bindValue(":NAME", m_titleEdit->GetText()); 00303 query.bindValue(":VALUE", item->GetText()); 00304 query.bindValue(":CLAUSE", m_descriptionEdit->GetText()); 00305 00306 if (!query.exec()) 00307 MythDB::DBError("Install power search insert", query); 00308 else 00309 ScheduledRecording::ReschedulePlace("InstallCustomPriority"); 00310 00311 Close(); 00312 } 00313 00314 void CustomPriority::deleteClicked(void) 00315 { 00316 if (!checkSyntax()) 00317 return; 00318 00319 MSqlQuery query(MSqlQuery::InitCon()); 00320 query.prepare("DELETE FROM powerpriority " 00321 "WHERE priorityname=:NAME;"); 00322 query.bindValue(":NAME", m_titleEdit->GetText()); 00323 00324 if (!query.exec()) 00325 MythDB::DBError("Delete power search query", query); 00326 else 00327 ScheduledRecording::ReschedulePlace("DeleteCustomPriority"); 00328 00329 Close(); 00330 } 00331 00332 bool CustomPriority::checkSyntax(void) 00333 { 00334 bool ret = false; 00335 QString msg; 00336 00337 QString desc = m_descriptionEdit->GetText(); 00338 00339 if (desc.contains(QRegExp("^\\s*AND\\s", Qt::CaseInsensitive))) 00340 { 00341 msg = "Power Priority rules do not reqiure a leading \"AND\""; 00342 } 00343 else if (desc.contains(';')) 00344 { 00345 msg = "Power Priority rules cannot include semicolon ( ; ) "; 00346 msg += "statement terminators."; 00347 } 00348 else 00349 { 00350 QString qstr = QString("SELECT (%1) FROM (recordmatch, record, " 00351 "program, channel, cardinput, capturecard, " 00352 "oldrecorded) WHERE NULL").arg(desc); 00353 while (1) 00354 { 00355 int i = qstr.indexOf("RECTABLE"); 00356 if (i == -1) break; 00357 qstr = qstr.replace(i, strlen("RECTABLE"), "record"); 00358 } 00359 00360 MSqlQuery query(MSqlQuery::InitCon()); 00361 query.prepare(qstr); 00362 00363 if (query.exec()) 00364 { 00365 ret = true; 00366 } 00367 else 00368 { 00369 msg = tr("An error was found when checking") + ":\n\n"; 00370 msg += query.executedQuery(); 00371 msg += "\n\n" + tr("The database error was") + ":\n"; 00372 msg += query.lastError().databaseText(); 00373 ret = false; 00374 } 00375 } 00376 00377 if (!msg.isEmpty()) 00378 ShowOkPopup(msg); 00379 00380 return ret; 00381 } 00382 00383 void CustomPriority::testSchedule(void) 00384 { 00385 MythUIButtonListItem *item = m_prioritySpin->GetItemCurrent(); 00386 if (!item) 00387 return; 00388 00389 QString ttable = "powerpriority_tmp"; 00390 00391 MSqlQueryInfo dbcon = MSqlQuery::SchedCon(); 00392 MSqlQuery query(dbcon); 00393 QString thequery; 00394 00395 thequery = "SELECT GET_LOCK(:LOCK, 2);"; 00396 query.prepare(thequery); 00397 query.bindValue(":LOCK", "DiffSchedule"); 00398 if (!query.exec()) 00399 { 00400 QString msg = 00401 QString("DB Error (Obtaining lock in testRecording): \n" 00402 "Query was: %1 \nError was: %2 \n") 00403 .arg(thequery) 00404 .arg(MythDB::DBErrorMessage(query.lastError())); 00405 LOG(VB_GENERAL, LOG_ERR, msg); 00406 return; 00407 } 00408 00409 thequery = QString("DROP TABLE IF EXISTS %1;").arg(ttable); 00410 query.prepare(thequery); 00411 if (!query.exec()) 00412 { 00413 QString msg = 00414 QString("DB Error (deleting old table in testRecording): \n" 00415 "Query was: %1 \nError was: %2 \n") 00416 .arg(thequery) 00417 .arg(MythDB::DBErrorMessage(query.lastError())); 00418 LOG(VB_GENERAL, LOG_ERR, msg); 00419 return; 00420 } 00421 00422 thequery = QString("CREATE TABLE %1 SELECT * FROM powerpriority;") 00423 .arg(ttable); 00424 query.prepare(thequery); 00425 if (!query.exec()) 00426 { 00427 QString msg = 00428 QString("DB Error (create new table): \n" 00429 "Query was: %1 \nError was: %2 \n") 00430 .arg(thequery) 00431 .arg(MythDB::DBErrorMessage(query.lastError())); 00432 LOG(VB_GENERAL, LOG_ERR, msg); 00433 return; 00434 } 00435 00436 query.prepare(QString("DELETE FROM %1 WHERE priorityname = :NAME;") 00437 .arg(ttable)); 00438 query.bindValue(":NAME", m_titleEdit->GetText()); 00439 00440 if (!query.exec()) 00441 MythDB::DBError("Test power search delete", query); 00442 00443 thequery = QString("INSERT INTO %1 " 00444 "(priorityname, recpriority, selectclause) " 00445 "VALUES(:NAME,:VALUE,:CLAUSE);").arg(ttable); 00446 query.prepare(thequery); 00447 query.bindValue(":NAME", m_titleEdit->GetText()); 00448 query.bindValue(":VALUE", item->GetText()); 00449 query.bindValue(":CLAUSE", m_descriptionEdit->GetText()); 00450 00451 if (!query.exec()) 00452 MythDB::DBError("Test power search insert", query); 00453 00454 QString ltitle = tr("Power Priority"); 00455 if (!m_titleEdit->GetText().isEmpty()) 00456 ltitle = m_titleEdit->GetText(); 00457 00458 MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); 00459 ViewScheduleDiff *vsd = new ViewScheduleDiff(mainStack, ttable, 0, ltitle); 00460 00461 if (vsd->Create()) 00462 mainStack->AddScreen(vsd); 00463 else 00464 delete vsd; 00465 00466 thequery = "SELECT RELEASE_LOCK(:LOCK);"; 00467 query.prepare(thequery); 00468 query.bindValue(":LOCK", "DiffSchedule"); 00469 if (!query.exec()) 00470 { 00471 QString msg = 00472 QString("DB Error (free lock): \n" 00473 "Query was: %1 \nError was: %2 \n") 00474 .arg(thequery) 00475 .arg(MythDB::DBErrorMessage(query.lastError())); 00476 LOG(VB_GENERAL, LOG_ERR, msg); 00477 } 00478 }
1.7.6.1