diff --git a/HISTORY b/HISTORY index 12d6c28..862bed6 100644 --- a/HISTORY +++ b/HISTORY @@ -97,3 +97,4 @@ Version 1.1.0 - Fixed some issues with text backgrounds in flat themes (closes Tickets 1480 and 1486) - Added possibility to search for reruns in case of a timer conflict +- Added timer Timeline view in red button recording menu diff --git a/config.h b/config.h index 31cf988..4e1087c 100644 --- a/config.h +++ b/config.h @@ -206,5 +206,9 @@ THEME_CLR(theme, clrRecMenuKeyboardHigh, 0x40BB0000); THEME_CLR(theme, clrButtonRedKeyboard, 0xFFBB0000); THEME_CLR(theme, clrButtonGreenKeyboard, 0xFF00BB00); THEME_CLR(theme, clrButtonYellowKeyboard, 0xFFBBBB00); - +THEME_CLR(theme, clrRecMenuTimelineTimer, 0xB012273f); +THEME_CLR(theme, clrRecMenuTimelineBack, 0xFF828282); +THEME_CLR(theme, clrRecMenuTimelineActive, 0xFF3F3F3F); +THEME_CLR(theme, clrRecMenuTimelineConflict, 0x30FF0000); +THEME_CLR(theme, clrRecMenuTimelineConflictOverlap, 0x90FF0000); #endif //__TVGUIDE_CONFIG_H \ No newline at end of file diff --git a/po/ca_ES.po b/po/ca_ES.po index 2de7d06..7985a3f 100644 --- a/po/ca_ES.po +++ b/po/ca_ES.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: vdr-tvguide 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-29 17:53+0100\n" +"POT-Creation-Date: 2013-12-31 14:31+0100\n" "PO-Revision-Date: 2013-09-21 17:49+0200\n" "Last-Translator: My friend Thanks David \n" "Language-Team: \n" @@ -72,6 +72,15 @@ msgstr "enregistrat a" msgid "from" msgstr "des de" +msgid "Timers for" +msgstr "" + +msgid "Rec" +msgstr "" + +msgid "No Timers active" +msgstr "" + msgid "Instant Record" msgstr "Enregistra a l'instant" @@ -96,12 +105,15 @@ msgstr "Esborra canvis de temporitzadors" msgid "Search" msgstr "Cerca" -msgid "Search in Recordings" -msgstr "Cerca a les gravacions" +msgid "Timer Timeline" +msgstr "" msgid "Check for Timer Conflicts" msgstr "Comprova conflictes de temporitzadors" +msgid "Search in Recordings" +msgstr "Cerca a les gravacions" + msgid "Set Folder for" msgstr "Programa carpeta per" diff --git a/po/de_DE.po b/po/de_DE.po index b8b9128..cc1085b 100755 --- a/po/de_DE.po +++ b/po/de_DE.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: vdr-tvguide 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-29 17:53+0100\n" +"POT-Creation-Date: 2013-12-31 14:31+0100\n" "PO-Revision-Date: 2012-08-25 17:49+0200\n" "Last-Translator: Horst\n" "Language-Team: \n" @@ -69,6 +69,15 @@ msgstr "aufgenommen am" msgid "from" msgstr "von" +msgid "Timers for" +msgstr "Timer für" + +msgid "Rec" +msgstr "Aufn" + +msgid "No Timers active" +msgstr "Keine Timer aktiv" + msgid "Instant Record" msgstr "Sofortaufnahme" @@ -93,12 +102,15 @@ msgstr "Umschalttimer löschen" msgid "Search" msgstr "Suchen" -msgid "Search in Recordings" -msgstr "In Aufnahmen suchen" +msgid "Timer Timeline" +msgstr "Timer Zeitleiste" msgid "Check for Timer Conflicts" msgstr "Auf Timerkoflikte prüfen" +msgid "Search in Recordings" +msgstr "In Aufnahmen suchen" + msgid "Set Folder for" msgstr "Verzeichnis festlegen für" @@ -157,25 +169,25 @@ msgid "Close" msgstr "Schließen" msgid "reruns for" -msgstr "" +msgstr "Wiederholungen für" msgid "rerun for" -msgstr "" +msgstr "Wiederholung für" msgid "found" -msgstr "" +msgstr "gefunden" msgid "Ignore reruns" -msgstr "" +msgstr "Wiederholungen ignorieren" msgid "No reruns found for Event" -msgstr "" +msgstr "Keine Wiederholungen gefunden für" msgid "Timer for" -msgstr "" +msgstr "Timer für" msgid "replaced by rerun" -msgstr "" +msgstr "ersetzt durch Wiederholung" msgid "Timer Active" msgstr "Timer aktiv" @@ -664,4 +676,4 @@ msgid "Channel Groups Cache" msgstr "Kanalgruppen Cache" msgid "Recording Menus Icon Cache" -msgstr "" +msgstr "Recording Menüs Icon Cache" diff --git a/po/ru_RU.po b/po/ru_RU.po index b8cdeb5..e9bec09 100644 --- a/po/ru_RU.po +++ b/po/ru_RU.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: vdr-tvguide 1.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-29 17:53+0100\n" +"POT-Creation-Date: 2013-12-31 14:31+0100\n" "PO-Revision-Date: 2013-09-25 17:49+0400\n" "Last-Translator: AmiD, ilya\n" "Language-Team: Russia-Cherepovets(wm.amid@gmail.com)\n" @@ -69,6 +69,15 @@ msgstr "записано" msgid "from" msgstr "от" +msgid "Timers for" +msgstr "" + +msgid "Rec" +msgstr "" + +msgid "No Timers active" +msgstr "" + msgid "Instant Record" msgstr "Записать" @@ -93,12 +102,15 @@ msgstr "Удалить таймер переключения" msgid "Search" msgstr "Поиск" -msgid "Search in Recordings" -msgstr "Искать в записях" +msgid "Timer Timeline" +msgstr "" msgid "Check for Timer Conflicts" msgstr "Поиск таймер-конфликтов" +msgid "Search in Recordings" +msgstr "Искать в записях" + msgid "Set Folder for" msgstr "Укажите каталог для" diff --git a/po/sk_SK.po b/po/sk_SK.po index 8699ef7..0a54044 100644 --- a/po/sk_SK.po +++ b/po/sk_SK.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: vdr-tvguide 1.1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-29 17:53+0100\n" +"POT-Creation-Date: 2013-12-31 14:31+0100\n" "PO-Revision-Date: 2013-09-15 00:12+0100\n" "Last-Translator: Milan Hrala \n" "Language-Team: \n" @@ -69,6 +69,15 @@ msgstr "Zaznamenan msgid "from" msgstr "z" +msgid "Timers for" +msgstr "" + +msgid "Rec" +msgstr "" + +msgid "No Timers active" +msgstr "" + msgid "Instant Record" msgstr "Okamite nahra" @@ -93,12 +102,15 @@ msgstr "Vymaza msgid "Search" msgstr "Hada" -msgid "Search in Recordings" -msgstr "Vyhada v nahrvkach" +msgid "Timer Timeline" +msgstr "" msgid "Check for Timer Conflicts" msgstr "Skontrolova konflikty plnu" +msgid "Search in Recordings" +msgstr "Vyhada v nahrvkach" + msgid "Set Folder for" msgstr "Nastavi adresr pre" diff --git a/recmanager.c b/recmanager.c index 8816c40..d366593 100644 --- a/recmanager.c +++ b/recmanager.c @@ -705,4 +705,4 @@ const cEvent **cRecManager::LoadReruns(const cEvent *event, int &numResults) { } } return NULL; -} \ No newline at end of file +} diff --git a/recmenu.c b/recmenu.c index c279bc7..728db1e 100644 --- a/recmenu.c +++ b/recmenu.c @@ -528,4 +528,4 @@ cImage *cRecMenu::createScrollbar(int width, int height, tColor clrBgr, tColor c } } return image; -} +} \ No newline at end of file diff --git a/recmenu.h b/recmenu.h index 3445a63..9788aac 100644 --- a/recmenu.h +++ b/recmenu.h @@ -58,6 +58,6 @@ public: bool GetBoolValue(int itemNumber); cString GetStringValue(int itemNumber); const cEvent *GetEventValue(int itemNumber); - eRecMenuState ProcessKey(eKeys Key); + virtual eRecMenuState ProcessKey(eKeys Key); }; #endif //__TVGUIDE_RECMENU_H \ No newline at end of file diff --git a/recmenuitem.c b/recmenuitem.c index 056ac80..db10a7c 100644 --- a/recmenuitem.c +++ b/recmenuitem.c @@ -10,6 +10,7 @@ cRecMenuItem::cRecMenuItem(void) { height = 0; action = rmsNotConsumed; + defaultBackground = true; drawn = false; font = fontManager.FontRecMenuItem; fontSmall = fontManager.FontRecMenuItemSmall; @@ -34,7 +35,9 @@ void cRecMenuItem::SetPixmaps(void) { void cRecMenuItem::setBackground(void) { if (tvguideConfig.style == eStyleGraphical) { - drawBackgroundGraphical(bgButton, active); + if (defaultBackground) { + drawBackgroundGraphical(bgButton, active); + } colorTextBack = clrTransparent; colorText = (active)?theme.Color(clrFontActive):theme.Color(clrFont); } else { @@ -48,8 +51,10 @@ void cRecMenuItem::setBackground(void) { colorText = theme.Color(clrFont); } colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent; - drawBackground(); - drawBorder(); + if (defaultBackground) { + drawBackground(); + drawBorder(); + } } } @@ -2057,3 +2062,355 @@ void cRecMenuItemRecording::Show(void) { pixmap->SetLayer(4); pixmapText->SetLayer(5); } + +// --- cRecMenuItemTimelineHeader ------------------------------------------------------- +cRecMenuItemTimelineHeader::cRecMenuItemTimelineHeader(time_t day, std::vector conflictsToday) { + conflicts = conflictsToday; + pixmapTimeline = NULL; + pixmapTimerInfo = NULL; + pixmapTimerConflicts = NULL; + timer = NULL; + this->day = day; + selectable = false; + active = false; + height = 5 * font->Height(); + timelineDrawn = false; +} + +cRecMenuItemTimelineHeader::~cRecMenuItemTimelineHeader(void) { + if (pixmapTimeline) + osdManager.releasePixmap(pixmapTimeline); + if (pixmapTimerInfo) + osdManager.releasePixmap(pixmapTimerInfo); + if (pixmapTimerConflicts) + osdManager.releasePixmap(pixmapTimerConflicts); +} + +void cRecMenuItemTimelineHeader::SetPixmaps(void) { + if (!pixmap) { + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + pixmapTimeline = osdManager.requestPixmap(5, cRect(x, y, width, height)); + pixmapTimerInfo = osdManager.requestPixmap(6, cRect(x, y + 3 * font->Height() / 2, width, 2 * font->Height())); + if (conflicts.size() > 0) { + pixmapTimerConflicts = osdManager.requestPixmap(6, cRect(x, y, width, height)); + } + } else { + pixmap->SetViewPort(cRect(x, y, width, height)); + pixmapTimeline->SetViewPort(cRect(x, y, width, height)); + pixmapTimerInfo->SetViewPort(cRect(x, y + 3 * font->Height() / 2, width, 2 * font->Height())); + if (pixmapTimerConflicts) + pixmapTimerConflicts->SetViewPort(cRect(x, y, width, height)); + } +} + +void cRecMenuItemTimelineHeader::RefreshTimerDisplay(void) { + if (!pixmapTimerInfo) + return; + if (timer) + DrawCurrentTimer(); + else + pixmapTimerInfo->Fill(clrTransparent); +} + +void cRecMenuItemTimelineHeader::Draw(void) { + if (!timelineDrawn) { + DrawTimeline(); + timelineDrawn = true; + } + DrawTimerConflicts(); + pixmap->Fill(clrTransparent); + cString headerText = tr("Timers for"); + cString dateText = DateString(day); + cString header = cString::sprintf("%s: %s", *headerText, *dateText); + int xText = (width - font->Width(*header)) / 2; + int yText = (height/4 - font->Height())/2; + pixmap->DrawText(cPoint(xText, yText), *header, colorText, clrTransparent, font); + + if (timer) { + DrawCurrentTimer(); + } +} + +void cRecMenuItemTimelineHeader::DrawCurrentTimer(void) { + int infoHeight = pixmapTimerInfo->ViewPort().Height(); + pixmapTimerInfo->Fill(clrTransparent); + const cEvent *event = timer->Event(); + const cChannel *channel = timer->Channel(); + int x = 0; + if (channel) { + int logoWidth = infoHeight * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio; + bool logoDrawn = false; + cImageLoader imgLoader; + if (!tvguideConfig.hideChannelLogos) { + if (imgLoader.LoadLogo(channel, logoWidth, infoHeight)) { + cImage logo = imgLoader.GetImage(); + pixmapTimerInfo->DrawImage(cPoint(0, 0), logo); + x += logoWidth + 10; + logoDrawn = true; + } + } + if (tvguideConfig.hideChannelLogos || !logoDrawn) { + int channelNameWidth = fontSmall->Width(channel->Name()); + pixmapTimerInfo->DrawText(cPoint(10, (infoHeight - fontSmall->Height())/2), channel->Name(), colorText, clrTransparent, fontSmall); + x += channelNameWidth + 20; + } + } + + cString timerStartTime = TimeString(timer->StartTime()); + cString timerStopTime = TimeString(timer->StopTime()); + cString channelInfo = cString::sprintf("%s %d", tr("Transp."), timer->Channel()->Transponder()); + + if (event) { + cString title; + if (event->ShortText()) { + title = cString::sprintf("%s - %s", event->Title(), event->ShortText()); + } else { + title = event->Title(); + } + std::string titleCut = CutText(*title, width - x, font); + cString infoString = cString::sprintf("%s: %s - %s (%s. %s - %s), %s", *event->GetDateString(), *event->GetTimeString(), *event->GetEndTimeString(), tr("Rec"), *timerStartTime, *timerStopTime, *channelInfo); + pixmapTimerInfo->DrawText(cPoint(x, 0), *infoString, colorText, clrTransparent, font); + pixmapTimerInfo->DrawText(cPoint(x, font->Height()), titleCut.c_str(), colorText, clrTransparent, font); + } else { + cString infoString = cString::sprintf("%s. %s - %s, %s", tr("Rec"), *timerStartTime, *timerStopTime, *channelInfo); + pixmapTimerInfo->DrawText(cPoint(x, 0), *infoString, colorText, clrTransparent, font); + } +} + +void cRecMenuItemTimelineHeader::DrawTimeline(void) { + pixmapTimeline->Fill(clrTransparent); + width5Mins = (float)width * 5.0 / 24.0 / 60.0; + int widthHour = 12 * width5Mins; + x0 = (width - 24*widthHour)/2; + int barHeight = fontSmall->Height(); + int y = height - barHeight; + tColor col1 = theme.Color(clrTimeline1); + tColor col2 = theme.Color(clrTimeline2); + tColor colCurText = col1; + tColor colCurBack = col2; + int x = x0; + for (int hour = 0; hour < 24; hour++) { + pixmapTimeline->DrawRectangle(cRect(x, y, widthHour, barHeight), colCurBack); + cString hourText = cString::sprintf("%d", hour); + int xDelta = (widthHour - fontSmall->Width(*hourText)) / 2; + pixmapTimeline->DrawText(cPoint(x + xDelta, y), *hourText, colCurText, colCurBack, fontSmall); + x += widthHour; + colCurText = (colCurText==col1)?col2:col1; + colCurBack = (colCurBack==col1)?col2:col1; + } + pixmapTimeline->DrawRectangle(cRect(x0, height-2, width - 2*x0, 2), col2); +} + +void cRecMenuItemTimelineHeader::DrawTimerConflicts(void) { + if (!pixmapTimerConflicts) + return; + pixmapTimerConflicts->Fill(clrTransparent); + int numConflicts = conflicts.size(); + int barHeight = fontSmall->Height(); + int y = height - barHeight; + for (int conflict = 0; conflict < numConflicts; conflict++) { + int confStart = conflicts[conflict]->timeStart - day; + int confStop = conflicts[conflict]->timeStop - day; + int overlapStart = conflicts[conflict]->overlapStart - day; + int overlapStop = conflicts[conflict]->overlapStop - day; + if (confStart < 0) + confStart = 0; + if (confStop > 24*60*60) + confStop = 24 * 60 * 60; + if (overlapStart < 0) + overlapStart = 0; + if (overlapStop > 24*60*60) + overlapStop = 24 * 60 * 60; + confStart = confStart / 60; + confStop = confStop / 60; + overlapStart = overlapStart / 60; + overlapStop = overlapStop / 60; + int xStartConflict = x0 + confStart * width5Mins / 5; + int xStopConflict = x0 + confStop * width5Mins / 5; + int xStartOverlap = x0 + overlapStart * width5Mins / 5; + int xStopOverlap = x0 + overlapStop * width5Mins / 5; + pixmapTimerConflicts->DrawRectangle(cRect(xStartConflict, y, xStopConflict - xStartConflict, barHeight), theme.Color(clrRecMenuTimelineConflict)); + pixmapTimerConflicts->DrawRectangle(cRect(xStartOverlap, y, xStopOverlap - xStartOverlap, barHeight), theme.Color(clrRecMenuTimelineConflictOverlap)); + } +} + +void cRecMenuItemTimelineHeader::Hide(void) { + pixmap->SetLayer(-1); + pixmapTimeline->SetLayer(-1); + pixmapTimerInfo->SetLayer(-1); + if (pixmapTimerConflicts) + pixmapTimerConflicts->SetLayer(-1); +} + +void cRecMenuItemTimelineHeader::Show(void) { + pixmap->SetLayer(4); + pixmapTimeline->SetLayer(5); + pixmapTimerInfo->SetLayer(6); + if (pixmapTimerConflicts) + pixmapTimerConflicts->SetLayer(6); +} + + +// --- cRecMenuItemTimelineTimer ------------------------------------------------------- +cRecMenuItemTimelineTimer::cRecMenuItemTimelineTimer(cTimer *timer, time_t start, time_t stop, std::vector conflictsToday, cRecMenuItemTimelineHeader *header, bool active) { + conflicts = conflictsToday; + defaultBackground = false; + pixmapBack = NULL; + pixmapTimerConflicts = NULL; + this->timer = timer; + this->start = start; + this->stop = stop; + this->header = header; + selectable = true; + this->active = active; + height = geoManager.osdHeight / 16; +} + +cRecMenuItemTimelineTimer::~cRecMenuItemTimelineTimer(void) { + if (pixmapBack) + osdManager.releasePixmap(pixmapBack); + if (pixmapTimerConflicts) + osdManager.releasePixmap(pixmapTimerConflicts); +} + +void cRecMenuItemTimelineTimer::SetPixmaps(void) { + if (!pixmap) { + pixmapBack = osdManager.requestPixmap(4, cRect(x, y, width, height)); + pixmap = osdManager.requestPixmap(5, cRect(x, y, width, height)); + if (conflicts.size() > 0) { + pixmapTimerConflicts = osdManager.requestPixmap(6, cRect(x, y, width, height)); + } + } else { + pixmapBack->SetViewPort(cRect(x, y, width, height)); + pixmap->SetViewPort(cRect(x, y, width, height)); + if (pixmapTimerConflicts) + pixmapTimerConflicts->SetViewPort(cRect(x, y, width, height)); + + } + width5Mins = (float)width * 5.0 / 24.0 / 60.0; + x0 = (width - 24*12*width5Mins)/2; +} + +void cRecMenuItemTimelineTimer::Draw(void) { + DrawBackground(); + if (!timer) { + DrawNoTimerInfo(); + return; + } + if (!drawn) { + pixmap->Fill(clrTransparent); + DrawTimeScale(); + DrawTimerBar(); + DrawTimerConflicts(); + drawn = true; + } +} + +void cRecMenuItemTimelineTimer::DrawBackground(void) { + tColor backgroundColor = (active)?theme.Color(clrRecMenuTimelineActive):theme.Color(clrRecMenuTimelineBack); + pixmapBack->Fill(clrTransparent); + pixmapBack->DrawRectangle(cRect(x0, 0, width - 2 * x0, height), backgroundColor); +} + +void cRecMenuItemTimelineTimer::DrawTimeScale(void) { + int x = x0; + for (int hour = 0; hour < 25; hour++) { + int xModified = (hour%2) ? x - 1 : x ; + pixmap->DrawRectangle(cRect(xModified,0,1,height), theme.Color(clrTimeline2)); + x += width5Mins*12; + } +} + +void cRecMenuItemTimelineTimer::DrawTimerBar(void) { + time_t timerStart = timer->StartTime() - start; + time_t timerStop = timer->StopTime() - start; + if (timerStart < 0) + timerStart = 0; + if (timerStop > 24*60*60) + timerStop = 24 * 60 * 60; + timerStart = timerStart / 60; + timerStop = timerStop / 60; + int xStart = x0 + timerStart * width5Mins / 5; + int xStop = x0 + timerStop * width5Mins / 5; + pixmap->DrawRectangle(cRect(xStart, height / 4, xStop - xStart, height / 2), theme.Color(clrRecMenuTimelineTimer)); +} + +void cRecMenuItemTimelineTimer::DrawTimerConflicts(void) { + if (!pixmapTimerConflicts) + return; + pixmapTimerConflicts->Fill(clrTransparent); + int numConflicts = conflicts.size(); + for (int conflict = 0; conflict < numConflicts; conflict++) { + int confStart = conflicts[conflict]->timeStart - start; + int confStop = conflicts[conflict]->timeStop - start; + int overlapStart = conflicts[conflict]->overlapStart - start; + int overlapStop = conflicts[conflict]->overlapStop - start; + if (confStart < 0) + confStart = 0; + if (confStop > 24*60*60) + confStop = 24 * 60 * 60; + if (overlapStart < 0) + overlapStart = 0; + if (overlapStop > 24*60*60) + overlapStop = 24 * 60 * 60; + confStart = confStart / 60; + confStop = confStop / 60; + overlapStart = overlapStart / 60; + overlapStop = overlapStop / 60; + int xStartConflict = x0 + confStart * width5Mins / 5; + int xStopConflict = x0 + confStop * width5Mins / 5; + int xStartOverlap = x0 + overlapStart * width5Mins / 5; + int xStopOverlap = x0 + overlapStop * width5Mins / 5; + pixmapTimerConflicts->DrawRectangle(cRect(xStartConflict, 0, xStopConflict - xStartConflict, height), theme.Color(clrRecMenuTimelineConflict)); + pixmapTimerConflicts->DrawRectangle(cRect(xStartOverlap, 0, xStopOverlap - xStartOverlap, height), theme.Color(clrRecMenuTimelineConflictOverlap)); + } +} + +void cRecMenuItemTimelineTimer::DrawNoTimerInfo(void) { + pixmap->Fill(clrTransparent); + cString noTimersText = tr("No Timers active"); + int widthText = font->Width(*noTimersText); + int x = (width - widthText) / 2; + int y = (height - font->Height()) / 2; + pixmap->DrawText(cPoint(x, y), *noTimersText, colorText, clrTransparent, font); +} + +void cRecMenuItemTimelineTimer::setActive(void) { + active = true; + header->SetCurrentTimer(timer); + header->RefreshTimerDisplay(); +} + +void cRecMenuItemTimelineTimer::setInactive(void) { + active = false; + header->UnsetCurrentTimer(); + header->RefreshTimerDisplay(); +} + +void cRecMenuItemTimelineTimer::Hide(void) { + pixmap->SetLayer(-1); + pixmapBack->SetLayer(-1); + if (pixmapTimerConflicts) + pixmapTimerConflicts->SetLayer(-1); +} + +void cRecMenuItemTimelineTimer::Show(void) { + pixmap->SetLayer(5); + pixmapBack->SetLayer(4); + if (pixmapTimerConflicts) + pixmapTimerConflicts->SetLayer(6); +} + +const cEvent *cRecMenuItemTimelineTimer::GetEventValue(void) { + return timer->Event(); +} + +eRecMenuState cRecMenuItemTimelineTimer::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kOk: + return rmsTimelineInfo; + default: + break; + } + return rmsNotConsumed; +} diff --git a/recmenuitem.h b/recmenuitem.h index 8d8ad95..b0d1db9 100644 --- a/recmenuitem.h +++ b/recmenuitem.h @@ -6,6 +6,7 @@ #include #include #include "styledpixmap.h" +#include "timerconflict.h" enum eRecMenuState { rmsConsumed, @@ -54,6 +55,8 @@ enum eRecMenuState { rmsTimerConflicts, rmsTimerConflictIgnoreReruns, rmsTimerConflictRecordRerun, + rmsTimeline, + rmsTimelineInfo, rmsDisabled, }; @@ -68,6 +71,7 @@ protected: int width, height; bool selectable; bool active; + bool defaultBackground; bool drawn; eRecMenuState action; tColor colorText; @@ -82,8 +86,8 @@ public: virtual int GetHeight(void) { return height; }; virtual int GetWidth(void) { return 0; }; virtual void CalculateHeight(int textWidth) {}; - void setActive(void) { this->active = true; } - void setInactive(void) { this->active = false; } + virtual void setActive(void) { this->active = true; } + virtual void setInactive(void) { this->active = false; } bool isSelectable(void) { return selectable; } bool isActive(void) { return active; } virtual void setBackground(void); @@ -476,4 +480,62 @@ public: void Draw(void); }; +// --- cRecMenuItemTimelineHeader ------------------------------------------------------- +class cRecMenuItemTimelineHeader : public cRecMenuItem { +private: + time_t day; + cTimer *timer; + std::vector conflicts; + cPixmap *pixmapTimeline; + cPixmap *pixmapTimerInfo; + cPixmap *pixmapTimerConflicts; + int width5Mins; + int x0; + bool timelineDrawn; + void DrawTimeline(void); + void DrawTimerConflicts(void); + void DrawCurrentTimer(void); +public: + cRecMenuItemTimelineHeader(time_t day, std::vector conflictsToday); + virtual ~cRecMenuItemTimelineHeader(void); + void SetDay(time_t day) { this->day = day; }; + void SetPixmaps(void); + void SetCurrentTimer(cTimer *timer) { this->timer = timer; }; + void UnsetCurrentTimer(void) { timer = NULL; }; + void RefreshTimerDisplay(void); + void Hide(void); + void Show(void); + void Draw(void); +}; + +// --- cRecMenuItemTimelineTimer ------------------------------------------------------- +class cRecMenuItemTimelineTimer : public cRecMenuItem { +private: + cTimer *timer; + std::vector conflicts; + cPixmap *pixmapBack; + cPixmap *pixmapTimerConflicts; + cRecMenuItemTimelineHeader *header; + int x0; + int width5Mins; + time_t start; + time_t stop; + void DrawBackground(void); + void DrawTimerBar(void); + void DrawTimeScale(void); + void DrawTimerConflicts(void); + void DrawNoTimerInfo(void); +public: + cRecMenuItemTimelineTimer(cTimer *timer, time_t start, time_t stop, std::vector conflictsToday, cRecMenuItemTimelineHeader *header, bool active); + virtual ~cRecMenuItemTimelineTimer(void); + void setActive(void); + void setInactive(void); + void SetPixmaps(void); + void Hide(void); + void Show(void); + void Draw(void); + const cEvent *GetEventValue(void); + eRecMenuState ProcessKey(eKeys Key); +}; + #endif //__TVGUIDE_RECMENUITEM_H \ No newline at end of file diff --git a/recmenumanager.c b/recmenumanager.c index 5162478..d02db9c 100644 --- a/recmenumanager.c +++ b/recmenumanager.c @@ -138,6 +138,7 @@ eOSState cRecMenuManager::StateMachine(eRecMenuState nextState) { detailView->drawHeader(); detailView->drawContent(); detailView->drawScrollbar(); + detailView->Start(); detailViewActive = true; } } @@ -426,6 +427,7 @@ eOSState cRecMenuManager::StateMachine(eRecMenuState nextState) { detailView->drawHeader(); detailView->drawContent(); detailView->drawScrollbar(); + detailView->Start(); detailViewActive = true; } break;} @@ -522,6 +524,32 @@ eOSState cRecMenuManager::StateMachine(eRecMenuState nextState) { activeMenu->Display(); } break; } + /* + * --------- TIMELINE --------------------------------- + */ + case rmsTimeline: { + if (timerConflicts) { + delete timerConflicts; + } + timerConflicts = recManager->CheckTimerConflict(); + delete activeMenu; + activeMenu = new cRecMenuTimeline(timerConflicts); + activeMenu->Display(); + break; } + case rmsTimelineInfo: { + const cEvent *ev = activeMenu->GetEventValue(activeMenu->GetActive(true)); + if (ev) { + activeMenu->Hide(); + detailView = new cDetailView(ev); + detailView->setContent(); + detailView->drawHeader(); + detailView->drawContent(); + detailView->drawScrollbar(); + detailView->Start(); + detailViewActive = true; + } + break;} + /* * --------- COMMON --------------------------------- */ diff --git a/recmenus.c b/recmenus.c index 9ac7c59..2d22f2c 100644 --- a/recmenus.c +++ b/recmenus.c @@ -28,10 +28,12 @@ cRecMenuMain::cRecMenuMain(bool epgSearchAvailable, bool timerActive, bool switc if (epgSearchAvailable) { AddMenuItem(new cRecMenuItemButton(tr("Search"), rmsSearch, false)); } - AddMenuItem(new cRecMenuItemButton(tr("Search in Recordings"), rmsRecordingSearch, false)); + + AddMenuItem(new cRecMenuItemButton(tr("Timer Timeline"), rmsTimeline, false)); if (epgSearchAvailable) { AddMenuItem(new cRecMenuItemButton(tr("Check for Timer Conflicts"), rmsTimerConflicts, false)); } + AddMenuItem(new cRecMenuItemButton(tr("Search in Recordings"), rmsRecordingSearch, false)); int menuWidth = CalculateOptimalWidth() + 4 * border; SetWidthPixel(menuWidth); @@ -935,4 +937,140 @@ cRecMenuRecordingSearchNotFound::cRecMenuRecordingSearchNotFound(cString searchS CalculateHeight(); CreatePixmap(); Arrange(); +} + +// --- cRecMenuTimeline --------------------------------------------------------- +cRecMenuTimeline::cRecMenuTimeline(cTVGuideTimerConflicts *timerConflicts) { + this->timerConflicts = timerConflicts; + SetStartStop(); + conflictsToday = timerConflicts->GetConflictsBetween(timeStart, timeStop); + GetTimersForDay(); + SetWidthPercent(95); + header = new cRecMenuItemTimelineHeader(timeStart, conflictsToday); + SetHeader(header); + cRecMenuItem *footer = new cRecMenuItemButton(tr("Close"), rmsClose, false, true); + SetFooter(footer); + SetTimers(); +} + +void cRecMenuTimeline::SetStartStop(void) { + time_t now = time(0); + tm *timeStruct = localtime(&now); + timeStart = now - timeStruct->tm_hour * 3600 - timeStruct->tm_min * 60 - timeStruct->tm_sec; + today = timeStart; + timeStop = timeStart + 24*3600 - 1; +} + + +void cRecMenuTimeline::GetTimersForDay(void) { + timersToday.clear(); + for (cTimer *t = Timers.First(); t; t = Timers.Next(t)) { + if (((t->StartTime() > timeStart) && (t->StartTime() <= timeStop)) || ((t->StopTime() > timeStart) && (t->StopTime() <= timeStop))) { + timersToday.push_back(t); + } + } + numTimersToday = timersToday.size(); +} + +void cRecMenuTimeline::SetTimers(void) { + ClearMenuItems(); + if (numTimersToday == 0) { + AddMenuItem(new cRecMenuItemTimelineTimer(NULL, 0, 0, conflictsToday, header, false)); + header->UnsetCurrentTimer(); + footer->setActive(); + } else { + for (int i=0; isetActive(); + AddMenuItemScroll(item); + if (!CheckHeight()) + break; + } + footer->setInactive(); + } + CalculateHeight(); + CreatePixmap(); + Arrange(); +} + +void cRecMenuTimeline::PrevDay(void) { + if ((timeStart - 3600*24) < today) + return; + timeStart -= 3600*24; + timeStop -= 3600*24; + conflictsToday = timerConflicts->GetConflictsBetween(timeStart, timeStop); + SetWidthPercent(95); + header->SetDay(timeStart); + header->UnsetCurrentTimer(); + header->RefreshTimerDisplay(); + GetTimersForDay(); + SetTimers(); + Display(); +} + +void cRecMenuTimeline::NextDay(void) { + timeStart += 3600*24; + timeStop += 3600*24; + conflictsToday = timerConflicts->GetConflictsBetween(timeStart, timeStop); + SetWidthPercent(95); + header->SetDay(timeStart); + header->UnsetCurrentTimer(); + header->RefreshTimerDisplay(); + GetTimersForDay(); + SetTimers(); + Display(); +} + +cRecMenuItem *cRecMenuTimeline::GetMenuItem(int number) { + if (number < 0) + return NULL; + if (number >= numTimersToday) + return NULL; + return new cRecMenuItemTimelineTimer(timersToday[number], timeStart, timeStop, conflictsToday, header, false); +} + +int cRecMenuTimeline::GetTotalNumMenuItems(void) { + return numTimersToday; +} + +void cRecMenuTimeline::ClearMenuItems(void) { + if (pixmap) + osdManager.releasePixmap(pixmap); + pixmap = NULL; + menuItems.Clear(); + if (pixmapScrollBar) + osdManager.releasePixmap(pixmapScrollBar); + if (imgScrollBar) + delete imgScrollBar; + header->UnsetCurrentTimer(); + height = 2*border + headerHeight + footerHeight; + scrollHeight = 0; + scrollItemHeight = 0; + scrollable = false; + pixmapScrollBar = NULL; + imgScrollBar = NULL; + startIndex = 0; + stopIndex = 0; + numItems = 0; +} + +eRecMenuState cRecMenuTimeline::ProcessKey(eKeys Key) { + eRecMenuState state = rmsContinue; + switch (Key & ~k_Repeat) { + case kLeft: + PrevDay(); + state = rmsConsumed; + break; + case kRight: + NextDay(); + state = rmsConsumed; + break; + default: + break; + } + if (state != rmsConsumed) { + state = cRecMenu::ProcessKey(Key); + } + return state; } \ No newline at end of file diff --git a/recmenus.h b/recmenus.h index 5b7c485..09d9d8c 100644 --- a/recmenus.h +++ b/recmenus.h @@ -267,7 +267,6 @@ public: }; // --- cRecMenuRecordingSearchResults --------------------------------------------------------- - class cRecMenuRecordingSearchResults: public cRecMenu { private: cRecording **searchResults; @@ -288,5 +287,30 @@ public: virtual ~cRecMenuRecordingSearchNotFound(void) {}; }; +// --- cRecMenuTimeline --------------------------------------------------------- +class cRecMenuTimeline: public cRecMenu { +private: + std::vector timersToday; + int numTimersToday; + time_t today; + time_t timeStart; + time_t timeStop; + cTVGuideTimerConflicts *timerConflicts; + std::vector conflictsToday; + cRecMenuItemTimelineHeader *header; + void SetStartStop(void); + void GetTimersForDay(void); + void SetTimers(void); + void PrevDay(void); + void NextDay(void); + void ClearMenuItems(void); +public: + cRecMenuTimeline(cTVGuideTimerConflicts *timerConflicts); + cRecMenuItem *GetMenuItem(int number); + int GetTotalNumMenuItems(void); + virtual ~cRecMenuTimeline(void) { + }; + eRecMenuState ProcessKey(eKeys Key); +}; #endif //__TVGUIDE_RECMENUS_H \ No newline at end of file diff --git a/themes/tvguide-blue.theme b/themes/tvguide-blue.theme index 88827ba..5fa4b9c 100644 --- a/themes/tvguide-blue.theme +++ b/themes/tvguide-blue.theme @@ -42,3 +42,8 @@ clrRecMenuTextActiveBack = FF404749 clrRecMenuKeyboardBack = FF000000 clrRecMenuKeyboardBorder = FF003DF5 clrRecMenuKeyboardHigh = 40BB0000 +clrRecMenuTimelineTimer = B012273f +clrRecMenuTimelineBack = FF828282 +clrRecMenuTimelineActive = FF3F3F3F +clrRecMenuTimelineConflict = 30FF0000 +clrRecMenuTimelineConflictOverlap = 90FF0000 \ No newline at end of file diff --git a/themes/tvguide-darkblue.theme b/themes/tvguide-darkblue.theme index 039323b..8340587 100644 --- a/themes/tvguide-darkblue.theme +++ b/themes/tvguide-darkblue.theme @@ -42,3 +42,8 @@ clrRecMenuTextActiveBack = FF404749 clrRecMenuKeyboardBack = FF000000 clrRecMenuKeyboardBorder = FFFFFFFF clrRecMenuKeyboardHigh = 40BB0000 +clrRecMenuTimelineTimer = B012273f +clrRecMenuTimelineBack = FF828282 +clrRecMenuTimelineActive = FF3F3F3F +clrRecMenuTimelineConflict = 30FF0000 +clrRecMenuTimelineConflictOverlap = 90FF0000 \ No newline at end of file diff --git a/themes/tvguide-darkred.theme b/themes/tvguide-darkred.theme index 84d5af8..9e9a3b4 100644 --- a/themes/tvguide-darkred.theme +++ b/themes/tvguide-darkred.theme @@ -42,3 +42,8 @@ clrRecMenuTextActiveBack = FF404749 clrRecMenuKeyboardBack = FF000000 clrRecMenuKeyboardBorder = FF660000 clrRecMenuKeyboardHigh = 40BB0000 +clrRecMenuTimelineTimer = B0660000 +clrRecMenuTimelineBack = FF828282 +clrRecMenuTimelineActive = FF3F3F3F +clrRecMenuTimelineConflict = 30FF0000 +clrRecMenuTimelineConflictOverlap = 90FF0000 \ No newline at end of file diff --git a/themes/tvguide-darkredNG.theme b/themes/tvguide-darkredNG.theme index 2b9729b..097710d 100644 --- a/themes/tvguide-darkredNG.theme +++ b/themes/tvguide-darkredNG.theme @@ -33,7 +33,7 @@ clrButtonBlend = DD000000 clrRecMenuBackground = AA000000 clrRecMenuTimerConflictBackground = FFCCCCCC clrRecMenuTimerConflictBar = FF222222 -clrRecMenuTimerConflictOverlap = AAFF0000 +clrRecMenuTimerConflictOverlap = 90FF0000 clrRecMenuDayActive = FF00FF00 clrRecMenuDayInactive = FFFF0000 clrRecMenuDayHighlight = 44FFFFFF @@ -42,3 +42,8 @@ clrRecMenuTextActiveBack = FF404749 clrRecMenuKeyboardBack = FF000000 clrRecMenuKeyboardBorder = FF660000 clrRecMenuKeyboardHigh = 40BB0000 +clrRecMenuTimelineTimer = B0660000 +clrRecMenuTimelineBack = FF828282 +clrRecMenuTimelineActive = FF3F3F3F +clrRecMenuTimelineConflict = 30FF0000 +clrRecMenuTimelineConflictOverlap = 90FF0000 \ No newline at end of file diff --git a/themes/tvguide-default.theme b/themes/tvguide-default.theme index 782cf21..5fcaacc 100644 --- a/themes/tvguide-default.theme +++ b/themes/tvguide-default.theme @@ -33,7 +33,7 @@ clrButtonBlend = DD000000 clrRecMenuBackground = AA000000 clrRecMenuTimerConflictBackground = FFCCCCCC clrRecMenuTimerConflictBar = FF222222 -clrRecMenuTimerConflictOverlap = AAFF0000 +clrRecMenuTimerConflictOverlap = A0FF0000 clrRecMenuDayActive = FF00FF00 clrRecMenuDayInactive = FFFF0000 clrRecMenuDayHighlight = 44FFFFFF @@ -41,4 +41,9 @@ clrRecMenuTextBack = FF000000 clrRecMenuTextActiveBack = FF404749 clrRecMenuKeyboardBack = FF000000 clrRecMenuKeyboardBorder = FFFFFFFF -clrRecMenuKeyboardHigh = 40BB0000 \ No newline at end of file +clrRecMenuKeyboardHigh = 40BB0000 +clrRecMenuTimelineTimer = B012273f +clrRecMenuTimelineBack = FF828282 +clrRecMenuTimelineActive = FF3F3F3F +clrRecMenuTimelineConflict = 30FF0000 +clrRecMenuTimelineConflictOverlap = 90FF0000 diff --git a/themes/tvguide-green.theme b/themes/tvguide-green.theme index 7a94397..e113882 100644 --- a/themes/tvguide-green.theme +++ b/themes/tvguide-green.theme @@ -42,3 +42,8 @@ clrRecMenuTextActiveBack = FF404749 clrRecMenuKeyboardBack = FF000000 clrRecMenuKeyboardBorder = EE006600 clrRecMenuKeyboardHigh = 40BB0000 +clrRecMenuTimelineTimer = B0003D00 +clrRecMenuTimelineBack = FF828282 +clrRecMenuTimelineActive = FF3F3F3F +clrRecMenuTimelineConflict = 30FF0000 +clrRecMenuTimelineConflictOverlap = 90FF0000 \ No newline at end of file diff --git a/themes/tvguide-iceblue.theme b/themes/tvguide-iceblue.theme index 7da7143..2b36c26 100644 --- a/themes/tvguide-iceblue.theme +++ b/themes/tvguide-iceblue.theme @@ -40,3 +40,8 @@ clrRecMenuKeyboardHigh = 55FFFFFF clrButtonRedKeyboard = FFBB0000 clrButtonGreenKeyboard = FF00BB00 clrButtonYellowKeyboard = FFBBBB00 +clrRecMenuTimelineTimer = B012273f +clrRecMenuTimelineBack = FF828282 +clrRecMenuTimelineActive = FF3F3F3F +clrRecMenuTimelineConflict = 30FF0000 +clrRecMenuTimelineConflictOverlap = 90FF0000 \ No newline at end of file diff --git a/themes/tvguide-keepitsimple.theme b/themes/tvguide-keepitsimple.theme index 1a55167..7dec01f 100644 --- a/themes/tvguide-keepitsimple.theme +++ b/themes/tvguide-keepitsimple.theme @@ -37,4 +37,9 @@ clrRecMenuTextBack = FF000000 clrRecMenuTextActiveBack = FF404749 clrRecMenuKeyboardBack = FF000000 clrRecMenuKeyboardBorder = BB555555 -clrRecMenuKeyboardHigh = 40BB0000 \ No newline at end of file +clrRecMenuKeyboardHigh = 40BB0000 +clrRecMenuTimelineTimer = B012273f +clrRecMenuTimelineBack = FF828282 +clrRecMenuTimelineActive = FF3F3F3F +clrRecMenuTimelineConflict = 30FF0000 +clrRecMenuTimelineConflictOverlap = 90FF0000 \ No newline at end of file diff --git a/timerconflict.c b/timerconflict.c index 3488487..e2a1fee 100644 --- a/timerconflict.c +++ b/timerconflict.c @@ -165,3 +165,13 @@ cTVGuideTimerConflict *cTVGuideTimerConflicts::GetConflict(int conflictIndex) { return NULL; return conflicts[conflictIndex]; } + +std::vector cTVGuideTimerConflicts::GetConflictsBetween(time_t start, time_t stop) { + std::vector conflictsFound; + for (int i=0; i < numConflicts; i++) { + if ((conflicts[i]->timeStart > start) && (conflicts[i]->timeStart < stop)|| + (conflicts[i]->timeStop > start) && (conflicts[i]->timeStop < stop)) + conflictsFound.push_back(conflicts[i]); + } + return conflictsFound; +} \ No newline at end of file diff --git a/timerconflict.h b/timerconflict.h index dc7c98f..d3def89 100644 --- a/timerconflict.h +++ b/timerconflict.h @@ -3,8 +3,8 @@ class cTVGuideTimerConflict { public: - cTVGuideTimerConflict(void); - virtual ~cTVGuideTimerConflict(void); + cTVGuideTimerConflict(void); + virtual ~cTVGuideTimerConflict(void); time_t time; time_t timeStart; time_t timeStop; @@ -18,20 +18,21 @@ public: class cTVGuideTimerConflicts { private: - std::vector conflicts; - int numConflicts; - int currentConflict; + std::vector conflicts; + int numConflicts; + int currentConflict; public: - cTVGuideTimerConflicts(void); - virtual ~cTVGuideTimerConflicts(void); - void AddConflict(std::string epgSearchConflictLine); - void CalculateConflicts(void); - int NumConflicts(void) {return numConflicts; }; - void SetCurrentConflict(int current) { currentConflict = current; }; - cTVGuideTimerConflict *GetCurrentConflict(void); - int GetCurrentConflictTimerID(int timerIndex); + cTVGuideTimerConflicts(void); + virtual ~cTVGuideTimerConflicts(void); + void AddConflict(std::string epgSearchConflictLine); + void CalculateConflicts(void); + int NumConflicts(void) {return numConflicts; }; + void SetCurrentConflict(int current) { currentConflict = current; }; + cTVGuideTimerConflict *GetCurrentConflict(void); + int GetCurrentConflictTimerID(int timerIndex); int GetCorrespondingConflict(int timerID); cTVGuideTimerConflict *GetConflict(int conflictIndex); + std::vector GetConflictsBetween(time_t start, time_t stop); }; #endif //__TVGUIDE_RECMMANAGER_H \ No newline at end of file