00001 #include <qapplication.h>
00002 #include <qpainter.h>
00003 #include <qfont.h>
00004 #include <qsqldatabase.h>
00005 #include <qsqlquery.h>
00006 #include <math.h>
00007 #include <qcursor.h>
00008 #include <qapplication.h>
00009 #include <qimage.h>
00010 #include <qlayout.h>
00011 #include <qlabel.h>
00012 #include <qdatetime.h>
00013 #include <qvgroupbox.h>
00014 #include <qheader.h>
00015 #include <qrect.h>
00016
00017 #include <unistd.h>
00018 #include <iostream>
00019 #include <algorithm>
00020 using namespace std;
00021
00022 #include "mythcontext.h"
00023 #include "mythdbcon.h"
00024 #include "guidegrid.h"
00025 #include "infostructs.h"
00026 #include "programinfo.h"
00027 #include "scheduledrecording.h"
00028 #include "oldsettings.h"
00029 #include "tv_play.h"
00030 #include "tv_rec.h"
00031 #include "progfind.h"
00032 #include "proglist.h"
00033 #include "customedit.h"
00034 #include "util.h"
00035 #include "remoteutil.h"
00036 #include "channelutil.h"
00037 #include "cardutil.h"
00038
00039 DBChanList GuideGrid::Run(
00040 uint chanid,
00041 const QString &channum,
00042 bool thread,
00043 TV *player,
00044 bool allowsecondaryepg)
00045 {
00046 DBChanList channel_changed;
00047
00048 if (thread)
00049 qApp->lock();
00050
00051 gContext->addCurrentLocation("GuideGrid");
00052
00053 GuideGrid *gg = new GuideGrid(gContext->GetMainWindow(),
00054 chanid, channum,
00055 player, allowsecondaryepg, "guidegrid");
00056
00057 gg->Show();
00058
00059 if (thread)
00060 {
00061 qApp->unlock();
00062
00063 while (gg->isVisible())
00064 usleep(50);
00065 }
00066 else
00067 gg->exec();
00068
00069 if (gg->selectState)
00070 {
00071 DBChanList sel = gg->GetSelection();
00072 if (sel.size() &&
00073 (std::find(sel.begin(), sel.end(), chanid) == sel.end()))
00074 {
00075 channel_changed = sel;
00076 }
00077 }
00078
00079 if (thread)
00080 qApp->lock();
00081
00082 delete gg;
00083
00084 gContext->removeCurrentLocation();
00085
00086 if (thread)
00087 qApp->unlock();
00088
00089 return channel_changed;
00090 }
00091
00092 GuideGrid::GuideGrid(MythMainWindow *parent,
00093 uint chanid, QString channum,
00094 TV *player, bool allowsecondaryepg,
00095 const char *name)
00096 : MythDialog(parent, name)
00097 {
00098 desiredDisplayChans = DISPLAY_CHANS = 6;
00099 DISPLAY_TIMES = 30;
00100 int maxchannel = 0;
00101 m_currentStartChannel = 0;
00102
00103 m_player = player;
00104
00105 m_context = 0;
00106
00107 fullRect = QRect(0, 0, size().width(), size().height());
00108 dateRect = QRect(0, 0, 0, 0);
00109 jumpToChannelRect = QRect(0, 0, 0, 0);
00110 channelRect = QRect(0, 0, 0, 0);
00111 timeRect = QRect(0, 0, 0, 0);
00112 programRect = QRect(0, 0, 0, 0);
00113 infoRect = QRect(0, 0, 0, 0);
00114 curInfoRect = QRect(0, 0, 0, 0);
00115 videoRect = QRect(0, 0, 0, 0);
00116
00117 jumpToChannelEnabled = gContext->GetNumSetting("EPGEnableJumpToChannel", 0);
00118 jumpToChannelActive = false;
00119 jumpToChannelHasRect = false;
00120 jumpToChannelTimer = new QTimer(this);
00121 connect(jumpToChannelTimer, SIGNAL(timeout()), SLOT(jumpToChannelTimeout()));
00122
00123 theme = new XMLParse();
00124 theme->SetWMult(wmult);
00125 theme->SetHMult(hmult);
00126 if (m_player && m_player->IsRunning() && allowsecondaryepg)
00127 theme->LoadTheme(xmldata, "programguide-video");
00128 else
00129 theme->LoadTheme(xmldata, "programguide");
00130
00131 LoadWindow(xmldata);
00132
00133 if (m_player && m_player->IsRunning() && !allowsecondaryepg)
00134 videoRect = QRect(0, 0, 1, 1);
00135
00136 showFavorites = gContext->GetNumSetting("EPGShowFavorites", 0);
00137 gridfilltype = gContext->GetNumSetting("EPGFillType", UIGuideType::Alpha);
00138 if (gridfilltype < (int)UIGuideType::Alpha)
00139 {
00140 if (gridfilltype == 5)
00141 gridfilltype = UIGuideType::Dense;
00142 else
00143 gridfilltype = UIGuideType::Alpha;
00144
00145 gContext->SaveSetting("EPGFillType", gridfilltype);
00146 }
00147
00148 scrolltype = gContext->GetNumSetting("EPGScrollType", 1);
00149 sortReverse = gContext->GetNumSetting("EPGSortReverse", 0);
00150
00151 selectChangesChannel = gContext->GetNumSetting("SelectChangesChannel", 0);
00152 selectRecThreshold = gContext->GetNumSetting("SelChangeRecThreshold", 16);
00153
00154 LayerSet *container = NULL;
00155 container = theme->GetSet("guide");
00156 if (container)
00157 {
00158 UIGuideType *type = (UIGuideType *)container->GetType("guidegrid");
00159 if (type)
00160 {
00161 type->SetFillType(gridfilltype);
00162 type->SetShowCategoryColors(
00163 gContext->GetNumSetting("EPGShowCategoryColors", 1));
00164 type->SetShowCategoryText(
00165 gContext->GetNumSetting("EPGShowCategoryText", 1));
00166 }
00167 if (gridfilltype == UIGuideType::Eco)
00168 container->SetDrawFontShadow(false);
00169 }
00170
00171 timeformat = gContext->GetSetting("TimeFormat", "h:mm AP");
00172
00173 QTime new_time = QTime::currentTime();
00174 QString curTime = new_time.toString(timeformat);
00175
00176 container = theme->GetSet("current_info");
00177 if (container)
00178 {
00179 UITextType *type = (UITextType *)container->GetType("time");
00180 if (type)
00181 type->SetText(curTime);
00182 if (gridfilltype == UIGuideType::Eco)
00183 container->SetDrawFontShadow(false);
00184 }
00185
00186 container = theme->GetSet("program_info");
00187 if (container)
00188 {
00189 if (gridfilltype == UIGuideType::Eco)
00190 container->SetDrawFontShadow(false);
00191 }
00192
00193 channelOrdering = gContext->GetSetting("ChannelOrdering", "channum");
00194 dateformat = gContext->GetSetting("ShortDateFormat", "ddd d");
00195 unknownTitle = gContext->GetSetting("UnknownTitle", "Unknown");
00196 unknownCategory = gContext->GetSetting("UnknownCategory", "Unknown");
00197 channelFormat = gContext->GetSetting("ChannelFormat", "<num> <sign>");
00198 channelFormat.replace(" ", "\n");
00199
00200 UIBarType *type = NULL;
00201 container = theme->GetSet("chanbar");
00202
00203 int dNum = gContext->GetNumSetting("chanPerPage", 8);
00204
00205 if (m_player && m_player->IsRunning() && allowsecondaryepg)
00206 dNum = dNum * 2 / 3 + 1;
00207
00208 desiredDisplayChans = DISPLAY_CHANS = dNum;
00209 if (container)
00210 {
00211 type = (UIBarType *)container->GetType("chans");
00212 if (type)
00213 type->SetSize(dNum);
00214 if (gridfilltype == UIGuideType::Eco)
00215 container->SetDrawFontShadow(false);
00216 }
00217
00218 container = theme->GetSet("timebar");
00219 dNum = gContext->GetNumSetting("timePerPage", 5);
00220 if (dNum > 5)
00221 dNum = 5;
00222 DISPLAY_TIMES = 6 * dNum;
00223
00224 if (container)
00225 {
00226 type = (UIBarType *)container->GetType("times");
00227 if (type)
00228 type->SetSize(dNum);
00229 if (gridfilltype == UIGuideType::Eco)
00230 container->SetDrawFontShadow(false);
00231 }
00232 m_originalStartTime = QDateTime::currentDateTime();
00233
00234 int secsoffset = -((m_originalStartTime.time().minute() % 30) * 60 +
00235 m_originalStartTime.time().second());
00236 m_currentStartTime = m_originalStartTime.addSecs(secsoffset);
00237 startChanID = chanid;
00238 startChanNum = channum;
00239
00240 m_currentRow = (int)(desiredDisplayChans / 2);
00241 m_currentCol = 0;
00242
00243 for (int y = 0; y < MAX_DISPLAY_CHANS; y++)
00244 m_programs[y] = NULL;
00245
00246 for (int x = 0; x < MAX_DISPLAY_TIMES; x++)
00247 {
00248 m_timeInfos[x] = NULL;
00249 for (int y = 0; y < MAX_DISPLAY_CHANS; y++)
00250 m_programInfos[y][x] = NULL;
00251 }
00252
00253
00254
00255 fillTimeInfos();
00256
00257
00258 fillChannelInfos();
00259 maxchannel = max((int)GetChannelCount() - 1, 0);
00260 setStartChannel((int)(m_currentStartChannel) -
00261 (int)(desiredDisplayChans / 2));
00262 DISPLAY_CHANS = min(DISPLAY_CHANS, maxchannel + 1);
00263
00264
00265
00266 m_recList.FromScheduler();
00267 fillProgramInfos();
00268
00269
00270 timeCheck = NULL;
00271 timeCheck = new QTimer(this);
00272 connect(timeCheck, SIGNAL(timeout()), SLOT(timeCheckTimeout()) );
00273 timeCheck->start(200);
00274
00275 videoRepaintTimer = new QTimer(this);
00276 QObject::connect(videoRepaintTimer, SIGNAL(timeout()),
00277 this, SLOT(repaintVideoTimeout()));
00278 videoRepaintTimer->start(1000);
00279
00280 selectState = false;
00281
00282 updateBackground();
00283
00284 setNoErase();
00285 gContext->addListener(this);
00286
00287 keyDown = false;
00288 setFocusPolicy(QWidget::ClickFocus);
00289 }
00290
00291 GuideGrid::~GuideGrid()
00292 {
00293 gContext->removeListener(this);
00294 for (int x = 0; x < MAX_DISPLAY_TIMES; x++)
00295 {
00296 if (m_timeInfos[x])
00297 {
00298 delete m_timeInfos[x];
00299 m_timeInfos[x] = NULL;
00300 }
00301 }
00302
00303 for (int y = 0; y < MAX_DISPLAY_CHANS; y++)
00304 {
00305 if (m_programs[y])
00306 {
00307 delete m_programs[y];
00308 m_programs[y] = NULL;
00309 }
00310 }
00311
00312 m_channelInfos.clear();
00313
00314 if (theme)
00315 {
00316 delete theme;
00317 theme = NULL;
00318 }
00319
00320 if (jumpToChannelTimer)
00321 {
00322 jumpToChannelTimer->deleteLater();
00323 jumpToChannelTimer = NULL;
00324 }
00325
00326 if (timeCheck)
00327 {
00328 timeCheck->deleteLater();
00329 timeCheck = NULL;
00330 }
00331
00332 if (videoRepaintTimer)
00333 {
00334 videoRepaintTimer->deleteLater();
00335 videoRepaintTimer = NULL;
00336 }
00337
00338 gContext->SaveSetting("EPGSortReverse", sortReverse ? "1" : "0");
00339 }
00340
00341 void GuideGrid::keyPressEvent(QKeyEvent *e)
00342 {
00343
00344
00345
00346
00347
00348
00349
00350 bool handled = false;
00351
00352 QStringList actions;
00353 gContext->GetMainWindow()->TranslateKeyPress("TV Frontend", e, actions);
00354
00355 if (actions.size() > 0 && keyDown && actions[0] != "ESCAPE")
00356 return;
00357
00358
00359 if (e->key() != Key_Control && e->key() != Key_Shift &&
00360 e->key() != Key_Meta && e->key() != Key_Alt)
00361 keyDown = true;
00362
00363 if (e->state() == Qt::ControlButton)
00364 {
00365 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00366 {
00367 QString action = actions[i];
00368 handled = true;
00369
00370 if (action == "LEFT")
00371 pageLeft();
00372 else if (action == "RIGHT")
00373 pageRight();
00374 else if (action == "UP")
00375 pageUp();
00376 else if (action == "DOWN")
00377 pageDown();
00378 else
00379 handled = false;
00380 }
00381 handled = true;
00382 }
00383 else
00384 {
00385
00386
00387
00388
00389 if (jumpToChannelEnabled)
00390 {
00391 int digit;
00392 if (jumpToChannelGetInputDigit(actions, digit))
00393 {
00394 jumpToChannelDigitPress(digit);
00395
00396
00397 handled = true;
00398 }
00399 }
00400
00401 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00402 {
00403 QString action = actions[i];
00404 handled = true;
00405
00406 if (action == "LEFT")
00407 cursorLeft();
00408 else if (action == "RIGHT")
00409 cursorRight();
00410 else if (action == "DOWN")
00411 cursorDown();
00412 else if (action == "UP")
00413 cursorUp();
00414 else if (action == "PAGEUP")
00415 pageUp();
00416 else if (action == "PAGEDOWN")
00417 pageDown();
00418 else if (action == "PAGELEFT")
00419 pageLeft();
00420 else if (action == "PAGERIGHT")
00421 pageRight();
00422 else if (action == "DAYLEFT")
00423 dayLeft();
00424 else if (action == "DAYRIGHT")
00425 dayRight();
00426 else if (jumpToChannelEnabled && jumpToChannelActive &&
00427 (action == "ESCAPE"))
00428 jumpToChannelCancel();
00429 else if (jumpToChannelEnabled && jumpToChannelActive &&
00430 (action == "DELETE"))
00431 jumpToChannelDeleteLastDigit();
00432 else if (action == "NEXTFAV" || action == "4")
00433 toggleGuideListing();
00434 else if (action == "FINDER" || action == "6")
00435 showProgFinder();
00436 else if (action == "MENU")
00437 enter();
00438 else if (action == "ESCAPE")
00439 escape();
00440 else if (action == "SELECT")
00441 {
00442 if (m_player && selectChangesChannel)
00443 {
00444
00445
00446 ProgramInfo *pginfo = m_programInfos[m_currentRow][m_currentCol];
00447 if (pginfo && (pginfo->title != unknownTitle) &&
00448 ((pginfo->SecsTillStart() / 60) >= selectRecThreshold))
00449 {
00450 editRecording();
00451 }
00452 else
00453 {
00454 enter();
00455 }
00456 }
00457 else
00458 editRecording();
00459 }
00460 else if (action == "INFO")
00461 editScheduled();
00462 else if (action == "CUSTOMEDIT")
00463 customEdit();
00464 else if (action == "DELETE")
00465 remove();
00466 else if (action == "UPCOMING")
00467 upcoming();
00468 else if (action == "DETAILS")
00469 details();
00470 else if (action == "TOGGLERECORD")
00471 quickRecord();
00472 else if (action == "TOGGLEFAV")
00473 toggleChannelFavorite();
00474 else if (action == "CHANUPDATE")
00475 channelUpdate();
00476 else if (action == "VOLUMEUP")
00477 volumeUpdate(true);
00478 else if (action == "VOLUMEDOWN")
00479 volumeUpdate(false);
00480 else if (action == "MUTE")
00481 toggleMute();
00482 else if (action == "TOGGLEEPGORDER")
00483 {
00484 sortReverse = !sortReverse;
00485 generateListings();
00486 }
00487 else
00488 handled = false;
00489 }
00490 }
00491
00492 if (!handled)
00493 MythDialog::keyPressEvent(e);
00494 }
00495
00496 void GuideGrid::keyReleaseEvent(QKeyEvent *e)
00497 {
00498
00499
00500 (void)e;
00501 keyDown = false;
00502 }
00503
00504 void GuideGrid::updateBackground(void)
00505 {
00506 QPixmap bground(size());
00507 bground.fill(this, 0, 0);
00508
00509 QPainter tmp(&bground);
00510
00511 LayerSet *container = theme->GetSet("background");
00512 if (container)
00513 container->Draw(&tmp, 0, 0);
00514
00515 tmp.end();
00516
00517 setPaletteBackgroundPixmap(bground);
00518 }
00519
00520 void GuideGrid::LoadWindow(QDomElement &element)
00521 {
00522 for (QDomNode child = element.firstChild(); !child.isNull();
00523 child = child.nextSibling())
00524 {
00525 QDomElement e = child.toElement();
00526 if (!e.isNull())
00527 {
00528 if (e.tagName() == "font")
00529 {
00530 theme->parseFont(e);
00531 }
00532 else if (e.tagName() == "container")
00533 {
00534 parseContainer(e);
00535 }
00536 else
00537 {
00538 cerr << "Unknown element: " << e.tagName() << endl;
00539 continue;
00540 }
00541 }
00542 }
00543 }
00544
00545 void GuideGrid::parseContainer(QDomElement &element)
00546 {
00547 QRect area;
00548 QString name;
00549 int context;
00550 theme->parseContainer(element, name, context, area);
00551
00552 if (name.lower() == "guide")
00553 programRect = area;
00554 if (name.lower() == "program_info")
00555 infoRect = area;
00556 if (name.lower() == "chanbar")
00557 channelRect = area;
00558 if (name.lower() == "timebar")
00559 timeRect = area;
00560 if (name.lower() == "date_info")
00561 dateRect = area;
00562 if (name.lower() == "jumptochannel") {
00563 jumpToChannelRect = area;
00564 jumpToChannelHasRect = true;
00565 }
00566 if (name.lower() == "current_info")
00567 curInfoRect = area;
00568 if (name.lower() == "current_video")
00569 videoRect = area;
00570 }
00571
00572 PixmapChannel *GuideGrid::GetChannelInfo(uint chan_idx, int sel)
00573 {
00574 sel = (sel >= 0) ? sel : m_channelInfoIdx[chan_idx];
00575
00576 if (chan_idx >= GetChannelCount())
00577 return NULL;
00578
00579 if (sel >= (int) m_channelInfos[chan_idx].size())
00580 return NULL;
00581
00582 return &(m_channelInfos[chan_idx][sel]);
00583 }
00584
00585 const PixmapChannel *GuideGrid::GetChannelInfo(uint chan_idx, int sel) const
00586 {
00587 return ((GuideGrid*)this)->GetChannelInfo(chan_idx, sel);
00588 }
00589
00590 uint GuideGrid::GetChannelCount(void) const
00591 {
00592 return m_channelInfos.size();
00593 }
00594
00595 int GuideGrid::GetStartChannelOffset(int row) const
00596 {
00597 uint cnt = GetChannelCount();
00598 if (!cnt)
00599 return -1;
00600
00601 row = (row < 0) ? m_currentRow : row;
00602 return (row + m_currentStartChannel) % cnt;
00603 }
00604
00605 ProgramList GuideGrid::GetProgramList(uint chanid) const
00606 {
00607 ProgramList proglist;
00608 MSqlBindings bindings;
00609 QString querystr =
00610 "WHERE program.chanid = :CHANID AND "
00611 " program.endtime >= :STARTTS AND "
00612 " program.starttime <= :ENDTS AND "
00613 " program.manualid = 0 ";
00614 bindings[":STARTTS"] = m_currentStartTime.toString("yyyy-MM-ddThh:mm:00");
00615 bindings[":ENDTS"] = m_currentEndTime.toString("yyyy-MM-ddThh:mm:00");
00616 bindings[":CHANID"] = chanid;
00617
00618 ProgramList dummy;
00619 proglist.FromProgram(querystr, bindings, dummy);
00620
00621 return proglist;
00622 }
00623
00624 uint GuideGrid::GetAlternateChannelIndex(
00625 uint chan_idx, bool with_same_channum) const
00626 {
00627 uint si = m_channelInfoIdx[chan_idx];
00628 const PixmapChannel *chinfo = GetChannelInfo(chan_idx, si);
00629
00630 for (uint i = 0; (i < m_channelInfos[chan_idx].size()); i++)
00631 {
00632 if (i == si)
00633 continue;
00634
00635 const PixmapChannel *ciinfo = GetChannelInfo(chan_idx, i);
00636 bool same_channum = ciinfo->channum == chinfo->channum;
00637
00638 if (with_same_channum != same_channum)
00639 continue;
00640
00641 if (!ciinfo || !m_player->IsTunable(ciinfo->chanid, true))
00642 continue;
00643
00644 if (with_same_channum ||
00645 (GetProgramList(chinfo->chanid) ==
00646 GetProgramList(ciinfo->chanid)))
00647 {
00648 si = i;
00649 break;
00650 }
00651 }
00652
00653 return si;
00654 }
00655
00656
00657 #define MKKEY(IDX,SEL) ((((uint64_t)IDX) << 32) | SEL)
00658 DBChanList GuideGrid::GetSelection(void) const
00659 {
00660 DBChanList selected;
00661
00662 int idx = GetStartChannelOffset();
00663 if (idx < 0)
00664 return selected;
00665
00666 uint si = m_channelInfoIdx[idx];
00667
00668 vector<uint64_t> sel;
00669 sel.push_back( MKKEY(idx, si) );
00670
00671 const PixmapChannel *ch = GetChannelInfo(sel[0]>>32, sel[0]&0xffff);
00672 if (!ch)
00673 return selected;
00674
00675 selected.push_back(*ch);
00676 if (m_channelInfos[idx].size() <= 1)
00677 return selected;
00678
00679 ProgramList proglist = GetProgramList(selected[0].chanid);
00680
00681 if (proglist.count() == 0)
00682 return selected;
00683
00684 for (uint i = 0; i < m_channelInfos[idx].size(); i++)
00685 {
00686 const PixmapChannel *ci = GetChannelInfo(idx, i);
00687 if (ci && (i != si) &&
00688 (ci->callsign == ch->callsign) && (ci->channum == ch->channum))
00689 {
00690 sel.push_back( MKKEY(idx, i) );
00691 }
00692 }
00693
00694 for (uint i = 0; i < m_channelInfos[idx].size(); i++)
00695 {
00696 const PixmapChannel *ci = GetChannelInfo(idx, i);
00697 if (ci && (i != si) &&
00698 (ci->callsign == ch->callsign) && (ci->channum != ch->channum))
00699 {
00700 sel.push_back( MKKEY(idx, i) );
00701 }
00702 }
00703
00704 for (uint i = 0; i < m_channelInfos[idx].size(); i++)
00705 {
00706 const PixmapChannel *ci = GetChannelInfo(idx, i);
00707 if ((i != si) && (ci->callsign != ch->callsign))
00708 {
00709 sel.push_back( MKKEY(idx, i) );
00710 }
00711 }
00712
00713 for (uint i = 1; i < sel.size(); i++)
00714 {
00715 const PixmapChannel *ci = GetChannelInfo(sel[i]>>32, sel[i]&0xffff);
00716 if (!ci)
00717 continue;
00718
00719 ProgramList ch_proglist = GetProgramList(ch->chanid);
00720 if (proglist == ch_proglist)
00721 selected.push_back(*ci);
00722 }
00723
00724 return selected;
00725 }
00726 #undef MKKEY
00727
00728 void GuideGrid::timeCheckTimeout(void)
00729 {
00730 timeCheck->changeInterval((int)(60 * 1000));
00731 QTime new_time = QTime::currentTime();
00732 QString curTime = new_time.toString(timeformat);
00733
00734 LayerSet *container = NULL;
00735 container = theme->GetSet("current_info");
00736 if (container)
00737 {
00738 UITextType *type = (UITextType *)container->GetType("time");
00739 if (type)
00740 type->SetText(curTime);
00741 }
00742
00743 if (m_player)
00744 {
00745 if (m_player->IsRunning() == true && videoRect.width() > 0 &&
00746 videoRect.height() > 0)
00747 m_player->EmbedOutput(this->winId(), videoRect.x(), videoRect.y(),
00748 videoRect.width(), videoRect.height());
00749 }
00750
00751 fillProgramInfos();
00752 repaint(programRect, false);
00753 repaint(curInfoRect, false);
00754 }
00755
00756 void GuideGrid::repaintVideoTimeout(void)
00757 {
00758 videoRepaintTimer->changeInterval(1000);
00759 update(videoRect);
00760 }
00761
00762 void GuideGrid::fillChannelInfos(bool gotostartchannel)
00763 {
00764 m_channelInfos.clear();
00765 m_channelInfoIdx.clear();
00766
00767 DBChanList channels = ChannelUtil::GetChannels(0, true);
00768 ChannelUtil::SortChannels(channels, channelOrdering, false);
00769
00770 if (showFavorites)
00771 {
00772 DBChanList tmp;
00773 for (uint i = 0; i < channels.size(); i++)
00774 {
00775 if (channels[i].favorite)
00776 tmp.push_back(channels[i]);
00777 }
00778
00779 if (!tmp.empty())
00780 channels = tmp;
00781 }
00782
00783 typedef vector<uint> uint_list_t;
00784 QMap<QString,uint_list_t> channum_to_index_map;
00785 QMap<QString,uint_list_t> callsign_to_index_map;
00786
00787 bool startingset = false;
00788 m_currentStartChannel = 0;
00789 for (uint i = 0; i < channels.size(); i++)
00790 {
00791 uint chan=i;
00792 if (sortReverse)
00793 {
00794 chan=channels.size()-i-1;
00795 }
00796
00797 bool ndup = channum_to_index_map[channels[chan].channum].size();
00798 bool cdup = callsign_to_index_map[channels[chan].callsign].size();
00799
00800 if (ndup && cdup)
00801 continue;
00802
00803 PixmapChannel val(channels[chan]);
00804
00805
00806 bool match = gotostartchannel && !startingset;
00807 match &= (startChanID) ? (val.chanid == startChanID) : true;
00808 match &= (!startChanID) ? (val.channum == startChanNum) : true;
00809 if (match)
00810 {
00811 m_currentStartChannel = GetChannelCount();
00812 startingset = true;
00813 }
00814
00815 channum_to_index_map[val.channum].push_back(GetChannelCount());
00816 callsign_to_index_map[val.callsign].push_back(GetChannelCount());
00817
00818
00819 pix_chan_list_t tmp;
00820 tmp.push_back(val);
00821 m_channelInfos.push_back(tmp);
00822 }
00823
00824
00825 for (uint i = 0; i < channels.size(); i++)
00826 {
00827 const uint_list_t &ndups = channum_to_index_map[channels[i].channum];
00828 for (uint j = 0; j < ndups.size(); j++)
00829 {
00830 if (channels[i].chanid != m_channelInfos[ndups[j]][0].chanid)
00831 m_channelInfos[ndups[j]].push_back(channels[i]);
00832 }
00833
00834 const uint_list_t &cdups = callsign_to_index_map[channels[i].callsign];
00835 for (uint j = 0; j < cdups.size(); j++)
00836 {
00837 if (channels[i].chanid != m_channelInfos[cdups[j]][0].chanid)
00838 m_channelInfos[cdups[j]].push_back(channels[i]);
00839 }
00840 }
00841
00842 if (m_channelInfos.empty())
00843 {
00844 VERBOSE(VB_IMPORTANT, "GuideGrid: "
00845 "\n\t\t\tYou don't have any channels defined in the database."
00846 "\n\t\t\tGuide grid will have nothing to show you.");
00847 }
00848 }
00849
00850 void GuideGrid::fillTimeInfos()
00851 {
00852 for (int x = 0; x < DISPLAY_TIMES; x++)
00853 {
00854 if (m_timeInfos[x])
00855 delete m_timeInfos[x];
00856 m_timeInfos[x] = NULL;
00857 }
00858
00859 QDateTime t = m_currentStartTime;
00860 int cnt = 0;
00861
00862 LayerSet *container = NULL;
00863 UIBarType *type = NULL;
00864 container = theme->GetSet("timebar");
00865 if (container)
00866 type = (UIBarType *)container->GetType("times");
00867
00868 firstTime = m_currentStartTime;
00869 lastTime = firstTime.addSecs(DISPLAY_TIMES * 60 * 4);
00870
00871 for (int x = 0; x < DISPLAY_TIMES; x++)
00872 {
00873 int mins = t.time().minute();
00874 mins = 5 * (mins / 5);
00875 if (mins % 30 == 0)
00876 {
00877 TimeInfo *timeinfo = new TimeInfo;
00878
00879 int hour = t.time().hour();
00880 timeinfo->hour = hour;
00881 timeinfo->min = mins;
00882
00883 timeinfo->usertime = QTime(hour, mins).toString(timeformat);
00884
00885 m_timeInfos[x] = timeinfo;
00886 if (type)
00887 type->SetText(cnt, timeinfo->usertime);
00888 cnt++;
00889 }
00890
00891 t = t.addSecs(5 * 60);
00892 }
00893 m_currentEndTime = t;
00894 }
00895
00896 void GuideGrid::fillProgramInfos(void)
00897 {
00898 LayerSet *container = NULL;
00899 UIGuideType *type = NULL;
00900 container = theme->GetSet("guide");
00901 if (container)
00902 {
00903 type = (UIGuideType *)container->GetType("guidegrid");
00904 if (type)
00905 {
00906 type->SetWindow(this);
00907 type->SetScreenLocation(programRect.topLeft());
00908 type->SetNumRows(DISPLAY_CHANS);
00909 type->ResetData();
00910 }
00911 }
00912
00913 for (int y = 0; y < DISPLAY_CHANS; y++)
00914 {
00915 fillProgramRowInfos(y);
00916 }
00917 }
00918
00919 void GuideGrid::fillProgramRowInfos(unsigned int row)
00920 {
00921 LayerSet *container = NULL;
00922 container = theme->GetSet("guide");
00923 UIGuideType *type = NULL;
00924 if (container)
00925 type = (UIGuideType *)container->GetType("guidegrid");
00926
00927 if (type)
00928 type->ResetRow(row);
00929
00930 ProgramList *proglist;
00931 ProgramInfo *program;
00932 ProgramInfo *proginfo = NULL;
00933
00934 if (m_programs[row])
00935 delete m_programs[row];
00936 m_programs[row] = NULL;
00937
00938 for (int x = 0; x < DISPLAY_TIMES; x++)
00939 {
00940 m_programInfos[row][x] = NULL;
00941 }
00942
00943 if (m_channelInfos.size() == 0)
00944 return;
00945
00946 int chanNum = row + m_currentStartChannel;
00947 if (chanNum >= (int) m_channelInfos.size())
00948 chanNum -= (int) m_channelInfos.size();
00949 if (chanNum >= (int) m_channelInfos.size())
00950 return;
00951
00952 if (chanNum < 0)
00953 chanNum = 0;
00954
00955 m_programs[row] = proglist = new ProgramList();
00956
00957 MSqlBindings bindings;
00958 QString querystr = "WHERE program.chanid = :CHANID "
00959 " AND program.endtime >= :STARTTS "
00960 " AND program.starttime <= :ENDTS "
00961 " AND program.manualid = 0 ";
00962 bindings[":CHANID"] = GetChannelInfo(chanNum)->chanid;
00963 bindings[":STARTTS"] = m_currentStartTime.toString("yyyy-MM-ddThh:mm:00");
00964 bindings[":ENDTS"] = m_currentEndTime.toString("yyyy-MM-ddThh:mm:00");
00965
00966 proglist->FromProgram(querystr, bindings, m_recList);
00967
00968 QDateTime ts = m_currentStartTime;
00969
00970 if (type)
00971 {
00972 QDateTime tnow = QDateTime::currentDateTime();
00973 int progPast = 0;
00974 if (tnow > m_currentEndTime)
00975 progPast = 100;
00976 else if (tnow < m_currentStartTime)
00977 progPast = 0;
00978 else
00979 {
00980 int played = m_currentStartTime.secsTo(tnow);
00981 int length = m_currentStartTime.secsTo(m_currentEndTime);
00982 if (length)
00983 progPast = played * 100 / length;
00984 }
00985
00986 type->SetProgPast(progPast);
00987 }
00988
00989 program = proglist->first();
00990 QPtrList<ProgramInfo> unknownlist;
00991 bool unknown = false;
00992
00993 for (int x = 0; x < DISPLAY_TIMES; x++)
00994 {
00995 if (program && (ts >= (*program).endts))
00996 {
00997 program = proglist->next();
00998 }
00999
01000 if ((!program) || (ts < (*program).startts))
01001 {
01002 if (unknown)
01003 {
01004 proginfo->spread++;
01005 proginfo->endts = proginfo->endts.addSecs(5 * 60);
01006 }
01007 else
01008 {
01009 proginfo = new ProgramInfo;
01010 unknownlist.append(proginfo);
01011 proginfo->title = unknownTitle;
01012 proginfo->category = unknownCategory;
01013 proginfo->startCol = x;
01014 proginfo->spread = 1;
01015 proginfo->startts = ts;
01016 proginfo->endts = proginfo->startts.addSecs(5 * 60);
01017 unknown = true;
01018 }
01019 }
01020 else
01021 {
01022 if (proginfo == &*program)
01023 {
01024 proginfo->spread++;
01025 }
01026 else
01027 {
01028 proginfo = &*program;
01029 proginfo->startCol = x;
01030 proginfo->spread = 1;
01031 unknown = false;
01032 }
01033 }
01034 m_programInfos[row][x] = proginfo;
01035 ts = ts.addSecs(5 * 60);
01036 }
01037
01038 for (proginfo = unknownlist.first(); proginfo;
01039 proginfo = unknownlist.next())
01040 {
01041 proglist->append(proginfo);
01042 }
01043
01044 int ydifference = programRect.height() / DISPLAY_CHANS;
01045 int xdifference = programRect.width() / DISPLAY_TIMES;
01046
01047 int arrow = 0;
01048 int cnt = 0;
01049 int spread = 1;
01050 QDateTime lastprog;
01051 QRect tempRect;
01052 bool isCurrent = false;
01053
01054 for (int x = 0; x < DISPLAY_TIMES; x++)
01055 {
01056 proginfo = m_programInfos[row][x];
01057 if (!proginfo)
01058 continue;
01059
01060 spread = 1;
01061 if (proginfo->startts != lastprog)
01062 {
01063 arrow = 0;
01064 if (proginfo->startts < firstTime.addSecs(-300))
01065 arrow = arrow + 1;
01066 if (proginfo->endts > lastTime.addSecs(2100))
01067 arrow = arrow + 2;
01068
01069 if (proginfo->spread != -1)
01070 {
01071 spread = proginfo->spread;
01072 }
01073 else
01074 {
01075 for (int z = x + 1; z < DISPLAY_TIMES; z++)
01076 {
01077 ProgramInfo *test = m_programInfos[row][z];
01078 if (test && test->startts == proginfo->startts)
01079 spread++;
01080 }
01081 proginfo->spread = spread;
01082 proginfo->startCol = x;
01083
01084 for (int z = x + 1; z < x + spread; z++)
01085 {
01086 ProgramInfo *test = m_programInfos[row][z];
01087 if (test)
01088 {
01089 test->spread = spread;
01090 test->startCol = x;
01091 }
01092 }
01093 }
01094
01095 tempRect = QRect((int)(x * xdifference), (int)(row * ydifference),
01096 (int)(xdifference * proginfo->spread), ydifference);
01097
01098 if (m_currentRow == (int)row && (m_currentCol >= x) &&
01099 (m_currentCol < (x + spread)))
01100 isCurrent = true;
01101 else
01102 isCurrent = false;
01103
01104 if (type)
01105 {
01106 int recFlag;
01107 switch (proginfo->rectype)
01108 {
01109 case kSingleRecord:
01110 recFlag = 1;
01111 break;
01112 case kTimeslotRecord:
01113 recFlag = 2;
01114 break;
01115 case kChannelRecord:
01116 recFlag = 3;
01117 break;
01118 case kAllRecord:
01119 recFlag = 4;
01120 break;
01121 case kWeekslotRecord:
01122 recFlag = 5;
01123 break;
01124 case kFindOneRecord:
01125 case kFindDailyRecord:
01126 case kFindWeeklyRecord:
01127 recFlag = 6;
01128 break;
01129 case kOverrideRecord:
01130 case kDontRecord:
01131 recFlag = 7;
01132 break;
01133 case kNotRecording:
01134 default:
01135 recFlag = 0;
01136 break;
01137 }
01138
01139 int recStat;
01140 if (proginfo->recstatus == rsConflict ||
01141 proginfo->recstatus == rsOffLine)
01142 recStat = 2;
01143 if (proginfo->recstatus <= rsWillRecord)
01144 recStat = 1;
01145 else
01146 recStat = 0;
01147
01148 type->SetProgramInfo(row, cnt, tempRect, proginfo->title,
01149 proginfo->category, arrow, recFlag,
01150 recStat, isCurrent);
01151
01152 cnt++;
01153 }
01154 }
01155
01156 lastprog = proginfo->startts;
01157 }
01158 }
01159
01160 void GuideGrid::customEvent(QCustomEvent *e)
01161 {
01162 if ((MythEvent::Type)(e->type()) == MythEvent::MythEventMessage)
01163 {
01164 MythEvent *me = (MythEvent *)e;
01165 QString message = me->Message();
01166
01167 if (message == "SCHEDULE_CHANGE")
01168 {
01169 m_recList.FromScheduler();
01170 fillProgramInfos();
01171 update(fullRect);
01172 }
01173 }
01174 }
01175
01176 void GuideGrid::paintEvent(QPaintEvent *e)
01177 {
01178 qApp->lock();
01179
01180 QRect r = e->rect();
01181 QPainter p(this);
01182
01183 if (r.intersects(channelRect) && paintChannels(&p))
01184 {
01185 fillProgramInfos();
01186 update(programRect|curInfoRect|r);
01187 qApp->unlock();
01188 return;
01189 }
01190
01191 if (r.intersects(infoRect))
01192 paintInfo(&p);
01193 if (r.intersects(dateRect) && (jumpToChannelHasRect || (!jumpToChannelHasRect && !jumpToChannelActive)))
01194 paintDate(&p);
01195 if (r.intersects(timeRect))
01196 paintTimes(&p);
01197 if (r.intersects(programRect))
01198 paintPrograms(&p);
01199 if (r.intersects(curInfoRect))
01200 paintCurrentInfo(&p);
01201
01202
01203 if ((jumpToChannelHasRect && r.intersects(jumpToChannelRect)) ||
01204 (!jumpToChannelHasRect && r.intersects(dateRect)))
01205 paintJumpToChannel(&p);
01206
01207 if (r.intersects(videoRect) && m_player)
01208 {
01209 timeCheck->changeInterval((int)(200));
01210 m_player->DrawUnusedRects(false);
01211 }
01212
01213 qApp->unlock();
01214 }
01215
01216 void GuideGrid::paintDate(QPainter *p)
01217 {
01218 QRect dr = dateRect;
01219 QPixmap pix(dr.size());
01220 pix.fill(this, dr.topLeft());
01221 QPainter tmp(&pix);
01222
01223 LayerSet *container = NULL;
01224 container = theme->GetSet("date_info");
01225 if (container)
01226 {
01227 UITextType *type = (UITextType *)container->GetType("date");
01228 if (type)
01229 type->SetText(m_currentStartTime.toString(dateformat));
01230 }
01231
01232 if (container)
01233 {
01234 container->Draw(&tmp, 1, m_context);
01235 container->Draw(&tmp, 2, m_context);
01236 container->Draw(&tmp, 3, m_context);
01237 container->Draw(&tmp, 4, m_context);
01238 container->Draw(&tmp, 5, m_context);
01239 container->Draw(&tmp, 6, m_context);
01240 container->Draw(&tmp, 7, m_context);
01241 container->Draw(&tmp, 8, m_context);
01242 }
01243 tmp.end();
01244 p->drawPixmap(dr.topLeft(), pix);
01245 }
01246
01247 void GuideGrid::paintJumpToChannel(QPainter *p)
01248 {
01249 if (!jumpToChannelEnabled || !jumpToChannelActive)
01250 return;
01251
01252 QRect jtcr;
01253 LayerSet *container = NULL;
01254
01255 if (jumpToChannelHasRect) {
01256 jtcr = jumpToChannelRect;
01257 container = theme->GetSet("jumptochannel");
01258 } else {
01259 jtcr = dateRect;
01260 container = theme->GetSet("date_info");
01261 }
01262
01263 QPixmap pix(jtcr.size());
01264 pix.fill(this, jtcr.topLeft());
01265 QPainter tmp(&pix);
01266
01267 if (container)
01268 {
01269 UITextType *type = (UITextType *)container->GetType((jumpToChannelHasRect) ? "channel" : "date");
01270 if (type) {
01271 type->SetText(QString::number(jumpToChannel));
01272 }
01273 }
01274
01275 if (container)
01276 {
01277 container->Draw(&tmp, 1, m_context);
01278 container->Draw(&tmp, 2, m_context);
01279 container->Draw(&tmp, 3, m_context);
01280 container->Draw(&tmp, 4, m_context);
01281 container->Draw(&tmp, 5, m_context);
01282 container->Draw(&tmp, 6, m_context);
01283 container->Draw(&tmp, 7, m_context);
01284 container->Draw(&tmp, 8, m_context);
01285 }
01286 tmp.end();
01287 p->drawPixmap(jtcr.topLeft(), pix);
01288 }
01289
01290 void GuideGrid::paintCurrentInfo(QPainter *p)
01291 {
01292 QRect dr = curInfoRect;
01293 QPixmap pix(dr.size());
01294 pix.fill(this, dr.topLeft());
01295 QPainter tmp(&pix);
01296
01297 LayerSet *container = NULL;
01298 container = theme->GetSet("current_info");
01299 if (container)
01300 {
01301 container->Draw(&tmp, 1, m_context);
01302 container->Draw(&tmp, 2, m_context);
01303 container->Draw(&tmp, 3, m_context);
01304 container->Draw(&tmp, 4, m_context);
01305 container->Draw(&tmp, 5, m_context);
01306 container->Draw(&tmp, 6, m_context);
01307 container->Draw(&tmp, 7, m_context);
01308 container->Draw(&tmp, 8, m_context);
01309 }
01310 tmp.end();
01311 p->drawPixmap(dr.topLeft(), pix);
01312 }
01313
01314 bool GuideGrid::paintChannels(QPainter *p)
01315 {
01316 QRect cr = channelRect;
01317 QPixmap pix(cr.size());
01318 pix.fill(this, cr.topLeft());
01319 QPainter tmp(&pix);
01320 bool channelsChanged = false;
01321
01322 LayerSet *container = NULL;
01323 LayerSet *infocontainer = NULL;
01324 UIBarType *type = NULL;
01325 UIImageType *itype = NULL;
01326 container = theme->GetSet("chanbar");
01327 infocontainer = theme->GetSet("program_info");
01328 if (container)
01329 type = (UIBarType *)container->GetType("chans");
01330 if (infocontainer)
01331 itype = (UIImageType *)infocontainer->GetType("icon");
01332
01333 if (type && type->GetNums() != DISPLAY_CHANS)
01334 type->SetSize(DISPLAY_CHANS);
01335
01336 PixmapChannel *chinfo = GetChannelInfo(m_currentStartChannel);
01337
01338 if (m_player)
01339 m_player->ClearTunableCache();
01340
01341 bool showChannelIcon = gContext->GetNumSetting("EPGShowChannelIcon", 0);
01342
01343 for (unsigned int y = 0; (y < (unsigned int)DISPLAY_CHANS) && chinfo; y++)
01344 {
01345 unsigned int chanNumber = y + m_currentStartChannel;
01346 if (chanNumber >= m_channelInfos.size())
01347 chanNumber -= m_channelInfos.size();
01348 if (chanNumber >= m_channelInfos.size())
01349 break;
01350
01351 chinfo = GetChannelInfo(chanNumber);
01352
01353 bool unavailable = false;
01354 if (m_player && !m_player->IsTunable(chinfo->chanid, true))
01355 {
01356 unavailable = true;
01357
01358
01359 uint alt = GetAlternateChannelIndex(chanNumber, true);
01360 if (alt != m_channelInfoIdx[chanNumber])
01361 {
01362 unavailable = false;
01363 m_channelInfoIdx[chanNumber] = alt;
01364 chinfo = GetChannelInfo(chanNumber);
01365 channelsChanged = true;
01366 }
01367
01368
01369 if (unavailable && GetProgramList(chinfo->chanid).count())
01370 {
01371 alt = GetAlternateChannelIndex(chanNumber, false);
01372 unavailable = (alt == m_channelInfoIdx[chanNumber]);
01373 }
01374 }
01375
01376 if ((y == (unsigned int)2 && scrolltype != 1) ||
01377 ((signed int)y == m_currentRow && scrolltype == 1))
01378 {
01379 if (showChannelIcon && !chinfo->icon.isEmpty())
01380 {
01381 int iconsize = 0;
01382 if (itype)
01383 iconsize = itype->GetSize(true).width();
01384 else if (type)
01385 iconsize = type->GetSize();
01386 if (!chinfo->iconLoaded)
01387 chinfo->LoadChannelIcon(iconsize);
01388 if (chinfo->iconLoaded)
01389 {
01390 if (itype)
01391 itype->SetImage(chinfo->iconPixmap);
01392 }
01393 else
01394 chinfo->icon = QString::null;
01395 }
01396 }
01397
01398 QString tmpChannelFormat = channelFormat;
01399 if (chinfo->favorite > 0)
01400 {
01401 tmpChannelFormat.insert(tmpChannelFormat.find('<'), "<MARK:fav>");
01402 }
01403
01404 if (unavailable)
01405 {
01406 tmpChannelFormat.insert(tmpChannelFormat.find('<'),
01407 "<MARK:unavail>");
01408 }
01409
01410 if (type)
01411 {
01412 if (showChannelIcon && !chinfo->icon.isEmpty())
01413 {
01414 int iconsize = 0;
01415 if (itype)
01416 iconsize = itype->GetSize(true).width();
01417 else if (type)
01418 iconsize = type->GetSize();
01419 if (!chinfo->iconLoaded)
01420 chinfo->LoadChannelIcon(iconsize);
01421 if (chinfo->iconLoaded)
01422 type->SetIcon(y, chinfo->iconPixmap);
01423 else
01424 {
01425 chinfo->icon = QString::null;
01426 type->ResetImage(y);
01427 }
01428 }
01429 else
01430 {
01431 type->ResetImage(y);
01432 }
01433
01434 type->SetText(y, chinfo->GetFormatted(tmpChannelFormat));
01435 }
01436 }
01437
01438 if (container)
01439 {
01440 container->Draw(&tmp, 1, m_context);
01441 container->Draw(&tmp, 2, m_context);
01442 container->Draw(&tmp, 3, m_context);
01443 container->Draw(&tmp, 4, m_context);
01444 container->Draw(&tmp, 5, m_context);
01445 container->Draw(&tmp, 6, m_context);
01446 container->Draw(&tmp, 7, m_context);
01447 container->Draw(&tmp, 8, m_context);
01448 }
01449
01450 tmp.end();
01451 p->drawPixmap(cr.topLeft(), pix);
01452
01453 return channelsChanged;
01454 }
01455
01456 void GuideGrid::paintTimes(QPainter *p)
01457 {
01458 QRect tr = timeRect;
01459 QPixmap pix(tr.size());
01460 pix.fill(this, tr.topLeft());
01461 QPainter tmp(&pix);
01462
01463 LayerSet *container = theme->GetSet("timebar");
01464 if (container)
01465 {
01466 container->Draw(&tmp, 1, m_context);
01467 container->Draw(&tmp, 2, m_context);
01468 container->Draw(&tmp, 3, m_context);
01469 container->Draw(&tmp, 4, m_context);
01470 container->Draw(&tmp, 5, m_context);
01471 container->Draw(&tmp, 6, m_context);
01472 container->Draw(&tmp, 7, m_context);
01473 container->Draw(&tmp, 8, m_context);
01474 }
01475 tmp.end();
01476 p->drawPixmap(tr.topLeft(), pix);
01477 }
01478
01479 void GuideGrid::paintPrograms(QPainter *p)
01480 {
01481 QRect pr = programRect;
01482 QPixmap pix(pr.size());
01483 pix.fill(this, pr.topLeft());
01484 QPainter tmp(&pix);
01485
01486 LayerSet *container = theme->GetSet("guide");
01487 if (container)
01488 {
01489 container->Draw(&tmp, 1, m_context);
01490 container->Draw(&tmp, 2, m_context);
01491 container->Draw(&tmp, 3, m_context);
01492 container->Draw(&tmp, 4, m_context);
01493 container->Draw(&tmp, 5, m_context);
01494 container->Draw(&tmp, 6, m_context);
01495 container->Draw(&tmp, 7, m_context);
01496 container->Draw(&tmp, 8, m_context);
01497 }
01498 tmp.end();
01499 p->drawPixmap(pr.topLeft(), pix);
01500 }
01501
01502 void GuideGrid::paintInfo(QPainter *p)
01503 {
01504 if (m_currentRow < 0 || m_currentCol < 0)
01505 return;
01506
01507 ProgramInfo *pginfo = m_programInfos[m_currentRow][m_currentCol];
01508 if (!pginfo)
01509 return;
01510
01511 QMap<QString, QString> infoMap;
01512 QRect pr = infoRect;
01513 QPixmap pix(pr.size());
01514 pix.fill(this, pr.topLeft());
01515 QPainter tmp(&pix);
01516
01517 int chanNum = m_currentRow + m_currentStartChannel;
01518 if (chanNum >= (int)m_channelInfos.size())
01519 chanNum -= (int)m_channelInfos.size();
01520 if (chanNum >= (int)m_channelInfos.size())
01521 return;
01522 if (chanNum < 0)
01523 chanNum = 0;
01524
01525 PixmapChannel *chinfo = GetChannelInfo(chanNum);
01526
01527 bool showChannelIcon = gContext->GetNumSetting("EPGShowChannelIcon", 0);
01528
01529 pginfo->ToMap(infoMap);
01530
01531 LayerSet *container = theme->GetSet("program_info");
01532 if (container)
01533 {
01534 container->ClearAllText();
01535 container->SetText(infoMap);
01536
01537 UIImageType *itype = (UIImageType *)container->GetType("icon");
01538 if (itype && showChannelIcon)
01539 {
01540 int iconsize = 0;
01541 iconsize = itype->GetSize().width();
01542 if (!chinfo->iconLoaded)
01543 chinfo->LoadChannelIcon(iconsize);
01544 if (chinfo->iconLoaded)
01545 itype->SetImage(chinfo->icon);
01546 else
01547 itype->SetImage(QPixmap());
01548 }
01549
01550 if (!showChannelIcon || !itype || chinfo->icon.isEmpty())
01551 {
01552 UITextType *type = (UITextType *)container->GetType("misicon");
01553 if (type)
01554 type->SetText(chinfo->callsign);
01555 }
01556
01557 container->Draw(&tmp, 1, m_context);
01558 container->Draw(&tmp, 2, m_context);
01559 container->Draw(&tmp, 3, m_context);
01560 container->Draw(&tmp, 4, m_context);
01561 container->Draw(&tmp, 5, m_context);
01562 container->Draw(&tmp, 6, m_context);
01563 container->Draw(&tmp, 7, m_context);
01564 container->Draw(&tmp, 8, m_context);
01565 }
01566
01567 tmp.end();
01568 p->drawPixmap(pr.topLeft(), pix);
01569 }
01570
01571 void GuideGrid::toggleGuideListing()
01572 {
01573 showFavorites = (!showFavorites);
01574 generateListings();
01575 }
01576
01577 void GuideGrid::generateListings()
01578 {
01579 m_currentStartChannel = 0;
01580 m_currentRow = 0;
01581
01582 int maxchannel = 0;
01583 DISPLAY_CHANS = desiredDisplayChans;
01584 fillChannelInfos();
01585 maxchannel = max((int)GetChannelCount() - 1, 0);
01586 DISPLAY_CHANS = min(DISPLAY_CHANS, maxchannel + 1);
01587
01588 m_recList.FromScheduler();
01589 fillProgramInfos();
01590 update(fullRect);
01591 }
01592
01593 void GuideGrid::toggleChannelFavorite()
01594 {
01595 MSqlQuery query(MSqlQuery::InitCon());
01596
01597
01598 int chanNum = m_currentRow + m_currentStartChannel;
01599 if (chanNum >= (int)m_channelInfos.size())
01600 chanNum -= (int)m_channelInfos.size();
01601 if (chanNum >= (int)m_channelInfos.size())
01602 return;
01603 if (chanNum < 0)
01604 chanNum = 0;
01605
01606 PixmapChannel *ch = GetChannelInfo(chanNum);
01607 uint favid = ch->favorite;
01608 uint chanid = ch->chanid;
01609
01610 if (favid > 0)
01611 {
01612 query.prepare("DELETE FROM favorites WHERE favid = :FAVID ;");
01613 query.bindValue(":FAVID", favid);
01614 query.exec();
01615 }
01616 else
01617 {
01618
01619 query.prepare("INSERT INTO favorites (chanid) VALUES (:FAVID);");
01620 query.bindValue(":FAVID", chanid);
01621 query.exec();
01622 }
01623
01624 if (showFavorites)
01625 generateListings();
01626 else
01627 {
01628 int maxchannel = 0;
01629 DISPLAY_CHANS = desiredDisplayChans;
01630 fillChannelInfos(false);
01631 maxchannel = max((int)GetChannelCount() - 1, 0);
01632 DISPLAY_CHANS = min(DISPLAY_CHANS, maxchannel + 1);
01633
01634 repaint(channelRect, false);
01635 }
01636 }
01637
01638 void GuideGrid::cursorLeft()
01639 {
01640 ProgramInfo *test = m_programInfos[m_currentRow][m_currentCol];
01641
01642 if (!test)
01643 {
01644 scrollLeft();
01645 return;
01646 }
01647
01648 int startCol = test->startCol;
01649 m_currentCol = startCol - 1;
01650
01651 if (m_currentCol < 0)
01652 {
01653 m_currentCol = 0;
01654 scrollLeft();
01655 }
01656 else
01657 {
01658 fillProgramRowInfos(m_currentRow);
01659 repaint(programRect, false);
01660 repaint(infoRect, false);
01661 repaint(timeRect, false);
01662 }
01663 }
01664
01665 void GuideGrid::cursorRight()
01666 {
01667 ProgramInfo *test = m_programInfos[m_currentRow][m_currentCol];
01668
01669 if (!test)
01670 {
01671 scrollRight();
01672 return;
01673 }
01674
01675 int spread = test->spread;
01676 int startCol = test->startCol;
01677
01678 m_currentCol = startCol + spread;
01679
01680 if (m_currentCol > DISPLAY_TIMES - 1)
01681 {
01682 m_currentCol = DISPLAY_TIMES - 1;
01683 scrollRight();
01684 }
01685 else
01686 {
01687 fillProgramRowInfos(m_currentRow);
01688 repaint(programRect, false);
01689 repaint(infoRect, false);
01690 repaint(timeRect, false);
01691 }
01692 }
01693
01694 void GuideGrid::cursorDown()
01695 {
01696 if (scrolltype == 1)
01697 {
01698 m_currentRow++;
01699
01700 if (m_currentRow > DISPLAY_CHANS - 1)
01701 {
01702 m_currentRow = DISPLAY_CHANS - 1;
01703 scrollDown();
01704 }
01705 else
01706 {
01707 fillProgramRowInfos(m_currentRow);
01708 repaint(channelRect, false);
01709 repaint(programRect, false);
01710 repaint(infoRect, false);
01711 }
01712 }
01713 else
01714 scrollDown();
01715 }
01716
01717 void GuideGrid::cursorUp()
01718 {
01719 if (scrolltype == 1)
01720 {
01721 m_currentRow--;
01722
01723 if (m_currentRow < 0)
01724 {
01725 m_currentRow = 0;
01726 scrollUp();
01727 }
01728 else
01729 {
01730 fillProgramRowInfos(m_currentRow);
01731 repaint(channelRect, false);
01732 repaint(programRect, false);
01733 repaint(infoRect, false);
01734 }
01735 }
01736 else
01737 scrollUp();
01738 }
01739
01740 void GuideGrid::scrollLeft()
01741 {
01742 bool updatedate = false;
01743
01744 QDateTime t = m_currentStartTime;
01745
01746 t = m_currentStartTime.addSecs(-30 * 60);
01747
01748 if (t.date().day() != m_currentStartTime.date().day())
01749 updatedate = true;
01750
01751 m_currentStartTime = t;
01752
01753 fillTimeInfos();
01754 fillProgramInfos();
01755
01756 repaint(programRect, false);
01757 repaint(infoRect, false);
01758 repaint(dateRect, false);
01759 repaint(jumpToChannelRect, false);
01760 repaint(timeRect, false);
01761 }
01762
01763 void GuideGrid::scrollRight()
01764 {
01765 bool updatedate = false;
01766
01767 QDateTime t = m_currentStartTime;
01768 t = m_currentStartTime.addSecs(30 * 60);
01769
01770 if (t.date().day() != m_currentStartTime.date().day())
01771 updatedate = true;
01772
01773 m_currentStartTime = t;
01774
01775 fillTimeInfos();
01776 fillProgramInfos();
01777
01778 repaint(programRect, false);
01779 repaint(infoRect, false);
01780 repaint(dateRect, false);
01781 repaint(jumpToChannelRect, false);
01782 repaint(timeRect, false);
01783 }
01784
01785 void GuideGrid::setStartChannel(int newStartChannel)
01786 {
01787 if (newStartChannel < 0)
01788 m_currentStartChannel = newStartChannel + GetChannelCount();
01789 else if (newStartChannel >= (int) GetChannelCount())
01790 m_currentStartChannel = newStartChannel - GetChannelCount();
01791 else
01792 m_currentStartChannel = newStartChannel;
01793 }
01794
01795 void GuideGrid::scrollDown()
01796 {
01797 setStartChannel(m_currentStartChannel + 1);
01798
01799 fillProgramInfos();
01800
01801 repaint(channelRect, false);
01802 repaint(programRect, false);
01803 repaint(infoRect, false);
01804 }
01805
01806 void GuideGrid::scrollUp()
01807 {
01808 setStartChannel((int)(m_currentStartChannel) - 1);
01809
01810 fillProgramInfos();
01811
01812 repaint(channelRect, false);
01813 repaint(programRect, false);
01814 repaint(infoRect, false);
01815 }
01816
01817 void GuideGrid::dayLeft()
01818 {
01819 m_currentStartTime = m_currentStartTime.addSecs(-24 * 60 * 60);
01820
01821 fillTimeInfos();
01822 fillProgramInfos();
01823
01824 repaint(fullRect, false);
01825 }
01826
01827 void GuideGrid::dayRight()
01828 {
01829 m_currentStartTime = m_currentStartTime.addSecs(24 * 60 * 60);
01830
01831 fillTimeInfos();
01832 fillProgramInfos();
01833
01834 repaint(fullRect, false);
01835 }
01836
01837 void GuideGrid::pageLeft()
01838 {
01839 bool updatedate = false;
01840
01841 QDateTime t = m_currentStartTime;
01842
01843 t = m_currentStartTime.addSecs(-5 * 60 * DISPLAY_TIMES);
01844
01845 if (t.date().day() != m_currentStartTime.date().day())
01846 updatedate = true;
01847
01848 m_currentStartTime = t;
01849
01850 fillTimeInfos();
01851 fillProgramInfos();
01852
01853 repaint(fullRect, false);
01854 }
01855
01856 void GuideGrid::pageRight()
01857 {
01858 bool updatedate = false;
01859
01860 QDateTime t = m_currentStartTime;
01861
01862 t = m_currentStartTime.addSecs(5 * 60 * DISPLAY_TIMES);
01863
01864 if (t.date().day() != m_currentStartTime.date().day())
01865 updatedate = true;
01866
01867 m_currentStartTime = t;
01868
01869 fillTimeInfos();
01870 fillProgramInfos();
01871
01872 repaint(fullRect, false);
01873 }
01874
01875 void GuideGrid::pageDown()
01876 {
01877 setStartChannel(m_currentStartChannel + DISPLAY_CHANS);
01878
01879 fillProgramInfos();
01880
01881 repaint(fullRect, false);
01882 }
01883
01884 void GuideGrid::pageUp()
01885 {
01886 setStartChannel((int)(m_currentStartChannel) - DISPLAY_CHANS);
01887
01888 fillProgramInfos();
01889
01890 repaint(fullRect, false);
01891 }
01892
01893 void GuideGrid::showProgFinder()
01894 {
01895 RunProgramFind(false, true);
01896
01897 setActiveWindow();
01898 setFocus();
01899
01900 if (m_player && videoRect.height() > 0 && videoRect.width() > 0)
01901 m_player->EmbedOutput(this->winId(), videoRect.x(), videoRect.y(),
01902 videoRect.width(), videoRect.height());
01903 }
01904
01905 void GuideGrid::enter()
01906 {
01907 if (timeCheck)
01908 {
01909 timeCheck->stop();
01910 if (m_player)
01911 m_player->StopEmbeddingOutput();
01912 }
01913
01914 unsetCursor();
01915 selectState = 1;
01916 accept();
01917 }
01918
01919 void GuideGrid::escape()
01920 {
01921 if (timeCheck)
01922 {
01923 timeCheck->stop();
01924 if (m_player)
01925 m_player->StopEmbeddingOutput();
01926 }
01927
01928 unsetCursor();
01929 accept();
01930 }
01931
01932 void GuideGrid::quickRecord()
01933 {
01934 ProgramInfo *pginfo = m_programInfos[m_currentRow][m_currentCol];
01935
01936 if (!pginfo)
01937 return;
01938
01939 if (pginfo->title == unknownTitle)
01940 return;
01941
01942 pginfo->ToggleRecord();
01943
01944 m_recList.FromScheduler();
01945 fillProgramInfos();
01946 repaint(programRect, false);
01947 repaint(infoRect, false);
01948 }
01949
01950 void GuideGrid::editRecording()
01951 {
01952 ProgramInfo *pginfo = m_programInfos[m_currentRow][m_currentCol];
01953
01954 if (!pginfo)
01955 return;
01956
01957 if (pginfo->title == unknownTitle)
01958 return;
01959
01960 FocusPolicy storeFocus = focusPolicy();
01961 setFocusPolicy(QWidget::NoFocus);
01962
01963 ProgramInfo *temppginfo = new ProgramInfo(*pginfo);
01964 temppginfo->EditRecording();
01965 delete temppginfo;
01966
01967 setFocusPolicy(storeFocus);
01968
01969 setActiveWindow();
01970 setFocus();
01971
01972 m_recList.FromScheduler();
01973 fillProgramInfos();
01974 repaint(fullRect, false);
01975 }
01976
01977 void GuideGrid::editScheduled()
01978 {
01979 ProgramInfo *pginfo = m_programInfos[m_currentRow][m_currentCol];
01980
01981 if (!pginfo)
01982 return;
01983
01984 if (pginfo->title == unknownTitle)
01985 return;
01986
01987 FocusPolicy storeFocus = focusPolicy();
01988 setFocusPolicy(QWidget::NoFocus);
01989
01990 ProgramInfo *temppginfo = new ProgramInfo(*pginfo);
01991 temppginfo->EditScheduled();
01992 delete temppginfo;
01993
01994 setFocusPolicy(storeFocus);
01995
01996 setActiveWindow();
01997 setFocus();
01998
01999 m_recList.FromScheduler();
02000 fillProgramInfos();
02001
02002 repaint(fullRect, false);
02003 }
02004
02005 void GuideGrid::customEdit()
02006 {
02007 ProgramInfo *pginfo = m_programInfos[m_currentRow][m_currentCol];
02008
02009 if (!pginfo)
02010 return;
02011
02012 CustomEdit *ce = new CustomEdit(gContext->GetMainWindow(),
02013 "customedit", pginfo);
02014 ce->exec();
02015 delete ce;
02016 }
02017
02018 void GuideGrid::remove()
02019 {
02020 ProgramInfo *pginfo = m_programInfos[m_currentRow][m_currentCol];
02021
02022 if (!pginfo || pginfo->recordid <= 0)
02023 return;
02024
02025 ScheduledRecording *record = new ScheduledRecording();
02026 int recid = pginfo->recordid;
02027 record->loadByID(recid);
02028
02029 QString message =
02030 tr("Delete '%1' %2 rule?").arg(record->getRecordTitle())
02031 .arg(pginfo->RecTypeText());
02032
02033 bool ok = MythPopupBox::showOkCancelPopup(gContext->GetMainWindow(), "",
02034 message, false);
02035
02036 if (ok)
02037 {
02038 record->remove();
02039 ScheduledRecording::signalChange(recid);
02040 }
02041 record->deleteLater();
02042 }
02043
02044 void GuideGrid::upcoming()
02045 {
02046 ProgramInfo *pginfo = m_programInfos[m_currentRow][m_currentCol];
02047
02048 if (!pginfo)
02049 return;
02050
02051 if (pginfo->title == unknownTitle)
02052 return;
02053
02054 ProgLister *pl = new ProgLister(plTitle, pginfo->title, "",
02055 gContext->GetMainWindow(), "proglist");
02056 pl->exec();
02057 delete pl;
02058 }
02059
02060 void GuideGrid::details()
02061 {
02062 ProgramInfo *pginfo = m_programInfos[m_currentRow][m_currentCol];
02063
02064 if (!pginfo)
02065 return;
02066
02067 if (pginfo->title == unknownTitle)
02068 return;
02069
02070 pginfo->showDetails();
02071 }
02072
02073 void GuideGrid::channelUpdate(void)
02074 {
02075 if (!m_player)
02076 return;
02077
02078 DBChanList sel = GetSelection();
02079
02080 if (sel.size())
02081 {
02082 m_player->ChangeChannel(sel);
02083 videoRepaintTimer->start(200);
02084 }
02085 }
02086
02087 void GuideGrid::volumeUpdate(bool up)
02088 {
02089 if (m_player)
02090 m_player->ChangeVolume(up);
02091 }
02092
02093 void GuideGrid::toggleMute(void)
02094 {
02095 if (m_player)
02096 m_player->ToggleMute();
02097 }
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123 void GuideGrid::jumpToChannelDigitPress(int digit)
02124 {
02125
02126 if (jumpToChannelActive == false) {
02127 jumpToChannelActive = true;
02128 jumpToChannel = 0;
02129 jumpToChannelPreviousStartChannel = m_currentStartChannel;
02130 jumpToChannelPreviousRow = m_currentRow;
02131 }
02132
02133
02134 jumpToChannelTimer->stop();
02135 jumpToChannelTimer->start(3500, true);
02136
02137 jumpToChannel = (jumpToChannel * 10) + digit;
02138
02139
02140 jumpToChannelShowSelection();
02141 }
02142
02143 void GuideGrid::jumpToChannelDeleteLastDigit()
02144 {
02145 jumpToChannel /= 10;
02146
02147 if (jumpToChannel == 0)
02148 jumpToChannelCancel();
02149 else
02150 jumpToChannelShowSelection();
02151 }
02152
02153 void GuideGrid::jumpToChannelShowSelection()
02154 {
02155 unsigned int i;
02156
02157
02158
02159
02160 for (i=0; (i < GetChannelCount()-1) &&
02161 (GetChannelInfo(i)->channum.toInt() < jumpToChannel); i++);
02162
02163 if ((i > 0) &&
02164 ((GetChannelInfo(i)->channum.toInt() - jumpToChannel) >
02165 (jumpToChannel - GetChannelInfo(i-1)->channum.toInt())))
02166 {
02167 i--;
02168 }
02169
02170
02171 setStartChannel(i-DISPLAY_CHANS/2);
02172 m_currentRow = DISPLAY_CHANS/2;
02173
02174 fillProgramInfos();
02175
02176 repaint(fullRect, false);
02177 }
02178
02179 void GuideGrid::jumpToChannelCommit()
02180 {
02181 jumpToChannelResetAndHide();
02182 }
02183
02184 void GuideGrid::jumpToChannelCancel()
02185 {
02186 setStartChannel(jumpToChannelPreviousStartChannel);
02187 m_currentRow = jumpToChannelPreviousRow;
02188
02189 fillProgramInfos();
02190
02191 repaint(fullRect, false);
02192
02193 jumpToChannelResetAndHide();
02194 }
02195
02196 void GuideGrid::jumpToChannelResetAndHide()
02197 {
02198 jumpToChannelActive = false;
02199
02200 jumpToChannelTimer->stop();
02201
02202 repaint(fullRect, false);
02203 }
02204
02205 void GuideGrid::jumpToChannelTimeout()
02206 {
02207 jumpToChannelCommit();
02208 }
02209
02210
02211
02212 bool GuideGrid::jumpToChannelGetInputDigit(QStringList &actions, int &digit)
02213 {
02214 for (unsigned int i = 0; i < actions.size(); ++i)
02215 {
02216 QString action = actions[i];
02217 if (action[0] >= '0' && action[0] <= '9')
02218 {
02219 digit = action.toInt();
02220 return true;
02221 }
02222 }
02223
02224
02225 return false;
02226 }