00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <qlabel.h>
00011 #include <qlayout.h>
00012 #include <qdatetime.h>
00013 #include <qtimer.h>
00014 #include <qapplication.h>
00015 #include <qsqldatabase.h>
00016 #include <qstringlist.h>
00017 #include <qcursor.h>
00018 #include <qregexp.h>
00019 #include <unistd.h>
00020 #include <time.h>
00021 #include <cassert>
00022
00023 #include "progfind.h"
00024 #include "proglist.h"
00025 #include "customedit.h"
00026 #include "infostructs.h"
00027 #include "programinfo.h"
00028 #include "oldsettings.h"
00029 #include "tv.h"
00030 #include "guidegrid.h"
00031
00032 using namespace std;
00033
00034 #include "libmyth/mythcontext.h"
00035 #include "libmyth/mythdbcon.h"
00036
00037 void RunProgramFind(bool thread, bool ggActive)
00038 {
00039 if (thread)
00040 qApp->lock();
00041
00042 gContext->addCurrentLocation("ProgFinder");
00043
00044
00045
00046 ProgFinder *programFind = NULL;
00047 if (gContext->GetLanguage() == "ja")
00048 programFind = new JaProgFinder(gContext->GetMainWindow(),
00049 "program finder", ggActive);
00050 else if (gContext->GetLanguage() == "he")
00051 programFind = new HeProgFinder(gContext->GetMainWindow(),
00052 "program finder", ggActive);
00053 else
00054 programFind = new ProgFinder(gContext->GetMainWindow(),
00055 "program finder", ggActive);
00056
00057 programFind->Initialize();
00058 programFind->Show();
00059
00060 if (thread)
00061 {
00062 qApp->unlock();
00063
00064 while (programFind->isVisible())
00065 usleep(50);
00066 }
00067 else
00068 programFind->exec();
00069
00070 delete programFind;
00071
00072 gContext->removeCurrentLocation();
00073
00074 return;
00075 }
00076
00077 ProgFinder::ProgFinder(MythMainWindow *parent, const char *name, bool gg)
00078 : MythDialog(parent, name),
00079 arrowAccel(true)
00080 {
00081 curSearch = 10;
00082 searchCount = 37;
00083 ggActive = gg;
00084
00085 channelFormat = gContext->GetSetting("ChannelFormat", "<num> <sign>");
00086 arrowAccel = gContext->GetNumSetting("UseArrowAccels", 1);
00087 }
00088
00089 void ProgFinder::Initialize(void)
00090 {
00091 running = true;
00092
00093 allowkeypress = true;
00094 inFill = false;
00095 needFill = false;
00096
00097 baseDir = gContext->GetInstallPrefix();
00098
00099 listRect = QRect(0, 0, 0, 0);
00100 infoRect = QRect(0, 0, 0, 0);
00101
00102 timeFormat = gContext->GetSetting("TimeFormat");
00103 dateFormat = gContext->GetSetting("DateFormat");
00104
00105 theme = new XMLParse();
00106 theme->SetWMult(wmult);
00107 theme->SetHMult(hmult);
00108 theme->LoadTheme(xmldata, "programfind");
00109 LoadWindow(xmldata);
00110
00111 LayerSet *container = theme->GetSet("selector");
00112 assert(container);
00113
00114 UIListType *ltype = (UIListType *)container->GetType("alphabet");
00115 if (ltype)
00116 {
00117 showsPerListing = ltype->GetItems();
00118 }
00119
00120 updateBackground();
00121
00122 progData = new QString[1];
00123 listCount = 1;
00124 if (showsPerListing < 1)
00125 showsPerListing = 7;
00126 if (showsPerListing % 2 == 0)
00127 showsPerListing = showsPerListing + 1;
00128
00129 inSearch = 0;
00130 pastInitial = false;
00131
00132 initData = new QString[(int)(searchCount*showsPerListing)];
00133 gotInitData = new int[searchCount];
00134 searchData = new QString[searchCount];
00135
00136 fillSearchData();
00137 schedList.FromScheduler();
00138
00139 update_Timer = new QTimer(this);
00140 connect(update_Timer, SIGNAL(timeout()), SLOT(update_timeout()) );
00141
00142 getSearchData(curSearch);
00143 showSearchList();
00144
00145 update_Timer->start((int)(100));
00146
00147 setNoErase();
00148 gContext->addListener(this);
00149
00150 showInfo = false;
00151 }
00152
00153 ProgFinder::~ProgFinder()
00154 {
00155 gContext->removeListener(this);
00156
00157 if (inSearch > 0)
00158 delete [] progData;
00159 delete [] searchData;
00160 delete [] initData;
00161
00162 delete [] gotInitData;
00163
00164 delete update_Timer;
00165
00166 delete theme;
00167 }
00168
00169 void ProgFinder::keyPressEvent(QKeyEvent *e)
00170 {
00171 if (!allowkeypress)
00172 return;
00173 allowkeypress = false;
00174
00175 bool handled = false;
00176
00177 QStringList actions;
00178 gContext->GetMainWindow()->TranslateKeyPress("TV Frontend", e, actions);
00179
00180 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00181 {
00182 QString action = actions[i];
00183 handled = true;
00184
00185 if (action == "UP")
00186 cursorUp();
00187 else if (action == "DOWN")
00188 cursorDown();
00189 else if (action == "LEFT")
00190 cursorLeft();
00191 else if (action == "RIGHT")
00192 cursorRight();
00193 else if (action == "PAGEUP")
00194 pageUp();
00195 else if (action == "PAGEDOWN")
00196 pageDown();
00197 else if (action == "5")
00198 pageMiddle();
00199 else if (action == "SELECT" || action == "INFO")
00200 select();
00201 else if (action == "CUSTOMEDIT")
00202 customEdit();
00203 else if (action == "UPCOMING")
00204 upcoming();
00205 else if (action == "DETAILS")
00206 details();
00207 else if (action == "MENU" || action == "ESCAPE")
00208 escape();
00209 else if (action == "TOGGLERECORD")
00210 quickRecord();
00211 else if (action == "GUIDE" || action == "4")
00212 showGuide();
00213 else
00214 handled = false;
00215 }
00216
00217 if (!handled)
00218 MythDialog::keyPressEvent(e);
00219
00220 if (needFill && inSearch == 2)
00221 {
00222 do
00223 {
00224 needFill = false;
00225 ProgramInfo *curPick = showData[curShow];
00226 if (curPick)
00227 selectShowData(curPick->title, curShow);
00228 } while (needFill);
00229 }
00230
00231 allowkeypress = true;
00232 }
00233
00234 void ProgFinder::updateBackground(void)
00235 {
00236 QPixmap bground(size());
00237 bground.fill(this, 0, 0);
00238
00239 QPainter tmp(&bground);
00240
00241 LayerSet *container = theme->GetSet("background");
00242 if (container)
00243 {
00244 if (gContext->GetNumSetting("EPGProgramBar", 1) == 1)
00245 container->Draw(&tmp, 0, 1);
00246 else
00247 container->Draw(&tmp, 0, 0);
00248 }
00249
00250 tmp.end();
00251
00252 setPaletteBackgroundPixmap(bground);
00253 }
00254
00255 void ProgFinder::paintEvent(QPaintEvent *e)
00256 {
00257 if (inFill)
00258 return;
00259
00260 QRect r = e->rect();
00261 QPainter p(this);
00262
00263 if (r.intersects(listRect))
00264 updateList(&p);
00265 if (r.intersects(infoRect))
00266 updateInfo(&p);
00267 }
00268
00269 void ProgFinder::updateList(QPainter *p)
00270 {
00271 QRect pr = listRect;
00272 QPixmap pix(pr.size());
00273 pix.fill(this, pr.topLeft());
00274 QPainter tmp(&pix);
00275
00276 LayerSet *container = NULL;
00277 container = theme->GetSet("selector");
00278 if (container)
00279 {
00280 UIListType *ltype = (UIListType *)container->GetType("alphabet");
00281 if (ltype)
00282 {
00283 if (inSearch == 0)
00284 {
00285 ltype->SetItemCurrent((int)(ltype->GetItems() / 2));
00286 ltype->SetActive(true);
00287 }
00288 else
00289 {
00290 ltype->SetItemCurrent(-1);
00291 ltype->SetActive(false);
00292 }
00293 }
00294
00295 ltype = (UIListType *)container->GetType("shows");
00296 if (ltype)
00297 {
00298 if (inSearch == 1)
00299 {
00300 ltype->SetItemCurrent((int)(ltype->GetItems() / 2));
00301 ltype->SetActive(true);
00302 }
00303 else
00304 {
00305 ltype->SetItemCurrent(-1);
00306 ltype->SetActive(false);
00307 }
00308 }
00309
00310 ltype = (UIListType *)container->GetType("times");
00311 if (ltype)
00312 {
00313 if (inSearch == 2)
00314 {
00315 ltype->SetItemCurrent((int)(ltype->GetItems() / 2));
00316 ltype->SetActive(true);
00317 }
00318 else
00319 {
00320 ltype->SetItemCurrent(-1);
00321 ltype->SetActive(false);
00322 }
00323 }
00324
00325 container->Draw(&tmp, 0, 0);
00326 container->Draw(&tmp, 1, 0);
00327 container->Draw(&tmp, 2, 0);
00328 container->Draw(&tmp, 3, 0);
00329 container->Draw(&tmp, 4, 0);
00330 container->Draw(&tmp, 5, 0);
00331 container->Draw(&tmp, 6, 0);
00332 container->Draw(&tmp, 7, 0);
00333 container->Draw(&tmp, 8, 0);
00334 }
00335
00336 tmp.end();
00337 p->drawPixmap(pr.topLeft(), pix);
00338 }
00339
00340 void ProgFinder::updateInfo(QPainter *p)
00341 {
00342 QRect pr = infoRect;
00343 QPixmap pix(pr.size());
00344 pix.fill(this, pr.topLeft());
00345 QPainter tmp(&pix);
00346
00347 LayerSet *container = NULL;
00348
00349 if (inSearch == 0)
00350 {
00351 QString title = "";
00352 QString description = "";
00353 if (gotInitData[curSearch] == 1)
00354 container = theme->GetSet("noprograms");
00355 else
00356 container = theme->GetSet("help_info_1");
00357 }
00358 else if (inSearch == 1)
00359 {
00360 container = theme->GetSet("help_info_2");
00361 }
00362 else if (inSearch == 2)
00363 {
00364 container = theme->GetSet("program_info");
00365 if (container)
00366 {
00367 container->ClearAllText();
00368 if (gotInitData[curSearch] == 1)
00369 {
00370 UITextType *type = (UITextType *)container->GetType("title");
00371 if (type)
00372 type->SetText(tr("No Programs"));
00373 type = (UITextType *)container->GetType("description");
00374 if (type)
00375 type->SetText(tr("There are no available programs under "
00376 "this search. Please select another "
00377 "search."));
00378 }
00379 else
00380 {
00381 QMap<QString, QString> infoMap;
00382 showData[curShow]->ToMap(infoMap);
00383 container->SetText(infoMap);
00384 }
00385 }
00386 }
00387
00388 if (container)
00389 container->Draw(&tmp, 6, 0);
00390
00391 tmp.end();
00392 p->drawPixmap(pr.topLeft(), pix);
00393 }
00394
00395 void ProgFinder::escape()
00396 {
00397 running = false;
00398 hide();
00399
00400 unsetCursor();
00401 emit accept();
00402 }
00403
00404 void ProgFinder::showGuide()
00405 {
00406 if (!ggActive)
00407 {
00408 QString startchannel = gContext->GetSetting("DefaultTVChannel");
00409 if (startchannel == "")
00410 startchannel = "3";
00411 uint startchanid = 0;
00412 GuideGrid::Run(startchanid, startchannel);
00413 }
00414
00415 running = false;
00416 hide();
00417
00418 unsetCursor();
00419 emit accept();
00420 }
00421
00422 void ProgFinder::LoadWindow(QDomElement &element)
00423 {
00424 for (QDomNode child = element.firstChild(); !child.isNull();
00425 child = child.nextSibling())
00426 {
00427 QDomElement e = child.toElement();
00428 if (!e.isNull())
00429 {
00430 if (e.tagName() == "font")
00431 {
00432 theme->parseFont(e);
00433 }
00434 else if (e.tagName() == "container")
00435 {
00436 parseContainer(e);
00437 }
00438 else
00439 {
00440 cerr << "Unknown element: " << e.tagName() << endl;
00441 continue;
00442 }
00443 }
00444 }
00445 }
00446
00447 void ProgFinder::parseContainer(QDomElement &element)
00448 {
00449 QRect area;
00450 QString name;
00451 int context;
00452 theme->parseContainer(element, name, context, area);
00453
00454 if (name.lower() == "selector")
00455 listRect = area;
00456 if (name.lower() == "program_info")
00457 infoRect = area;
00458 }
00459
00460 void ProgFinder::getInfo(bool toggle)
00461 {
00462 if (inSearch == 2)
00463 {
00464 showInfo = 1;
00465 ProgramInfo *curPick = showData[curShow];
00466
00467 if (curPick)
00468 {
00469 if (toggle)
00470 curPick->ToggleRecord();
00471 else
00472 curPick->EditRecording();
00473 }
00474 else
00475 return;
00476
00477 showInfo = 0;
00478
00479 selectShowData(curPick->title, curShow);
00480
00481 setActiveWindow();
00482 setFocus();
00483 }
00484 }
00485
00486 void ProgFinder::update_timeout()
00487 {
00488 if (pastInitial == false)
00489 {
00490 update_Timer->stop();
00491 pastInitial = true;
00492 getInitialProgramData();
00493 }
00494 else
00495 {
00496 if (inSearch == 0 && gotInitData[curSearch] == 0)
00497 {
00498 int cnt = 0;
00499
00500 for (int j = 0; j < searchCount; j++)
00501 {
00502 if (gotInitData[j] > 1)
00503 cnt++;
00504 }
00505
00506 int amountDone = (int)(100.0 * (float)((float)cnt /
00507 (float)searchCount));
00508 QString data = QString(" Loading Data...%1% Complete")
00509 .arg(amountDone);
00510
00511 LayerSet *container = theme->GetSet("selector");
00512 if (container)
00513 {
00514 UIListType *ltype = (UIListType *)container->GetType("shows");
00515 if (ltype)
00516 ltype->SetItemText((int)(showsPerListing / 2), data);
00517 }
00518 update(listRect);
00519 }
00520 }
00521 }
00522
00523 void ProgFinder::cursorLeft()
00524 {
00525 if (inSearch > 0)
00526 {
00527 inSearch--;
00528 if (inSearch == 0)
00529 showSearchList();
00530 else if (inSearch == 1)
00531 {
00532 showProgramList();
00533 clearShowData();
00534 }
00535 }
00536 else if (inSearch == 0 && arrowAccel)
00537 escape();
00538
00539 update(infoRect);
00540 update(listRect);
00541 }
00542
00543 void ProgFinder::cursorRight()
00544 {
00545 if (inSearch < 2) {
00546 inSearch++;
00547 if (inSearch == 1)
00548 {
00549 if (gotInitData[curSearch] == 0)
00550 getSearchData(curSearch);
00551 if (gotInitData[curSearch] >= 10)
00552 selectSearchData();
00553 if (gotInitData[curSearch] == 1)
00554 {
00555 LayerSet *container = theme->GetSet("selector");
00556 if (container)
00557 {
00558 UIListType *ltype = (UIListType *)container->GetType("shows");
00559 if (ltype)
00560 ltype->SetItemText((int)(showsPerListing / 2),
00561 tr(" !! No Programs !!"));
00562 }
00563 inSearch = 0;
00564 }
00565 }
00566 if (inSearch == 2)
00567 {
00568 if (gotInitData[curSearch] > 10)
00569 selectShowData(progData[curProgram], 0);
00570 else
00571 inSearch = 1;
00572 }
00573 }
00574 else if (inSearch == 2 && arrowAccel)
00575 getInfo();
00576
00577 update(infoRect);
00578 update(listRect);
00579 }
00580
00581 void ProgFinder::select()
00582 {
00583 if (inSearch == 2)
00584 getInfo();
00585 else
00586 cursorRight();
00587 }
00588
00589 void ProgFinder::customEdit()
00590 {
00591 if (inSearch == 2)
00592 {
00593 ProgramInfo *curPick = showData[curShow];
00594
00595 if (!curPick)
00596 return;
00597
00598 CustomEdit *ce = new CustomEdit(gContext->GetMainWindow(),
00599 "customedit", curPick);
00600 ce->exec();
00601 delete ce;
00602 }
00603 else
00604 cursorRight();
00605 }
00606
00607 void ProgFinder::upcoming()
00608 {
00609 if (inSearch == 2)
00610 {
00611 ProgramInfo *curPick = showData[curShow];
00612
00613 if (!curPick)
00614 return;
00615
00616 ProgLister *pl = new ProgLister(plTitle, curPick->title, "",
00617 gContext->GetMainWindow(), "proglist");
00618 pl->exec();
00619 delete pl;
00620 }
00621 else
00622 cursorRight();
00623 }
00624
00625 void ProgFinder::details()
00626 {
00627 if (inSearch == 2)
00628 {
00629 ProgramInfo *curPick = showData[curShow];
00630
00631 if (!curPick)
00632 return;
00633
00634 curPick->showDetails();
00635 }
00636 else
00637 cursorRight();
00638 }
00639
00640 void ProgFinder::quickRecord()
00641 {
00642 if (inSearch == 2)
00643 getInfo(true);
00644 else
00645 cursorRight();
00646 }
00647
00648 void ProgFinder::pageUp()
00649 {
00650 if (inSearch == 0)
00651 {
00652 curSearch = curSearch - showsPerListing;
00653 if (curSearch <= -1)
00654 curSearch = searchCount + curSearch;
00655
00656 if (gotInitData[curSearch] <= 1)
00657 clearProgramList();
00658 else
00659 showSearchList();
00660 }
00661 if (inSearch == 1)
00662 {
00663 curProgram = curProgram - showsPerListing;
00664 if (curProgram <= -1)
00665 curProgram = listCount + curProgram;
00666
00667 showProgramList();
00668 }
00669 if (inSearch == 2)
00670 {
00671 curShow = curShow - showsPerListing;
00672 if (curShow <= -1)
00673 curShow = showCount + curShow;
00674
00675 showShowingList();
00676 }
00677 }
00678
00679 void ProgFinder::pageDown()
00680 {
00681 if (inSearch == 0)
00682 {
00683 curSearch = curSearch + showsPerListing;
00684
00685 if (curSearch >= searchCount)
00686 curSearch = curSearch - searchCount;
00687
00688 if (gotInitData[curSearch] <= 1)
00689 clearProgramList();
00690 else
00691 showSearchList();
00692 }
00693 if (inSearch == 1)
00694 {
00695 curProgram = curProgram + showsPerListing;
00696 if (curProgram >= listCount)
00697 curProgram = curProgram - listCount;
00698
00699 showProgramList();
00700 }
00701 if (inSearch == 2)
00702 {
00703 curShow = curShow + showsPerListing;
00704 if (curShow >= showCount)
00705 curShow = curShow - showCount;
00706
00707 showShowingList();
00708 }
00709 }
00710
00711 void ProgFinder::pageMiddle()
00712 {
00713 if (inSearch == 0)
00714 {
00715 curSearch = searchCount / 2 + 10 - 1;
00716
00717 if (gotInitData[curSearch] <= 1)
00718 clearProgramList();
00719 else
00720 showSearchList();
00721 }
00722 if (inSearch == 1)
00723 {
00724 if (listCount > showsPerListing)
00725 {
00726 curProgram = listCount / 2 - 1;
00727
00728 showProgramList();
00729 }
00730 }
00731 if (inSearch == 2)
00732 {
00733 if (showCount > showsPerListing)
00734 {
00735 curShow = showCount / 2 - 1;
00736
00737 showShowingList();
00738 }
00739 }
00740 }
00741
00742 void ProgFinder::cursorUp()
00743 {
00744 if (inSearch == 0)
00745 {
00746 curSearch--;
00747 if (curSearch == -1)
00748 curSearch = searchCount - 1;
00749
00750 if (gotInitData[curSearch] <= 1)
00751 clearProgramList();
00752 else
00753 showSearchList();
00754 }
00755 if (inSearch == 1)
00756 {
00757 curProgram--;
00758 if (curProgram == -1)
00759 {
00760 curProgram = listCount - 1;
00761 while (progData[curProgram] == "**!0")
00762 curProgram--;
00763 }
00764
00765 showProgramList();
00766 }
00767 if (inSearch == 2)
00768 {
00769 curShow--;
00770 if (curShow == -1)
00771 {
00772 curShow = showCount - 1;
00773 while (!showData[curShow])
00774 curShow--;
00775 }
00776
00777 showShowingList();
00778 }
00779 }
00780
00781 void ProgFinder::cursorDown()
00782 {
00783 if (inSearch == 0)
00784 {
00785 curSearch++;
00786 if (curSearch >= searchCount)
00787 curSearch = 0;
00788
00789 if (gotInitData[curSearch] <= 1)
00790 clearProgramList();
00791 else
00792 showSearchList();
00793 }
00794 if (inSearch == 1)
00795 {
00796 if ((curProgram + 1) >= listCount)
00797 curProgram = -1;
00798
00799 if (progData[curProgram + 1] != "**!0")
00800 {
00801 curProgram++;
00802 if (curProgram == listCount)
00803 curProgram = 0;
00804
00805 showProgramList();
00806 }
00807 else
00808 {
00809 curProgram = 0;
00810 showProgramList();
00811 }
00812 }
00813 if (inSearch == 2)
00814 {
00815 if ((curShow + 1) >= showCount)
00816 curShow = -1;
00817
00818 if (showData[curShow + 1])
00819 {
00820 curShow++;
00821 if (curShow == showCount)
00822 curShow = 0;
00823
00824 showShowingList();
00825 }
00826 else
00827 {
00828 curShow = 0;
00829 showShowingList();
00830 }
00831 }
00832 }
00833
00834 void ProgFinder::showSearchList()
00835 {
00836 int curLabel = 0;
00837 int t = 0;
00838 int tempSearch;
00839 QString placeHold;
00840
00841 tempSearch = curSearch;
00842
00843 LayerSet *container = NULL;
00844 container = theme->GetSet("selector");
00845 if (container)
00846 {
00847 UIListType *ltype = (UIListType *)container->GetType("alphabet");
00848 if (ltype)
00849 {
00850 ltype->ResetList();
00851 for (int i = (tempSearch - ((showsPerListing - 1) / 2));
00852 i < (tempSearch + ((showsPerListing + 1) / 2)); i++)
00853 {
00854 t = i;
00855 if (i < 0)
00856 t = i + searchCount;
00857 if (i >= searchCount)
00858 t = i - searchCount;
00859 if (t < 0)
00860 cerr << "MythProgFind: -1 Error in showSearchList()\n";
00861
00862 if (searchData[t] != NULL)
00863 {
00864 if (curLabel == (int)(showsPerListing / 2))
00865 ltype->SetItemText(curLabel, " " + searchData[t] + " ");
00866 else
00867 ltype->SetItemText(curLabel, " " + searchData[t] + " ");
00868 }
00869 else
00870 ltype->SetItemText(curLabel, "");
00871 curLabel++;
00872 }
00873 }
00874
00875 ltype = (UIListType *)container->GetType("shows");
00876 if (ltype)
00877 {
00878 ltype->ResetList();
00879 if (gotInitData[curSearch] > 1)
00880 {
00881 if (update_Timer->isActive() == true)
00882 update_Timer->stop();
00883
00884 curLabel = 0;
00885
00886 for (int i = (int)(tempSearch * showsPerListing);
00887 i < (int)((tempSearch + 1) * showsPerListing); i++)
00888 {
00889 ltype->EnableForcedFont(curLabel, "inactive");
00890 if (initData[i] != NULL)
00891 {
00892 if (curLabel == (int)(showsPerListing / 2))
00893 ltype->SetItemText(curLabel, " " + initData[i] +
00894 " ");
00895 else
00896 ltype->SetItemText(curLabel, " " + initData[i] +
00897 " ");
00898
00899 ProgramInfo *s;
00900 for (s = schedList.first(); s; s = schedList.next())
00901 if ((s->title == initData[i]) &&
00902 ((s->recstatus == rsRecording) ||
00903 (s->recstatus == rsWillRecord)))
00904 break;
00905
00906 if (s && s->recstatus == rsRecording)
00907 ltype->EnableForcedFont(curLabel, "recording");
00908 else if (s && s->recstatus == rsWillRecord)
00909 ltype->EnableForcedFont(curLabel, "record");
00910 }
00911 else
00912 ltype->SetItemText(curLabel, "");
00913 curLabel++;
00914 }
00915 }
00916 }
00917 else
00918 {
00919 update_Timer->start((int)250);
00920 }
00921 }
00922
00923 update(listRect);
00924 update(infoRect);
00925 }
00926
00927 void ProgFinder::showProgramList()
00928 {
00929 if (gotInitData[curSearch] > 1)
00930 {
00931 LayerSet *container = NULL;
00932 container = theme->GetSet("selector");
00933 if (container)
00934 {
00935 UIListType *ltype = (UIListType *)container->GetType("shows");
00936 if (ltype)
00937 {
00938 int curLabel = 0;
00939 int t = 0;
00940 for (int i = (curProgram - ((showsPerListing - 1) / 2));
00941 i < (curProgram + ((showsPerListing + 1) / 2)); i++)
00942 {
00943 t = i;
00944 if (i < 0)
00945 t = i + listCount;
00946 if (i >= listCount)
00947 t = i - listCount;
00948
00949 if (inSearch == 1)
00950 ltype->EnableForcedFont(curLabel, "active");
00951 else
00952 ltype->EnableForcedFont(curLabel, "inactive");
00953
00954 if (progData[t] != NULL)
00955 {
00956 if (progData[t] != "**!0")
00957 {
00958 if (curLabel == (int)(showsPerListing / 2))
00959 ltype->SetItemText(curLabel, " " + progData[t]
00960 + " ");
00961 else
00962 ltype->SetItemText(curLabel, " " + progData[t]
00963 + " ");
00964
00965 ProgramInfo *s;
00966 for (s = schedList.first(); s; s = schedList.next())
00967 if ((s->title == progData[t]) &&
00968 ((s->recstatus == rsRecording) ||
00969 (s->recstatus == rsWillRecord)))
00970 break;
00971
00972 if (s && s->recstatus == rsRecording)
00973 ltype->EnableForcedFont(curLabel, "recording");
00974 else if (s && s->recstatus == rsWillRecord)
00975 ltype->EnableForcedFont(curLabel, "record");
00976 }
00977 else
00978 ltype->SetItemText(curLabel, "");
00979 }
00980 else
00981 ltype->SetItemText(curLabel, "");
00982 curLabel++;
00983 }
00984 }
00985 }
00986 update(listRect);
00987 }
00988 }
00989
00990 void ProgFinder::showShowingList()
00991 {
00992 int curLabel = 0;
00993 QString tempData = "";
00994
00995 if (showCount > 0)
00996 {
00997 LayerSet *container = NULL;
00998 container = theme->GetSet("selector");
00999 if (container)
01000 {
01001 UIListType *ltype = (UIListType *)container->GetType("times");
01002 if (ltype)
01003 {
01004 ltype->ResetList();
01005 int t = 0;
01006 for (int i = (curShow - ((showsPerListing - 1) / 2));
01007 i < (curShow + ((showsPerListing + 1) / 2)); i++)
01008 {
01009 t = i;
01010 if (i < 0)
01011 t = i + showCount;
01012 if (i >= showCount)
01013 t = i - showCount;
01014
01015 if (showData[t])
01016 {
01017 ltype->SetItemText(curLabel, " "
01018 + showData[t]->startts.toString(dateFormat)
01019 + " " + showData[t]->startts.toString(timeFormat));
01020
01021 if (showData[t]->recstatus == rsRecording)
01022 ltype->EnableForcedFont(curLabel, "recording");
01023 else if (showData[t]->recstatus == rsWillRecord)
01024 ltype->EnableForcedFont(curLabel, "record");
01025
01026 }
01027 else
01028 ltype->SetItemText(curLabel, "");
01029 curLabel++;
01030 }
01031 }
01032 }
01033 }
01034 update(infoRect);
01035 update(listRect);
01036 }
01037
01038 void ProgFinder::selectSearchData()
01039 {
01040 if (running == false)
01041 return;
01042
01043 inFill = true;
01044 QString thequery;
01045 QString data;
01046 MSqlBindings bindings;
01047
01048 MSqlQuery query(MSqlQuery::InitCon());
01049 whereClauseGetSearchData(curSearch, thequery, bindings);
01050
01051 query.prepare(thequery);
01052 query.bindValues(bindings);
01053 query.exec();
01054
01055 int rows = query.size();
01056
01057 if (rows == -1)
01058 {
01059 cerr << "MythProgFind: Error executing query! (selectSearchData)\n";
01060 cerr << "MythProgFind: QUERY = " << thequery.local8Bit() << endl;
01061 return;
01062 }
01063
01064 delete [] progData;
01065
01066 listCount = 0;
01067
01068 if (query.isActive() && rows > 0)
01069 {
01070 typedef QMap<QString,QString> ShowData;
01071 ShowData tempList;
01072
01073 while (query.next())
01074 {
01075 if (running == false)
01076 return;
01077 data = QString::fromUtf8(query.value(0).toString());
01078
01079 if (formatSelectedData(data))
01080 {
01081 tempList[data.lower()] = data;
01082 listCount++;
01083 }
01084 }
01085
01086 if (listCount < showsPerListing)
01087 {
01088 progData = new QString[showsPerListing];
01089 for (int i = 0; i < showsPerListing; i++)
01090 progData[i] = "**!0";
01091 }
01092 else
01093 progData = new QString[(int)listCount];
01094
01095 int cnt = 0;
01096
01097 ShowData::Iterator it;
01098 for (it = tempList.begin(); it != tempList.end(); ++it)
01099 {
01100 QString tmpProgData = it.data();
01101 restoreSelectedData(tmpProgData);
01102
01103 progData[cnt] = tmpProgData;
01104
01105 cnt++;
01106 }
01107 }
01108
01109 if (rows < showsPerListing)
01110 listCount = showsPerListing;
01111
01112 curProgram = 0;
01113 inFill = false;
01114 showProgramList();
01115 }
01116
01117 void ProgFinder::clearProgramList()
01118 {
01119 if (gotInitData[curSearch] == 0)
01120 {
01121 int cnt = 0;
01122 LayerSet *container = theme->GetSet("selector");
01123 if (container)
01124 {
01125 UIListType *ltype = (UIListType *)container->GetType("shows");
01126 if (ltype)
01127 {
01128 for (int i = 0; i < showsPerListing; i++)
01129 ltype->SetItemText(i, "");
01130 }
01131 }
01132
01133 for (int j = 0; j < searchCount; j++)
01134 {
01135 if (gotInitData[j] > 0)
01136 cnt++;
01137 }
01138
01139 int amountDone = (int)(100.0 * (float)((float)cnt /
01140 (float)searchCount));
01141
01142 QString data = QString(" Loading Data...%1% Complete").arg(amountDone);
01143
01144 if (container)
01145 {
01146 UIListType *ltype = (UIListType *)container->GetType("shows");
01147 if (ltype)
01148 ltype->SetItemText((int)(showsPerListing / 2), data);
01149 }
01150 showSearchList();
01151 }
01152 else
01153 {
01154 showSearchList();
01155 }
01156 }
01157
01158 void ProgFinder::clearShowData()
01159 {
01160 showData.clear();
01161
01162 LayerSet *container = theme->GetSet("selector");
01163 if (container)
01164 {
01165 UIListType *ltype = (UIListType *)container->GetType("times");
01166 if (ltype)
01167 {
01168 for (int i = 0; i < showsPerListing; i++)
01169 ltype->SetItemText(i, "");
01170 }
01171 }
01172 update(infoRect);
01173 }
01174
01175 void ProgFinder::selectShowData(QString progTitle, int newCurShow)
01176 {
01177 if (running == false)
01178 return;
01179
01180 inFill = true;
01181 QDateTime progStart = QDateTime::currentDateTime();
01182
01183 schedList.FromScheduler();
01184
01185 MSqlBindings bindings;
01186 QString querystr = "WHERE program.title = :TITLE "
01187 " AND program.endtime > :ENDTIME ";
01188 bindings[":TITLE"] = progTitle.utf8();
01189 bindings[":ENDTIME"] = progStart.toString("yyyy-MM-ddThh:mm:50");
01190
01191 showData.FromProgram(querystr, bindings, schedList);
01192
01193 showCount = showData.count();
01194 if (showCount < showsPerListing)
01195 showCount = showsPerListing;
01196
01197 curShow = newCurShow;
01198 inFill = false;
01199 showShowingList();
01200 }
01201
01202 void ProgFinder::getInitialProgramData()
01203 {
01204 getAllProgramData();
01205 }
01206
01207 void ProgFinder::getSearchData(int charNum)
01208 {
01209 if (running == false)
01210 return;
01211
01212 int cnts = 0;
01213 int dataNum = 0;
01214 int startPlace = 0;
01215 QString thequery;
01216 QString data;
01217 MSqlBindings bindings;
01218
01219 whereClauseGetSearchData(charNum, thequery, bindings);
01220
01221 MSqlQuery query(MSqlQuery::InitCon());
01222 query.prepare(thequery);
01223 query.bindValues(bindings);
01224 query.exec();
01225
01226 int rows = query.size();
01227
01228 if (rows == -1)
01229 {
01230 cerr << "MythProgFind: Error executing query! (getSearchData)\n";
01231 cerr << "MythProgFind: QUERY = " << thequery << endl;
01232 return;
01233 }
01234
01235 startPlace = (int)(charNum*showsPerListing);
01236 dataNum = (int)(showsPerListing / 2);
01237
01238 if (query.isActive() && rows > 0)
01239 {
01240 typedef QMap<QString,QString> ShowData;
01241 ShowData tempList;
01242
01243 while (query.next())
01244 {
01245 data = QString::fromUtf8(query.value(0).toString());
01246
01247 if (formatSelectedData(data, charNum))
01248 {
01249 tempList[data.lower()] = data;
01250 cnts++;
01251 }
01252 }
01253
01254 int cnt = 0;
01255 int dNum = 0;
01256
01257 ShowData::Iterator it;
01258 for (it = tempList.begin(); it != tempList.end(); ++it)
01259 {
01260 if (cnt <= (int)(showsPerListing / 2))
01261 {
01262 data = it.data();
01263 restoreSelectedData(data);
01264 initData[startPlace + dataNum] = data;
01265 dataNum++;
01266 }
01267
01268 if (cnt >= (cnts - (int)(showsPerListing / 2)) &&
01269 rows >= showsPerListing)
01270 {
01271 data = it.data();
01272 restoreSelectedData(data);
01273 initData[startPlace + dNum] = data;
01274 dNum++;
01275 }
01276
01277 cnt++;
01278 }
01279 }
01280
01281 if (cnts == 0)
01282 gotInitData[charNum] = 1;
01283 else
01284 {
01285 gotInitData[charNum] = 10 + cnts;
01286 }
01287
01288 if (charNum == curSearch)
01289 showSearchList();
01290 }
01291
01292 void ProgFinder::fillSearchData(void)
01293 {
01294 int curLabel = 0;
01295
01296 for (int charNum = 48; charNum < 91; charNum++)
01297 {
01298 if (charNum == 58)
01299 charNum = 65;
01300
01301 gotInitData[curLabel] = 0;
01302 searchData[curLabel] = (char)charNum;
01303 curLabel++;
01304 }
01305
01306 gotInitData[curLabel] = 0;
01307 searchData[curLabel] = '@';
01308 }
01309
01310 void ProgFinder::whereClauseGetSearchData(int charNum, QString &where,
01311 MSqlBindings &bindings)
01312 {
01313 QDateTime progStart = QDateTime::currentDateTime();
01314
01315 if (searchData[charNum].contains('@'))
01316 {
01317 where = "SELECT DISTINCT title FROM program WHERE ( "
01318 "title NOT REGEXP '^[A-Z0-9]' AND "
01319 "title NOT REGEXP '^The [A-Z0-9]' AND "
01320 "title NOT REGEXP '^A [A-Z0-9]' AND "
01321 "title NOT REGEXP '^An [A-Z0-9]' AND "
01322 "starttime > :STARTTIME ) ORDER BY title;";
01323 bindings[":STARTTIME"] = progStart.toString("yyyy-MM-ddThh:mm:50");
01324 }
01325 else
01326 {
01327 QString one = searchData[charNum] + "%";
01328 QString two = QString("The ") + one;
01329 QString three = QString("A ") + one;
01330 QString four = QString("An ") + one;
01331 where = "SELECT DISTINCT title "
01332 "FROM program "
01333 "WHERE ( title LIKE :ONE OR title LIKE :TWO "
01334 " OR title LIKE :THREE "
01335 " OR title LIKE :FOUR ) "
01336 "AND starttime > :STARTTIME "
01337 "ORDER BY title;";
01338 bindings[":ONE"] = one.utf8();
01339 bindings[":TWO"] = two.utf8();
01340 bindings[":THREE"] = three.utf8();
01341 bindings[":FOUR"] = four.utf8();
01342 bindings[":STARTTIME"] = progStart.toString("yyyy-MM-ddThh:mm:50");
01343 }
01344 }
01345
01346 bool ProgFinder::formatSelectedData(QString& data)
01347 {
01348 bool retval = true;
01349
01350 if (searchData[curSearch] == "T" || searchData[curSearch] == "A")
01351 {
01352 if (data.left(5) == "The T" && searchData[curSearch] == "T")
01353 data = data.mid(4) + ", The";
01354 else if (data.left(5) == "The A" && searchData[curSearch] == "A")
01355 data = data.mid(4) + ", The";
01356 else if (data.left(3) == "A T" && searchData[curSearch] == "T")
01357 data = data.mid(2) + ", A";
01358 else if (data.left(3) == "A A" && searchData[curSearch] == "A")
01359 data = data.mid(2) + ", A";
01360 else if (data.left(4) == "An A" && searchData[curSearch] == "A")
01361 data = data.mid(3) + ", An";
01362 else if (data.left(4) != "The " && data.left(2) != "A ")
01363 {
01364
01365 }
01366 else
01367 {
01368
01369 retval = false;
01370 }
01371 }
01372 else
01373 {
01374 if (data.left(4) == "The ")
01375 data = data.mid(4) + ", The";
01376 if (data.left(2) == "A ")
01377 data = data.mid(2) + ", A";
01378 if (data.left(3) == "An ")
01379 data = data.mid(3) + ", An";
01380 }
01381
01382 return retval;
01383 }
01384
01385 bool ProgFinder::formatSelectedData(QString& data, int charNum)
01386 {
01387 bool retval = true;
01388
01389 if (charNum == 29 || charNum == 10)
01390 {
01391 if (data.left(5) == "The T" && charNum == 29)
01392 data = data.mid(4) + ", The";
01393 else if (data.left(5) == "The A" && charNum == 10)
01394 data = data.mid(4) + ", The";
01395 else if (data.left(3) == "A T" && charNum == 29)
01396 data = data.mid(2) + ", A";
01397 else if (data.left(3) == "A A" && charNum == 10)
01398 data = data.mid(2) + ", A";
01399 else if (data.left(4) == "An A" && charNum == 10)
01400 data = data.mid(3) + ", An";
01401 else if (data.left(4) != "The " && data.left(2) != "A ")
01402 {
01403
01404 }
01405 else
01406 {
01407
01408 retval = false;
01409 }
01410 }
01411 else
01412 {
01413 if (data.left(4) == "The ")
01414 data = data.mid(4) + ", The";
01415 if (data.left(2) == "A ")
01416 data = data.mid(2) + ", A";
01417 if (data.left(3) == "An ")
01418 data = data.mid(3) + ", An";
01419 }
01420
01421 return retval;
01422 }
01423
01424 void ProgFinder::restoreSelectedData(QString &data)
01425 {
01426 if (data.right(5) == ", The")
01427 data = "The " + data.left(data.length() - 5);
01428 if (data.right(4) == ", An")
01429 data = "An " + data.left(data.length() - 4);
01430 if (data.right(3) == ", A")
01431 data = "A " + data.left(data.length() - 3);
01432 }
01433
01434 void ProgFinder::getAllProgramData()
01435 {
01436 getSearchData(8);
01437 getSearchData(9);
01438 getSearchData(11);
01439 getSearchData(12);
01440
01441 for (int charNum = 0; charNum < searchCount; charNum++)
01442 {
01443 if (charNum == 8)
01444 charNum = 13;
01445
01446 getSearchData(charNum);
01447 }
01448 }
01449
01450 void ProgFinder::customEvent(QCustomEvent *e)
01451 {
01452 if ((MythEvent::Type)(e->type()) == MythEvent::MythEventMessage)
01453 {
01454 MythEvent *me = (MythEvent *)e;
01455 QString message = me->Message();
01456
01457 if (message == "SCHEDULE_CHANGE")
01458 {
01459 if (inSearch == 2)
01460 {
01461 if (!allowkeypress)
01462 {
01463 needFill = true;
01464 return;
01465 }
01466
01467 allowkeypress = false;
01468
01469 do
01470 {
01471 needFill = false;
01472 ProgramInfo *curPick = showData[curShow];
01473 if (curPick)
01474 selectShowData(curPick->title, curShow);
01475 showProgramList();
01476 } while (needFill);
01477
01478 allowkeypress = true;
01479 }
01480 }
01481 }
01482 }
01483
01484
01485
01486
01487
01488 const char* JaProgFinder::searchChars[] = {
01489 "あ", "か", "さ", "た", "な", "は", "ま", "や", "ら", "わ",
01490 "英", "数",
01491 0,
01492 };
01493
01494 JaProgFinder::JaProgFinder(MythMainWindow *parent, const char *name, bool gg)
01495 : ProgFinder(parent, name, gg)
01496 {
01497 for (numberOfSearchChars = 0; searchChars[numberOfSearchChars];
01498 numberOfSearchChars++)
01499 ;
01500
01501 searchCount = numberOfSearchChars;
01502 curSearch = 0;
01503 }
01504
01505 void JaProgFinder::fillSearchData()
01506 {
01507 int curLabel = 0;
01508 for (int charNum = 0; charNum < searchCount; charNum++)
01509 {
01510 gotInitData[curLabel] = 0;
01511 searchData[curLabel] = QString::fromUtf8(searchChars[charNum]);
01512 curLabel++;
01513 }
01514 }
01515
01516
01517
01518
01519
01520 void JaProgFinder::whereClauseGetSearchData(int charNum, QString &where,
01521 MSqlBindings &bindings)
01522 {
01523 QDateTime progStart = QDateTime::currentDateTime();
01524
01525 where = "SELECT DISTINCT title FROM program ";
01526
01527 switch (charNum) {
01528 case 0:
01529 where += "WHERE ( title_pronounce >= 'あ' AND title_pronounce <= 'お') ";
01530 break;
01531 case 1:
01532 where += "WHERE ( title_pronounce >= 'か' AND title_pronounce <= 'ご') ";
01533 break;
01534 case 2:
01535 where += "WHERE ( title_pronounce >= 'さ' AND title_pronounce <= 'そ') ";
01536 break;
01537 case 3:
01538 where += "WHERE ( title_pronounce >= 'た' AND title_pronounce <= 'ど') ";
01539 break;
01540 case 4:
01541 where += "WHERE ( title_pronounce >= 'な' AND title_pronounce <= 'の') ";
01542 break;
01543 case 5:
01544 where += "WHERE ( title_pronounce >= 'は' AND title_pronounce <= 'ぽ') ";
01545 break;
01546 case 6:
01547 where += "WHERE ( title_pronounce >= 'ま' AND title_pronounce <= 'も') ";
01548 break;
01549 case 7:
01550 where += "WHERE ( title_pronounce >= 'や' AND title_pronounce <= 'よ') ";
01551 break;
01552 case 8:
01553 where += "WHERE ( title_pronounce >= 'ら' AND title_pronounce <= 'ろ') ";
01554 break;
01555 case 9:
01556 where += "WHERE ( title_pronounce >= 'わ' AND title_pronounce <= 'ん') ";
01557 break;
01558 case 10:
01559 where += "WHERE ( title_pronounce >= 'A' AND title_pronounce <= 'z') ";
01560 break;
01561 case 11:
01562 where += "WHERE ( title_pronounce >= '0' AND title_pronounce <= '9') ";
01563 break;
01564 }
01565
01566 where += "AND starttime > :STARTTIME ORDER BY title_pronounce;";
01567 bindings[":STARTTIME"] = progStart.toString("yyyy-MM-ddThh:mm:50");
01568 }
01569
01570
01571 bool JaProgFinder::formatSelectedData(QString& data)
01572 {
01573 (void)data;
01574 return true;
01575 }
01576
01577 bool JaProgFinder::formatSelectedData(QString& data, int charNum)
01578 {
01579 (void)data;
01580 (void)charNum;
01581 return true;
01582 }
01583
01584 void JaProgFinder::restoreSelectedData(QString& data)
01585 {
01586 (void)data;
01587 }
01588
01589 void JaProgFinder::getAllProgramData()
01590 {
01591 for (int charNum = 0; charNum < searchCount; charNum++)
01592 {
01593 getSearchData(charNum);
01594 }
01595 }
01596
01597
01598
01599
01600 const char* HeProgFinder::searchChars[] = {
01601 "א", "ב", "ג", "ד", "ה", "ו", "ז", "ח", "ט", "י", "כ", "ל", "מ",
01602 "נ", "ס", "ע", "פ", "צ", "ק", "ר", "ש", "ת", "E", "#", 0,
01603 };
01604
01605 HeProgFinder::HeProgFinder(MythMainWindow *parent, const char *name, bool gg)
01606 : ProgFinder(parent, name, gg)
01607 {
01608 for (numberOfSearchChars = 0; searchChars[numberOfSearchChars];
01609 numberOfSearchChars++)
01610 ;
01611
01612 searchCount = numberOfSearchChars;
01613 curSearch = 0;
01614 }
01615
01616 void HeProgFinder::fillSearchData()
01617 {
01618 int curLabel = 0;
01619 for (int charNum = 0; charNum < searchCount; charNum++)
01620 {
01621 gotInitData[curLabel] = 0;
01622 searchData[curLabel] = QString::fromUtf8(searchChars[charNum]);
01623 curLabel++;
01624 }
01625 }
01626
01627
01628
01629 void HeProgFinder::whereClauseGetSearchData(int charNum, QString &where,
01630 MSqlBindings &bindings)
01631 {
01632 QDateTime progStart = QDateTime::currentDateTime();
01633
01634 where = "SELECT DISTINCT title FROM program ";
01635
01636 if (searchData[charNum].contains('E'))
01637 {
01638 where += "WHERE ( title REGEXP '^[A-Z]') ";
01639 }
01640 else if (searchData[charNum].contains('#'))
01641 {
01642 where += "WHERE ( title REGEXP '^[0-9]') ";
01643 }
01644 else
01645 {
01646 QString one = searchData[charNum] + "%";
01647 bindings[":ONE"] = one.local8Bit();
01648 where += "WHERE ( title LIKE :ONE ) ";
01649 }
01650
01651 where += "AND starttime > :STARTTIME ORDER BY title;";
01652 bindings[":STARTTIME"] = progStart.toString("yyyy-MM-ddThh:mm:50");
01653 }
01654
01655 bool HeProgFinder::formatSelectedData(QString& data)
01656 {
01657 (void)data;
01658 return true;
01659 }
01660
01661 bool HeProgFinder::formatSelectedData(QString& data, int charNum)
01662 {
01663 (void)data;
01664 (void)charNum;
01665 return true;
01666 }
01667
01668 void HeProgFinder::restoreSelectedData(QString& data)
01669 {
01670 (void)data;
01671 }
01672
01673 void HeProgFinder::getAllProgramData()
01674 {
01675 for (int charNum = 0; charNum < searchCount; charNum++)
01676 {
01677 getSearchData(charNum);
01678 }
01679 }
01680
01681
01682