|
MythTV
0.26-pre
|
00001 // Qt 00002 #include <QDateTime> 00003 #include <QCoreApplication> 00004 #include <QStringList> 00005 #include <QRegExp> 00006 #include <QKeyEvent> 00007 #include <QEvent> 00008 00009 // MythTV 00010 #include "mythdb.h" 00011 #include "mythdbcon.h" 00012 #include "mythdirs.h" 00013 #include "mythcorecontext.h" 00014 #include "recordinginfo.h" 00015 #include "tv.h" 00016 00017 // MythUI 00018 #include "mythuitext.h" 00019 #include "mythuibuttonlist.h" 00020 #include "mythuibutton.h" 00021 #include "mythuihelper.h" 00022 #include "mythscreenstack.h" 00023 #include "mythmainwindow.h" 00024 00025 // mythfrontend 00026 #include "guidegrid.h" 00027 #include "customedit.h" 00028 #include "progfind.h" 00029 00030 #define LOC QString("ProgFinder: ") 00031 #define LOC_ERR QString("ProgFinder, Error: ") 00032 #define LOC_WARN QString("ProgFinder, Warning: ") 00033 00034 void RunProgramFinder(TV *player, bool embedVideo, bool allowEPG) 00035 { 00036 // Language specific progfinder, if needed 00037 MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); 00038 ProgFinder *programFind = NULL; 00039 if (gCoreContext->GetLanguage() == "ja") 00040 programFind = new JaProgFinder(mainStack, allowEPG, player, embedVideo); 00041 else if (gCoreContext->GetLanguage() == "he") 00042 programFind = new HeProgFinder(mainStack, allowEPG, player, embedVideo); 00043 else if (gCoreContext->GetLanguage() == "ru") 00044 programFind = new RuProgFinder(mainStack, allowEPG, player, embedVideo); 00045 else // default 00046 programFind = new ProgFinder(mainStack, allowEPG, player, embedVideo); 00047 00048 if (programFind->Create()) 00049 mainStack->AddScreen(programFind, (player == NULL)); 00050 else 00051 delete programFind; 00052 } 00053 00054 ProgFinder::ProgFinder(MythScreenStack *parentStack, bool allowEPG, 00055 TV *player, bool embedVideo) 00056 : ScheduleCommon(parentStack, "ProgFinder"), 00057 m_currentLetter(""), 00058 m_player(player), m_embedVideo(embedVideo), 00059 m_allowEPG(allowEPG), m_allowKeypress(true), 00060 m_alphabetList(NULL), m_showList(NULL), 00061 m_timesList(NULL), m_searchText(NULL), 00062 m_help1Text(NULL), m_help2Text(NULL) 00063 { 00064 } 00065 00066 bool ProgFinder::Create() 00067 { 00068 if (!LoadWindowFromXML("schedule-ui.xml", "programfind", this)) 00069 return false; 00070 00071 bool err = false; 00072 UIUtilE::Assign(this, m_alphabetList, "alphabet", &err); 00073 UIUtilE::Assign(this, m_showList, "shows", &err); 00074 UIUtilE::Assign(this, m_timesList, "times", &err); 00075 00076 UIUtilW::Assign(this, m_help1Text, "help1text"); 00077 UIUtilW::Assign(this, m_help2Text, "help2text"); 00078 UIUtilW::Assign(this, m_searchText, "search"); 00079 00080 if (err) 00081 { 00082 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'programfind'"); 00083 return false; 00084 } 00085 00086 m_alphabetList->SetLCDTitles(tr("Starts With"), ""); 00087 m_showList->SetLCDTitles(tr("Programs"), ""); 00088 m_timesList->SetLCDTitles(tr("Times"), "buttontext"); 00089 00090 BuildFocusList(); 00091 LoadInBackground(); 00092 00093 if (m_player) 00094 m_player->StartEmbedding(QRect()); 00095 00096 return true; 00097 } 00098 00099 void ProgFinder::Init(void) 00100 { 00101 m_allowKeypress = true; 00102 00103 initAlphabetList(); 00104 00105 gCoreContext->addListener(this); 00106 00107 connect(m_timesList, SIGNAL(itemSelected(MythUIButtonListItem*)), 00108 SLOT(updateInfo())); 00109 connect(m_timesList, SIGNAL(itemClicked(MythUIButtonListItem*)), 00110 SLOT(select())); 00111 connect(m_timesList, SIGNAL(LosingFocus()), SLOT(timesListLosingFocus())); 00112 connect(m_timesList, SIGNAL(TakingFocus()), SLOT(timesListTakeFocus())); 00113 00114 connect(m_alphabetList, SIGNAL(itemSelected(MythUIButtonListItem*)), 00115 SLOT(alphabetListItemSelected(MythUIButtonListItem*))); 00116 connect(m_alphabetList, SIGNAL(itemClicked(MythUIButtonListItem*)), 00117 SLOT(select())); 00118 00119 connect(m_showList, SIGNAL(TakingFocus()), SLOT(showListTakeFocus())); 00120 connect(m_showList, SIGNAL(itemClicked(MythUIButtonListItem*)), 00121 SLOT(select())); 00122 00123 m_alphabetList->MoveToNamedPosition("A"); 00124 } 00125 00126 ProgFinder::~ProgFinder() 00127 { 00128 gCoreContext->removeListener(this); 00129 00130 // if we have a player and we are returning to it we need 00131 // to tell it to stop embedding and return to fullscreen 00132 if (m_player && m_allowEPG) 00133 { 00134 QString message = QString("PROGFINDER_EXITING"); 00135 qApp->postEvent(m_player, new MythEvent(message)); 00136 } 00137 } 00138 00139 void ProgFinder::alphabetListItemSelected(MythUIButtonListItem *item) 00140 { 00141 if (!item || (m_currentLetter == item->GetText())) 00142 return; 00143 00144 m_currentLetter = item->GetText(); 00145 00146 updateShowList(); 00147 updateInfo(); 00148 } 00149 00150 void ProgFinder::timesListLosingFocus(void) 00151 { 00152 m_timesList->Reset(); 00153 } 00154 00155 void ProgFinder::showListTakeFocus(void) 00156 { 00157 updateInfo(); 00158 } 00159 00160 void ProgFinder::timesListTakeFocus(void) 00161 { 00162 selectShowData("", 0); 00163 updateInfo(); 00164 } 00165 00166 bool ProgFinder::keyPressEvent(QKeyEvent *event) 00167 { 00168 if (!m_allowKeypress) 00169 return true; 00170 00171 m_allowKeypress = false; 00172 00173 if (GetFocusWidget() && GetFocusWidget()->keyPressEvent(event)) 00174 { 00175 m_allowKeypress = true; 00176 return true; 00177 } 00178 00179 bool handled = false; 00180 00181 QStringList actions; 00182 handled = GetMythMainWindow()->TranslateKeyPress("TV Frontend", event, actions); 00183 00184 for (int i = 0; i < actions.size() && !handled; ++i) 00185 { 00186 QString action = actions[i]; 00187 handled = true; 00188 00189 if (action == "EDIT") 00190 edit(); 00191 else if (action == "CUSTOMEDIT") 00192 customEdit(); 00193 else if (action == "UPCOMING") 00194 upcoming(); 00195 else if (action == "DETAILS" || action == "INFO") 00196 details(); 00197 else if (action == "TOGGLERECORD") 00198 quickRecord(); 00199 else if (action == "GUIDE" || action == "4") 00200 showGuide(); 00201 else if (action == "ESCAPE") 00202 { 00203 // don't fade the screen if we are returning to the player 00204 if (m_player && m_allowEPG) 00205 GetScreenStack()->PopScreen(this, false); 00206 else 00207 GetScreenStack()->PopScreen(this, true); 00208 } 00209 else 00210 handled = false; 00211 } 00212 00213 if (!handled && MythScreenType::keyPressEvent(event)) 00214 handled = true; 00215 00216 m_allowKeypress = true; 00217 00218 return handled; 00219 } 00220 00221 void ProgFinder::ShowMenu(void) 00222 { 00223 QString label = tr("Options"); 00224 00225 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 00226 MythDialogBox *menuPopup = new MythDialogBox(label, popupStack, "menuPopup"); 00227 00228 if (menuPopup->Create()) 00229 { 00230 menuPopup->SetReturnEvent(this, "menu"); 00231 00232 if (!m_searchStr.isEmpty()) 00233 menuPopup->AddButton(tr("Clear Search")); 00234 menuPopup->AddButton(tr("Edit Search")); 00235 if (GetFocusWidget() == m_timesList && m_timesList->GetCount() > 0) 00236 { 00237 menuPopup->AddButton(tr("Toggle Record")); 00238 menuPopup->AddButton(tr("Program Details")); 00239 menuPopup->AddButton(tr("Upcoming")); 00240 menuPopup->AddButton(tr("Custom Edit")); 00241 menuPopup->AddButton(tr("Program Guide")); 00242 } 00243 00244 popupStack->AddScreen(menuPopup); 00245 } 00246 else 00247 { 00248 delete menuPopup; 00249 } 00250 } 00251 00252 void ProgFinder::customEvent(QEvent *event) 00253 { 00254 if ((MythEvent::Type)(event->type()) == MythEvent::MythEventMessage) 00255 { 00256 MythEvent *me = (MythEvent *)event; 00257 QString message = me->Message(); 00258 00259 if (message == "SCHEDULE_CHANGE") 00260 { 00261 if (GetFocusWidget() == m_timesList) 00262 { 00263 ProgramInfo *curPick = m_showData[m_timesList->GetCurrentPos()]; 00264 if (curPick) 00265 selectShowData(curPick->GetTitle(), 00266 m_timesList->GetCurrentPos()); 00267 } 00268 } 00269 } 00270 else if (event->type() == DialogCompletionEvent::kEventType) 00271 { 00272 DialogCompletionEvent *dce = (DialogCompletionEvent*)(event); 00273 00274 QString resultid = dce->GetId(); 00275 QString resulttext = dce->GetResultText(); 00276 00277 if (resultid == "menu") 00278 { 00279 if (resulttext == tr("Clear Search")) 00280 { 00281 m_searchStr.clear(); 00282 if (m_searchText) 00283 m_searchText->SetText(m_searchStr); 00284 updateShowList(); 00285 SetFocusWidget(m_showList); 00286 } 00287 else if (resulttext == tr("Edit Search")) 00288 { 00289 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 00290 SearchInputDialog *textInput = 00291 new SearchInputDialog(popupStack, m_searchStr); 00292 00293 if (textInput->Create()) 00294 { 00295 textInput->SetReturnEvent(this, "searchtext"); 00296 popupStack->AddScreen(textInput); 00297 } 00298 } 00299 else if (resulttext == tr("Toggle Record")) 00300 { 00301 quickRecord(); 00302 } 00303 else if (resulttext == tr("Program Details")) 00304 { 00305 details(); 00306 } 00307 else if (resulttext == tr("Upcoming")) 00308 { 00309 upcoming(); 00310 } 00311 else if (resulttext == tr("Custom Edit")) 00312 { 00313 customEdit(); 00314 } 00315 else if (resulttext == tr("Program Guide")) 00316 { 00317 showGuide(); 00318 } 00319 } 00320 else if (resultid == "searchtext") 00321 { 00322 m_searchStr = resulttext; 00323 if (m_searchText) 00324 m_searchText->SetText(m_searchStr); 00325 updateShowList(); 00326 SetFocusWidget(m_showList); 00327 } 00328 else 00329 ScheduleCommon::customEvent(event); 00330 } 00331 } 00332 00333 void ProgFinder::updateInfo(void) 00334 { 00335 if (m_help1Text) 00336 m_help1Text->Reset(); 00337 if (m_help2Text) 00338 m_help2Text->Reset(); 00339 00340 if (GetFocusWidget() == m_alphabetList) 00341 { 00342 QString title; 00343 QString description; 00344 00345 if (m_showList->GetCount() == 0) 00346 { 00347 if (m_help1Text) 00348 m_help1Text->SetText(tr("No Programs")); 00349 if (m_help2Text) 00350 m_help2Text->SetText(tr("There are no available programs under this search. " 00351 "Please select another search.")); 00352 } 00353 else 00354 { 00355 if (m_help1Text) 00356 m_help1Text->SetText(tr("Select a letter...")); 00357 if (m_help2Text) 00358 m_help2Text->SetText(tr("Pick the first letter of the program name, " 00359 "then press SELECT or the right arrow.")); 00360 } 00361 00362 ResetMap(m_infoMap); 00363 } 00364 else if (GetFocusWidget() == m_showList) 00365 { 00366 if (m_help1Text) 00367 m_help1Text->SetText(tr("Select a program...")); 00368 if (m_help2Text) 00369 m_help2Text->SetText(tr("Select the title of the program you wish to find. " 00370 "When finished return with the left arrow key. " 00371 "Press SELECT to schedule a recording.")); 00372 00373 ResetMap(m_infoMap); 00374 } 00375 else if (GetFocusWidget() == m_timesList) 00376 { 00377 if (m_showData.size() == 0) 00378 { 00379 ResetMap(m_infoMap); 00380 if (m_help1Text) 00381 m_help1Text->SetText(tr("No Programs")); 00382 if (m_help2Text) 00383 m_help2Text->SetText(tr("There are no available programs under " 00384 "this search. Please select another " 00385 "search.")); 00386 } 00387 else 00388 { 00389 InfoMap infoMap; 00390 m_showData[m_timesList->GetCurrentPos()]->ToMap(infoMap); 00391 SetTextFromMap(infoMap); 00392 m_infoMap = infoMap; 00393 } 00394 } 00395 } 00396 00397 void ProgFinder::showGuide() 00398 { 00399 if (m_allowEPG) 00400 { 00401 QString startchannel = gCoreContext->GetSetting("DefaultTVChannel"); 00402 if (startchannel.isEmpty()) 00403 startchannel = '3'; 00404 uint startchanid = 0; 00405 GuideGrid::RunProgramGuide(startchanid, startchannel, m_player, m_embedVideo, false, -2); 00406 } 00407 } 00408 00409 void ProgFinder::getInfo(bool toggle) 00410 { 00411 if (GetFocusWidget() == m_timesList) 00412 { 00413 ProgramInfo *curPick = m_showData[m_timesList->GetCurrentPos()]; 00414 00415 if (curPick) 00416 { 00417 if (toggle) 00418 { 00419 RecordingInfo ri(*curPick); 00420 ri.ToggleRecord(); 00421 *curPick = ri; 00422 } 00423 else 00424 EditRecording(curPick); 00425 } 00426 else 00427 return; 00428 00429 // TODO: When schedule editor is non-blocking, move 00430 selectShowData(curPick->GetTitle(), m_timesList->GetCurrentPos()); 00431 } 00432 } 00433 00434 void ProgFinder::edit() 00435 { 00436 if (GetFocusWidget() == m_timesList) 00437 { 00438 ProgramInfo *curPick = m_showData[m_timesList->GetCurrentPos()]; 00439 00440 if (curPick) 00441 { 00442 EditScheduled(curPick); 00443 // TODO: When schedule editor is non-blocking, move 00444 selectShowData(curPick->GetTitle(), m_timesList->GetCurrentPos()); 00445 } 00446 } 00447 } 00448 00449 void ProgFinder::select() 00450 { 00451 if (GetFocusWidget() == m_timesList) 00452 getInfo(); 00453 else if (GetFocusWidget() == m_alphabetList && m_showList->GetCount()) 00454 SetFocusWidget(m_showList); 00455 else if (GetFocusWidget() == m_showList) 00456 SetFocusWidget(m_timesList); 00457 } 00458 00459 void ProgFinder::customEdit() 00460 { 00461 if (GetFocusWidget() == m_timesList) 00462 { 00463 ProgramInfo *pginfo = m_showData[m_timesList->GetCurrentPos()]; 00464 EditCustom(pginfo); 00465 } 00466 } 00467 00468 void ProgFinder::upcoming() 00469 { 00470 if (GetFocusWidget() == m_timesList) 00471 { 00472 ProgramInfo *pginfo = m_showData[m_timesList->GetCurrentPos()]; 00473 ShowUpcoming(pginfo); 00474 } 00475 } 00476 00477 void ProgFinder::details() 00478 { 00479 if (GetFocusWidget() != m_timesList) 00480 return; 00481 00482 ProgramInfo *curPick = m_showData[m_timesList->GetCurrentPos()]; 00483 ShowDetails(curPick); 00484 } 00485 00486 void ProgFinder::quickRecord() 00487 { 00488 getInfo(true); 00489 } 00490 00491 void ProgFinder::updateTimesList() 00492 { 00493 InfoMap infoMap; 00494 00495 m_timesList->Reset(); 00496 00497 if (m_showData.size() > 0) 00498 { 00499 QString itemText; 00500 QDateTime starttime; 00501 for (uint i = 0; i < m_showData.size(); ++i) 00502 { 00503 starttime = m_showData[i]->GetScheduledStartTime(); 00504 itemText = MythDateTimeToString(starttime, 00505 kDateTimeFull | kSimplify); 00506 00507 MythUIButtonListItem *item = 00508 new MythUIButtonListItem(m_timesList, ""); 00509 00510 m_showData[i]->ToMap(infoMap); 00511 item->SetTextFromMap(infoMap); 00512 00513 QString state = toUIState(m_showData[i]->GetRecordingStatus()); 00514 item->SetText(itemText, "buttontext", state); 00515 item->DisplayState(state, "status"); 00516 } 00517 } 00518 } 00519 00520 void ProgFinder::getShowNames() 00521 { 00522 m_showNames.clear(); 00523 00524 QString thequery; 00525 MSqlBindings bindings; 00526 00527 MSqlQuery query(MSqlQuery::InitCon()); 00528 whereClauseGetSearchData(thequery, bindings); 00529 00530 query.prepare(thequery); 00531 query.bindValues(bindings); 00532 if (!query.exec()) 00533 { 00534 MythDB::DBError("getShowNames", query); 00535 return; 00536 } 00537 00538 QString data; 00539 while (query.next()) 00540 { 00541 data = query.value(0).toString(); 00542 00543 if (formatSelectedData(data)) 00544 m_showNames[data.toLower()] = data; 00545 } 00546 } 00547 00548 void ProgFinder::updateShowList() 00549 { 00550 m_showList->Reset(); 00551 00552 if (m_showNames.isEmpty()) 00553 getShowNames(); 00554 00555 ShowName::Iterator it; 00556 for (it = m_showNames.begin(); it != m_showNames.end(); ++it) 00557 { 00558 QString tmpProgData = *it; 00559 restoreSelectedData(tmpProgData); 00560 new MythUIButtonListItem(m_showList, tmpProgData); 00561 } 00562 00563 m_showNames.clear(); 00564 } 00565 00566 void ProgFinder::selectShowData(QString progTitle, int newCurShow) 00567 { 00568 progTitle = m_showList->GetValue(); 00569 00570 QDateTime progStart = QDateTime::currentDateTime(); 00571 00572 MSqlBindings bindings; 00573 QString querystr = "WHERE program.title = :TITLE " 00574 " AND program.endtime > :ENDTIME " 00575 " AND channel.visible = 1 "; 00576 bindings[":TITLE"] = progTitle; 00577 bindings[":ENDTIME"] = progStart.addSecs(50 - progStart.time().second()); 00578 00579 LoadFromScheduler(m_schedList); 00580 LoadFromProgram(m_showData, querystr, bindings, m_schedList); 00581 00582 updateTimesList(); 00583 00584 m_timesList->SetItemCurrent(newCurShow); 00585 } 00586 00587 void ProgFinder::initAlphabetList(void) 00588 { 00589 for (int charNum = 48; charNum < 91; ++charNum) 00590 { 00591 if (charNum == 58) 00592 charNum = 65; 00593 00594 new MythUIButtonListItem(m_alphabetList, QString((char)charNum)); 00595 } 00596 00597 new MythUIButtonListItem(m_alphabetList, QString('@')); 00598 } 00599 00600 void ProgFinder::whereClauseGetSearchData(QString &where, MSqlBindings &bindings) 00601 { 00602 QDateTime progStart = QDateTime::currentDateTime(); 00603 QString searchChar = m_alphabetList->GetValue(); 00604 00605 if (searchChar.isEmpty()) 00606 searchChar = "A"; 00607 00608 if (searchChar.contains('@')) 00609 { 00610 where = "SELECT DISTINCT title FROM program " 00611 "LEFT JOIN channel ON program.chanid = channel.chanid " 00612 "WHERE channel.visible = 1 AND " 00613 "( title NOT REGEXP '^[A-Z0-9]' AND " 00614 " title NOT REGEXP '^The [A-Z0-9]' AND " 00615 " title NOT REGEXP '^A [A-Z0-9]' AND " 00616 " title NOT REGEXP '^An [A-Z0-9]' AND " 00617 " starttime > :STARTTIME ) "; 00618 if (!m_searchStr.isEmpty()) 00619 { 00620 where += "AND title LIKE :SEARCH "; 00621 bindings[":SEARCH"] = '%' + m_searchStr + '%'; 00622 } 00623 00624 where += "ORDER BY title;"; 00625 00626 bindings[":STARTTIME"] = 00627 progStart.addSecs(50 - progStart.time().second()); 00628 } 00629 else 00630 { 00631 QString one = searchChar + '%'; 00632 QString two = QString("The ") + one; 00633 QString three = QString("A ") + one; 00634 QString four = QString("An ") + one; 00635 00636 where = "SELECT DISTINCT title FROM program " 00637 "LEFT JOIN channel ON program.chanid = channel.chanid " 00638 "WHERE channel.visible = 1 " 00639 "AND ( title LIKE :ONE OR title LIKE :TWO " 00640 " OR title LIKE :THREE " 00641 " OR title LIKE :FOUR ) " 00642 "AND starttime > :STARTTIME "; 00643 if (!m_searchStr.isEmpty()) 00644 where += "AND title LIKE :SEARCH "; 00645 00646 where += "ORDER BY title;"; 00647 00648 bindings[":ONE"] = one; 00649 bindings[":TWO"] = two; 00650 bindings[":THREE"] = three; 00651 bindings[":FOUR"] = four; 00652 bindings[":STARTTIME"] = 00653 progStart.addSecs(50 - progStart.time().second()); 00654 00655 if (!m_searchStr.isEmpty()) 00656 bindings[":SEARCH"] = '%' + m_searchStr + '%'; 00657 } 00658 } 00659 00660 bool ProgFinder::formatSelectedData(QString& data) 00661 { 00662 bool retval = true; 00663 QString searchChar = m_alphabetList->GetValue(); 00664 00665 if (searchChar == "T") 00666 { 00667 if (data.left(4) != "The " && data.left(2) != "A ") 00668 { 00669 // nothing, use as is 00670 } 00671 else if (data.left(5) == "The T") 00672 data = data.mid(4) + ", The"; 00673 else if (data.left(3) == "A T") 00674 data = data.mid(2) + ", A"; 00675 else 00676 { 00677 // don't add 00678 retval = false; 00679 } 00680 } 00681 else if (searchChar == "A") 00682 { 00683 if (data.left(4) != "The " && data.left(2) != "A ") 00684 { 00685 // nothing, use as is 00686 } 00687 else if (data.left(5) == "The A") 00688 data = data.mid(4) + ", The"; 00689 else if (data.left(3) == "A A") 00690 data = data.mid(2) + ", A"; 00691 else if (data.left(4) == "An A") 00692 data = data.mid(3) + ", An"; 00693 else 00694 { 00695 // don't add 00696 retval = false; 00697 } 00698 } 00699 else 00700 { 00701 if (data.left(4) == "The ") 00702 data = data.mid(4) + ", The"; 00703 else if (data.left(2) == "A ") 00704 data = data.mid(2) + ", A"; 00705 else if (data.left(3) == "An ") 00706 data = data.mid(3) + ", An"; 00707 } 00708 00709 return retval; 00710 } 00711 00712 bool ProgFinder::formatSelectedData(QString& data, int charNum) 00713 { 00714 bool retval = true; 00715 00716 if (charNum == 29 || charNum == 10) 00717 { 00718 if (data.left(5) == "The T" && charNum == 29) 00719 data = data.mid(4) + ", The"; 00720 else if (data.left(5) == "The A" && charNum == 10) 00721 data = data.mid(4) + ", The"; 00722 else if (data.left(3) == "A T" && charNum == 29) 00723 data = data.mid(2) + ", A"; 00724 else if (data.left(3) == "A A" && charNum == 10) 00725 data = data.mid(2) + ", A"; 00726 else if (data.left(4) == "An A" && charNum == 10) 00727 data = data.mid(3) + ", An"; 00728 else if (data.left(4) != "The " && data.left(2) != "A ") 00729 { 00730 // use as is 00731 } 00732 else 00733 { 00734 // don't add 00735 retval = false; 00736 } 00737 } 00738 else 00739 { 00740 if (data.left(4) == "The ") 00741 data = data.mid(4) + ", The"; 00742 if (data.left(2) == "A ") 00743 data = data.mid(2) + ", A"; 00744 if (data.left(3) == "An ") 00745 data = data.mid(3) + ", An"; 00746 } 00747 00748 return retval; 00749 } 00750 00751 void ProgFinder::restoreSelectedData(QString &data) 00752 { 00753 if (data.right(5) == ", The") 00754 data = "The " + data.left(data.length() - 5); 00755 if (data.right(3) == ", A") 00756 data = "A " + data.left(data.length() - 3); 00757 } 00758 00760 // Japanese specific program finder 00761 00762 // japanese HIRAGANA list and more 00763 const char* JaProgFinder::searchChars[] = { 00764 "あ", "か", "さ", "た", "な", "は", "ま", "や", "ら", "わ", 00765 "英", "数", 00766 0, 00767 }; 00768 00769 JaProgFinder::JaProgFinder(MythScreenStack *parentStack, bool gg, 00770 TV *player, bool embedVideo) 00771 : ProgFinder(parentStack, gg, player, embedVideo) 00772 { 00773 for (numberOfSearchChars = 0; searchChars[numberOfSearchChars]; 00774 ++numberOfSearchChars) 00775 ; 00776 } 00777 00778 void JaProgFinder::initAlphabetList() 00779 { 00780 for (int charNum = 0; charNum < numberOfSearchChars; ++charNum) 00781 { 00782 new MythUIButtonListItem(m_alphabetList, QString(searchChars[charNum])); 00783 } 00784 } 00785 00786 // search title_pronounce 00787 // we hope japanese HIRAGANA and alphabets, numerics is inserted 00788 // these character must required ZENKAKU 00789 // because query work not fine, if mysql's default charset latin1 00790 void JaProgFinder::whereClauseGetSearchData(QString &where, MSqlBindings &bindings) 00791 { 00792 QDateTime progStart = QDateTime::currentDateTime(); 00793 int charNum = m_alphabetList->GetCurrentPos(); 00794 00795 where = "SELECT DISTINCT title FROM program " 00796 "LEFT JOIN channel ON program.chanid = channel.chanid " 00797 "WHERE channel.visible = 1 "; 00798 00799 switch (charNum) { 00800 case 0: 00801 where += "AND ( title_pronounce >= 'あ' AND title_pronounce <= 'お') "; 00802 break; 00803 case 1: 00804 where += "AND ( title_pronounce >= 'か' AND title_pronounce <= 'ご') "; 00805 break; 00806 case 2: 00807 where += "AND ( title_pronounce >= 'さ' AND title_pronounce <= 'そ') "; 00808 break; 00809 case 3: 00810 where += "AND ( title_pronounce >= 'た' AND title_pronounce <= 'ど') "; 00811 break; 00812 case 4: 00813 where += "AND ( title_pronounce >= 'な' AND title_pronounce <= 'の') "; 00814 break; 00815 case 5: 00816 where += "AND ( title_pronounce >= 'は' AND title_pronounce <= 'ぽ') "; 00817 break; 00818 case 6: 00819 where += "AND ( title_pronounce >= 'ま' AND title_pronounce <= 'も') "; 00820 break; 00821 case 7: 00822 where += "AND ( title_pronounce >= 'や' AND title_pronounce <= 'よ') "; 00823 break; 00824 case 8: 00825 where += "AND ( title_pronounce >= 'ら' AND title_pronounce <= 'ろ') "; 00826 break; 00827 case 9: 00828 where += "AND ( title_pronounce >= 'わ' AND title_pronounce <= 'ん') "; 00829 break; 00830 case 10: 00831 where += "AND ( title_pronounce >= 'A' AND title_pronounce <= 'z') "; 00832 break; 00833 case 11: 00834 where += "AND ( title_pronounce >= '0' AND title_pronounce <= '9') "; 00835 break; 00836 } 00837 00838 where += "AND starttime > :STARTTIME "; 00839 00840 if (!m_searchStr.isEmpty()) 00841 { 00842 where += "AND title_pronounce LIKE :SEARCH "; 00843 bindings[":SEARCH"] = '%' + m_searchStr + '%'; 00844 } 00845 00846 where += "ORDER BY title_pronounce;"; 00847 00848 bindings[":STARTTIME"] = progStart.addSecs(50 - progStart.time().second()); 00849 } 00850 00851 00852 bool JaProgFinder::formatSelectedData(QString& data) 00853 { 00854 (void)data; 00855 return true; 00856 } 00857 00858 bool JaProgFinder::formatSelectedData(QString& data, int charNum) 00859 { 00860 (void)data; 00861 (void)charNum; 00862 return true; 00863 } 00864 00865 void JaProgFinder::restoreSelectedData(QString& data) 00866 { 00867 (void)data; 00868 } 00869 00870 // Hebrew specific program finder 00871 00872 // Hebrew alphabet list and more 00873 const char* HeProgFinder::searchChars[] = { 00874 "\u05d0", "\u05d1", "\u05d2", "\u05d3", "\u05d4", "\u05d5", "\u05d6", "\u05d7", "\u05d8", 00875 "\u05d9", "\u05db", "\u05dc", "\u05de", "\u05e0", "\u05e1", "\u05e2", "\u05e4", "\u05e6", 00876 "\u05e7", "\u05e8", "\u05e9", "\u05ea", "E", "#", 0 }; 00877 00878 HeProgFinder::HeProgFinder(MythScreenStack *parentStack, bool gg, 00879 TV *player, bool embedVideo) 00880 : ProgFinder(parentStack, gg, player, embedVideo) 00881 { 00882 for (numberOfSearchChars = 0; searchChars[numberOfSearchChars]; 00883 ++numberOfSearchChars) 00884 ; 00885 } 00886 00887 void HeProgFinder::initAlphabetList() 00888 { 00889 for (int charNum = 0; charNum < numberOfSearchChars; ++charNum) 00890 { 00891 new MythUIButtonListItem(m_alphabetList, QString::fromUtf8(searchChars[charNum])); 00892 } 00893 } 00894 00895 // search by hebrew aleph-bet 00896 // # for all numbers, E for all latin 00897 void HeProgFinder::whereClauseGetSearchData(QString &where, MSqlBindings &bindings) 00898 { 00899 QDateTime progStart = QDateTime::currentDateTime(); 00900 QString searchChar = m_alphabetList->GetValue(); 00901 00902 if (searchChar.isEmpty()) 00903 searchChar = searchChars[0]; 00904 00905 where = "SELECT DISTINCT title FROM program " 00906 "LEFT JOIN channel ON program.chanid = channel.chanid " 00907 "WHERE channel.visible = 1 "; 00908 00909 if (searchChar.contains('E')) 00910 { 00911 where += "AND ( title REGEXP '^[A-Z]') "; 00912 } 00913 else if (searchChar.contains('#')) 00914 { 00915 where += "AND ( title REGEXP '^[0-9]') "; 00916 } 00917 else 00918 { 00919 QString one = searchChar + '%'; 00920 bindings[":ONE"] = one; 00921 where += "AND ( title LIKE :ONE ) "; 00922 } 00923 00924 where += "AND starttime > :STARTTIME "; 00925 00926 if (!m_searchStr.isEmpty()) 00927 { 00928 where += "AND title LIKE :SEARCH "; 00929 bindings[":SEARCH"] = '%' + m_searchStr + '%'; 00930 } 00931 00932 where += "ORDER BY title;"; 00933 00934 bindings[":STARTTIME"] = progStart.addSecs(50 - progStart.time().second()); 00935 } 00936 00937 bool HeProgFinder::formatSelectedData(QString& data) 00938 { 00939 (void)data; 00940 return true; 00941 } 00942 00943 bool HeProgFinder::formatSelectedData(QString& data, int charNum) 00944 { 00945 (void)data; 00946 (void)charNum; 00947 return true; 00948 } 00949 00950 void HeProgFinder::restoreSelectedData(QString& data) 00951 { 00952 (void)data; 00953 } 00954 00956 00957 // Cyrrilic specific program finder 00958 // Cyrrilic alphabet list and more 00959 const char* RuProgFinder::searchChars[] = { 00960 "А", "Б", "В", "Г", "Д", "Е", "Ё", "Ж", "З", "И", 00961 "Й", "К", "Л", "М", "Н", "О", "П", "Р", "С", "Т", 00962 "У", "Ф", "Х", "Ц", "Ч", "Ш", "Щ", "Ъ", "Ы", "ь", 00963 "Э", "Ю", "Я", "0", "1", "2", "3", "4", "5", "6", 00964 "7", "8", "9", "@", "A", "B", "C", "D", "E", "F", 00965 "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", 00966 "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", 0 }; 00967 00968 RuProgFinder::RuProgFinder(MythScreenStack *parentStack, bool gg, 00969 TV *player, bool embedVideo) 00970 : ProgFinder(parentStack, gg, player, embedVideo) 00971 { 00972 for (numberOfSearchChars = 0; searchChars[numberOfSearchChars]; 00973 ++numberOfSearchChars) 00974 ; 00975 } 00976 00977 void RuProgFinder::initAlphabetList() 00978 { 00979 for (int charNum = 0; charNum < numberOfSearchChars; ++charNum) 00980 { 00981 new MythUIButtonListItem(m_alphabetList, QString::fromUtf8(searchChars[charNum])); 00982 } 00983 } 00984 00985 // search by cyrillic and latin alphabet 00986 // @ all programm 00987 void RuProgFinder::whereClauseGetSearchData(QString &where, MSqlBindings 00988 &bindings) 00989 { 00990 QDateTime progStart = QDateTime::currentDateTime(); 00991 QString searchChar = m_alphabetList->GetValue(); 00992 00993 if (searchChar.isEmpty()) 00994 searchChar = searchChars[0]; 00995 00996 00997 if (searchChar.contains('@')) 00998 { 00999 where = "SELECT DISTINCT title FROM program " 01000 "LEFT JOIN channel ON program.chanid = channel.chanid " 01001 "WHERE channel.visible = 1 AND " 01002 "( " 01003 "title NOT REGEXP '^[A-Z0-9]' AND " 01004 "title NOT REGEXP '^The [A-Z0-9]' AND " 01005 "title NOT REGEXP '^A [A-Z0-9]' AND " 01006 "title NOT REGEXP '^[0-9]' AND " 01007 "starttime > :STARTTIME ) "; 01008 if (!m_searchStr.isEmpty()) 01009 { 01010 where += "AND title LIKE :SEARCH "; 01011 bindings[":SEARCH"] = '%' + m_searchStr + '%'; 01012 } 01013 01014 where += "ORDER BY title;"; 01015 01016 bindings[":STARTTIME"] = 01017 progStart.addSecs(50 - progStart.time().second()); 01018 } 01019 else 01020 { 01021 QString one = searchChar + '%'; 01022 QString two = QString("The ") + one; 01023 QString three = QString("A ") + one; 01024 QString four = QString("An ") + one; 01025 QString five = QString("\"") + one; 01026 01027 where = "SELECT DISTINCT title FROM program " 01028 "LEFT JOIN channel ON program.chanid = channel.chanid " 01029 "WHERE channel.visible = 1 " 01030 "AND ( title LIKE :ONE OR title LIKE :TWO " 01031 " OR title LIKE :THREE " 01032 " OR title LIKE :FOUR " 01033 " OR title LIKE :FIVE )" 01034 "AND starttime > :STARTTIME "; 01035 if (!m_searchStr.isEmpty()) 01036 where += "AND title LIKE :SEARCH "; 01037 01038 where += "ORDER BY title;"; 01039 01040 bindings[":ONE"] = one; 01041 bindings[":TWO"] = two; 01042 bindings[":THREE"] = three; 01043 bindings[":FOUR"] = four; 01044 bindings[":FIVE"] = five; 01045 bindings[":STARTTIME"] = 01046 progStart.addSecs(50 - progStart.time().second()); 01047 01048 if (!m_searchStr.isEmpty()) 01049 bindings[":SEARCH"] = '%' + m_searchStr + '%'; 01050 } 01051 } 01052 01053 bool RuProgFinder::formatSelectedData(QString& data) 01054 { 01055 (void)data; 01056 return true; 01057 } 01058 01059 bool RuProgFinder::formatSelectedData(QString& data, int charNum) 01060 { 01061 (void)data; 01062 (void)charNum; 01063 return true; 01064 } 01065 01066 void RuProgFinder::restoreSelectedData(QString& data) 01067 { 01068 (void)data; 01069 } 01071 01072 SearchInputDialog::SearchInputDialog(MythScreenStack *parent, 01073 const QString &defaultValue) 01074 : MythTextInputDialog(parent, "", FilterNone, 01075 false, defaultValue) 01076 { 01077 } 01078 01079 bool SearchInputDialog::Create(void) 01080 { 01081 if (!LoadWindowFromXML("schedule-ui.xml", "searchpopup", this)) 01082 return false; 01083 01084 MythUIText *messageText = NULL; 01085 MythUIButton *okButton = NULL; 01086 MythUIButton *cancelButton = NULL; 01087 01088 bool err = false; 01089 UIUtilE::Assign(this, m_textEdit, "input", &err); 01090 UIUtilE::Assign(this, messageText, "message", &err); 01091 UIUtilE::Assign(this, okButton, "ok", &err); 01092 UIUtilW::Assign(this, cancelButton, "cancel"); 01093 01094 if (err) 01095 { 01096 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'searchpopup'"); 01097 return false; 01098 } 01099 01100 if (cancelButton) 01101 connect(cancelButton, SIGNAL(Clicked()), SLOT(Close())); 01102 connect(okButton, SIGNAL(Clicked()), SLOT(sendResult())); 01103 01104 m_textEdit->SetFilter(m_filter); 01105 m_textEdit->SetText(m_defaultValue); 01106 m_textEdit->SetPassword(m_isPassword); 01107 connect(m_textEdit, SIGNAL(valueChanged()), SLOT(editChanged())); 01108 01109 BuildFocusList(); 01110 01111 return true; 01112 } 01113 01114 void SearchInputDialog::editChanged(void) 01115 { 01116 QString inputString = m_textEdit->GetText(); 01117 emit valueChanged(inputString); 01118 01119 if (m_retObject) 01120 { 01121 //FIXME: add a new event type for this? 01122 DialogCompletionEvent *dce = 01123 new DialogCompletionEvent(m_id, 0, inputString, ""); 01124 QCoreApplication::postEvent(m_retObject, dce); 01125 } 01126 } 01127 01128 /* vim: set expandtab tabstop=4 shiftwidth=4: */
1.7.6.1